mirror of https://github.com/apache/nifi.git
NIFI-4436:
- Adding support to save a version of a flow based on a selected Process Group. - Adding support for revert changes back to the most recent version. - Adding support to disconnect from version control. - Moving the version control information out of the entity objects and into the dto's. - Fixing checkstyle issues. NIFI-4502: - Updating the UI to allow for the user to register registry clients. - Updating the version control menu item names.
This commit is contained in:
parent
6a58d780d7
commit
7a0a900a0f
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* Details about a bucket in a registry.
|
||||
*/
|
||||
@XmlType(name = "bucket")
|
||||
public class BucketDTO {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String description;
|
||||
private Long created;
|
||||
|
||||
@ApiModelProperty("The bucket identifier")
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The bucket name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The bucket description")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The created timestamp of this bucket")
|
||||
public Long getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Long created) {
|
||||
this.created = created;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ public class ControllerConfigurationDTO {
|
|||
|
||||
private Integer maxTimerDrivenThreadCount;
|
||||
private Integer maxEventDrivenThreadCount;
|
||||
private String registryUrl;
|
||||
|
||||
/**
|
||||
* @return maximum number of timer driven threads this NiFi has available
|
||||
|
|
|
@ -32,6 +32,7 @@ public class FlowConfigurationDTO {
|
|||
private Boolean supportsManagedAuthorizer;
|
||||
private Boolean supportsConfigurableAuthorizer;
|
||||
private Boolean supportsConfigurableUsersAndGroups;
|
||||
private Boolean supportsFlowVersioning;
|
||||
private Long autoRefreshIntervalSeconds;
|
||||
|
||||
private Date currentTime;
|
||||
|
@ -127,4 +128,18 @@ public class FlowConfigurationDTO {
|
|||
public void setTimeOffset(Integer timeOffset) {
|
||||
this.timeOffset = timeOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether this NiFi is configured for support flow versioning
|
||||
*/
|
||||
@ApiModelProperty(
|
||||
value = "Whether this NiFi supports flow versioning."
|
||||
)
|
||||
public Boolean getSupportsFlowVersioning() {
|
||||
return supportsFlowVersioning;
|
||||
}
|
||||
|
||||
public void setSupportsFlowVersioning(Boolean supportsFlowVersioning) {
|
||||
this.supportsFlowVersioning = supportsFlowVersioning;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
/**
|
||||
* Details about a configured registry.
|
||||
*/
|
||||
@XmlType(name = "registry")
|
||||
public class RegistryDTO {
|
||||
|
||||
private String id;
|
||||
private String name;
|
||||
private String description;
|
||||
private String uri;
|
||||
|
||||
@ApiModelProperty("The registry identifier")
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The registry name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The registry description")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The registry URI")
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ public class VersionedFlowDTO {
|
|||
private String flowId;
|
||||
private String flowName;
|
||||
private String description;
|
||||
private String comments;
|
||||
|
||||
@ApiModelProperty("The ID of the registry that the flow is tracked to")
|
||||
public String getRegistryId() {
|
||||
|
@ -73,4 +74,13 @@ public class VersionedFlowDTO {
|
|||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@ApiModelProperty("Comments for the changeset")
|
||||
public String getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(String comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.apache.nifi.web.api.dto.flow;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
|
||||
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
@ -28,6 +29,7 @@ public class FlowBreadcrumbDTO {
|
|||
|
||||
private String id;
|
||||
private String name;
|
||||
private VersionControlInformationDTO versionControlInformation;
|
||||
|
||||
/**
|
||||
* The id for this group.
|
||||
|
@ -60,4 +62,18 @@ public class FlowBreadcrumbDTO {
|
|||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the process group version control information or null if not version controlled
|
||||
*/
|
||||
@ApiModelProperty(
|
||||
value = "The process group version control information or null if not version controlled."
|
||||
)
|
||||
public VersionControlInformationDTO getVersionControlInformation() {
|
||||
return versionControlInformation;
|
||||
}
|
||||
|
||||
public void setVersionControlInformation(VersionControlInformationDTO versionControlInformation) {
|
||||
this.versionControlInformation = versionControlInformation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.entity;
|
||||
|
||||
import org.apache.nifi.web.api.dto.BucketDTO;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a BucketDTO.
|
||||
*/
|
||||
@XmlRootElement(name = "bucketEntity")
|
||||
public class BucketEntity extends Entity {
|
||||
|
||||
private BucketDTO bucket;
|
||||
|
||||
|
||||
public BucketDTO getBucket() {
|
||||
return bucket;
|
||||
}
|
||||
|
||||
public void setBucket(BucketDTO bucket) {
|
||||
this.bucket = bucket;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.entity;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a set of BucketEntity's.
|
||||
*/
|
||||
@XmlRootElement(name = "bucketsEntity")
|
||||
public class BucketsEntity extends Entity {
|
||||
|
||||
private Set<BucketEntity> buckets;
|
||||
|
||||
/**
|
||||
* @return collection of BucketEntity's that are being serialized
|
||||
*/
|
||||
public Set<BucketEntity> getBuckets() {
|
||||
return buckets;
|
||||
}
|
||||
|
||||
public void setBuckets(Set<BucketEntity> buckets) {
|
||||
this.buckets = buckets;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.entity;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A serialized representation of this class can be placed in the entity body of a response to the API. This particular entity holds a reference to a set of RegistryEntity's.
|
||||
*/
|
||||
@XmlRootElement(name = "registriesEntity")
|
||||
public class RegistriesEntity extends Entity {
|
||||
|
||||
private Set<RegistryEntity> registries;
|
||||
|
||||
/**
|
||||
* @return collection of LabelEntity's that are being serialized
|
||||
*/
|
||||
public Set<RegistryEntity> getRegistries() {
|
||||
return registries;
|
||||
}
|
||||
|
||||
public void setRegistries(Set<RegistryEntity> registries) {
|
||||
this.registries = registries;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.nifi.web.api.entity;
|
||||
|
||||
import org.apache.nifi.web.api.dto.RegistryDTO;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* A serialized representation of this class can be placed in the entity body of a request or response to or from the API. This particular entity holds a reference to a RegistryDTO.
|
||||
*/
|
||||
@XmlRootElement(name = "registryEntity")
|
||||
public class RegistryEntity extends ComponentEntity {
|
||||
|
||||
private RegistryDTO component;
|
||||
|
||||
|
||||
public RegistryDTO getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public void setComponent(RegistryDTO component) {
|
||||
this.component = component;
|
||||
}
|
||||
}
|
|
@ -25,16 +25,16 @@ import javax.xml.bind.annotation.XmlRootElement;
|
|||
|
||||
@XmlRootElement(name = "versionControlInformationEntity")
|
||||
public class VersionControlInformationEntity extends Entity {
|
||||
private VersionControlInformationDTO versionControlDto;
|
||||
private VersionControlInformationDTO versionControlInformation;
|
||||
private RevisionDTO processGroupRevision;
|
||||
|
||||
@ApiModelProperty("The Version Control information")
|
||||
public VersionControlInformationDTO getVersionControlInformation() {
|
||||
return versionControlDto;
|
||||
return versionControlInformation;
|
||||
}
|
||||
|
||||
public void setVersionControlInformation(VersionControlInformationDTO versionControlDto) {
|
||||
this.versionControlDto = versionControlDto;
|
||||
this.versionControlInformation = versionControlDto;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The Revision for the Process Group")
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.groups;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -42,7 +41,6 @@ import org.apache.nifi.flowfile.FlowFile;
|
|||
import org.apache.nifi.processor.Processor;
|
||||
import org.apache.nifi.registry.ComponentVariableRegistry;
|
||||
import org.apache.nifi.registry.flow.FlowRegistryClient;
|
||||
import org.apache.nifi.registry.flow.UnknownResourceException;
|
||||
import org.apache.nifi.registry.flow.VersionControlInformation;
|
||||
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
|
||||
import org.apache.nifi.remote.RemoteGroupPort;
|
||||
|
@ -940,6 +938,11 @@ public interface ProcessGroup extends ComponentAuthorizable, Positionable, Versi
|
|||
*/
|
||||
void setVersionControlInformation(VersionControlInformation versionControlInformation, Map<String, String> versionedComponentIds);
|
||||
|
||||
/**
|
||||
* Disconnects this Process Group from version control. If not currently under version control, this method does nothing.
|
||||
*/
|
||||
void disconnectVersionControl();
|
||||
|
||||
/**
|
||||
* Synchronizes the Process Group with the given Flow Registry, determining whether or not the local flow
|
||||
* is up to date with the newest version of the flow in the Registry and whether or not the local flow has been
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
|
||||
package org.apache.nifi.registry.flow;
|
||||
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.registry.bucket.Bucket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
public interface FlowRegistry {
|
||||
|
||||
|
@ -26,6 +30,19 @@ public interface FlowRegistry {
|
|||
*/
|
||||
String getURL();
|
||||
|
||||
/**
|
||||
* @return the name of the Flow Registry
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the buckets for the specified user.
|
||||
*
|
||||
* @param user current user
|
||||
* @return buckets for this user
|
||||
*/
|
||||
Set<Bucket> getBuckets(NiFiUser user) throws IOException;
|
||||
|
||||
/**
|
||||
* Registers the given Versioned Flow with the Flow Registry
|
||||
*
|
||||
|
|
|
@ -160,6 +160,11 @@
|
|||
<groupId>org.apache.nifi.registry</groupId>
|
||||
<artifactId>nifi-registry-flow-diff</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
|
|
|
@ -16,30 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.groups;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
@ -133,6 +109,30 @@ import org.apache.nifi.web.api.dto.TemplateDTO;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public final class StandardProcessGroup implements ProcessGroup {
|
||||
|
||||
private final String id;
|
||||
|
@ -2835,6 +2835,16 @@ public final class StandardProcessGroup implements ProcessGroup {
|
|||
}
|
||||
}
|
||||
|
||||
public void disconnectVersionControl() {
|
||||
writeLock.lock();
|
||||
try {
|
||||
// TODO remove version component ids from each component (until another versioned PG is encountered)
|
||||
this.versionControlInfo.set(null);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVersionedComponentIds(final ProcessGroup processGroup, final Map<String, String> versionedComponentIds) {
|
||||
if (versionedComponentIds == null || versionedComponentIds.isEmpty()) {
|
||||
return;
|
||||
|
|
|
@ -17,6 +17,15 @@
|
|||
|
||||
package org.apache.nifi.registry.flow;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.registry.bucket.Bucket;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -35,13 +44,6 @@ import java.util.SortedSet;
|
|||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.codehaus.jackson.JsonFactory;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.map.DeserializationConfig;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.util.DefaultPrettyPrinter;
|
||||
|
||||
/**
|
||||
* A simple file-based implementation of a Flow Registry Client. Rather than interacting
|
||||
* with an actual Flow Registry, this implementation simply reads flows from disk and writes
|
||||
|
@ -113,6 +115,35 @@ public class FileBasedFlowRegistryClient implements FlowRegistryClient, FlowRegi
|
|||
return directory.toURI().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Local Registry";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Bucket> getBuckets(NiFiUser user) throws IOException {
|
||||
final Set<Bucket> buckets = new HashSet<>();
|
||||
|
||||
final File[] bucketDirs = directory.listFiles();
|
||||
if (bucketDirs == null) {
|
||||
throw new IOException("Could not get listing of directory " + directory);
|
||||
}
|
||||
|
||||
for (final File bucketDirectory : bucketDirs) {
|
||||
final String bucketIdentifier = bucketDirectory.getName();
|
||||
final long creation = bucketDirectory.lastModified();
|
||||
|
||||
final Bucket bucket = new Bucket();
|
||||
bucket.setIdentifier(bucketIdentifier);
|
||||
bucket.setName("Bucket '" + bucketIdentifier + "'");
|
||||
bucket.setCreatedTimestamp(creation);
|
||||
|
||||
buckets.add(bucket);
|
||||
}
|
||||
|
||||
return buckets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized VersionedFlow registerVersionedFlow(final VersionedFlow flow) throws IOException, UnknownResourceException {
|
||||
Objects.requireNonNull(flow);
|
||||
|
@ -303,9 +334,9 @@ public class FileBasedFlowRegistryClient implements FlowRegistryClient, FlowRegi
|
|||
final File contentsFile = new File(versionDir, "flow.xml");
|
||||
|
||||
final VersionedProcessGroup processGroup;
|
||||
try (final JsonParser parser = jsonFactory.createJsonParser(contentsFile)) {
|
||||
try (final JsonParser parser = jsonFactory.createParser(contentsFile)) {
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
parser.setCodec(mapper);
|
||||
processGroup = parser.readValueAs(VersionedProcessGroup.class);
|
||||
|
|
|
@ -17,16 +17,6 @@
|
|||
|
||||
package org.apache.nifi.controller.service.mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.apache.nifi.authorization.Resource;
|
||||
import org.apache.nifi.authorization.resource.Authorizable;
|
||||
import org.apache.nifi.connectable.Connectable;
|
||||
|
@ -52,6 +42,16 @@ import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
|
|||
import org.apache.nifi.registry.variable.MutableVariableRegistry;
|
||||
import org.apache.nifi.remote.RemoteGroupPort;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class MockProcessGroup implements ProcessGroup {
|
||||
private final Map<String, ControllerServiceNode> serviceMap = new HashMap<>();
|
||||
private final Map<String, ProcessorNode> processorMap = new HashMap<>();
|
||||
|
@ -661,4 +661,9 @@ public class MockProcessGroup implements ProcessGroup {
|
|||
public void setVersionControlInformation(VersionControlInformation versionControlInformation, Map<String, String> versionedComponentIds) {
|
||||
this.versionControlInfo = versionControlInformation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnectVersionControl() {
|
||||
this.versionControlInfo = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.nifi.authorization.AuthorizeAccess;
|
||||
import org.apache.nifi.authorization.RequestAction;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
|
@ -31,7 +23,6 @@ import org.apache.nifi.controller.ScheduledState;
|
|||
import org.apache.nifi.controller.repository.claim.ContentDirection;
|
||||
import org.apache.nifi.controller.service.ControllerServiceState;
|
||||
import org.apache.nifi.groups.ProcessGroup;
|
||||
import org.apache.nifi.registry.flow.FlowRegistryClient;
|
||||
import org.apache.nifi.registry.flow.UnknownResourceException;
|
||||
import org.apache.nifi.registry.flow.VersionedFlow;
|
||||
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
|
||||
|
@ -62,6 +53,7 @@ import org.apache.nifi.web.api.dto.PortDTO;
|
|||
import org.apache.nifi.web.api.dto.ProcessGroupDTO;
|
||||
import org.apache.nifi.web.api.dto.ProcessorDTO;
|
||||
import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
|
||||
import org.apache.nifi.web.api.dto.RegistryDTO;
|
||||
import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
|
||||
import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO;
|
||||
import org.apache.nifi.web.api.dto.ReportingTaskDTO;
|
||||
|
@ -104,6 +96,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
|
|||
import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.RegistryEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
|
||||
|
@ -119,6 +112,14 @@ import org.apache.nifi.web.api.entity.VersionControlComponentMappingEntity;
|
|||
import org.apache.nifi.web.api.entity.VersionControlInformationEntity;
|
||||
import org.apache.nifi.web.api.entity.VersionedFlowEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Defines the NiFiServiceFacade interface.
|
||||
*/
|
||||
|
@ -1320,6 +1321,14 @@ public interface NiFiServiceFacade {
|
|||
VersionControlInformationEntity setVersionControlInformation(Revision processGroupRevision, String processGroupId, VersionControlInformationDTO versionControlInfo,
|
||||
Map<String, String> versionedComponentMapping);
|
||||
|
||||
/**
|
||||
* Disconnects the specified Process Group from version control.
|
||||
*
|
||||
* @param revision revision
|
||||
* @param processGroupId group id
|
||||
* @return version control information prior to disconnecting
|
||||
*/
|
||||
VersionControlInformationEntity deleteVersionControl(final Revision revision, final String processGroupId);
|
||||
|
||||
/**
|
||||
* Retrieves the Versioned Flow Snapshot for the coordinates provided by the given Version Control Information DTO
|
||||
|
@ -1381,8 +1390,6 @@ public interface NiFiServiceFacade {
|
|||
ProcessGroupEntity updateProcessGroup(NiFiUser user, Revision revision, String groupId, VersionControlInformationDTO versionControlInfo, VersionedFlowSnapshot snapshot, String componentIdSeed,
|
||||
boolean verifyNotModified);
|
||||
|
||||
void setFlowRegistryClient(FlowRegistryClient flowRegistryClient);
|
||||
|
||||
// ----------------------------------------
|
||||
// Component state methods
|
||||
// ----------------------------------------
|
||||
|
@ -1828,6 +1835,52 @@ public interface NiFiServiceFacade {
|
|||
*/
|
||||
void verifyDeleteReportingTask(String reportingTaskId);
|
||||
|
||||
// ----------------------------------------
|
||||
// Registry methods
|
||||
// ----------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a registry.
|
||||
*
|
||||
* @param revision revision
|
||||
* @param registryDTO The registry DTO
|
||||
* @return The reporting task DTO
|
||||
*/
|
||||
RegistryEntity createRegistry(Revision revision, RegistryDTO registryDTO);
|
||||
|
||||
/**
|
||||
* Gets a registry with the specified id.
|
||||
*
|
||||
* @param registryId id
|
||||
* @return entity
|
||||
*/
|
||||
RegistryEntity getRegistry(String registryId);
|
||||
|
||||
/**
|
||||
* Gets all registries.
|
||||
*
|
||||
* @return registries
|
||||
*/
|
||||
Set<RegistryEntity> getRegistries();
|
||||
|
||||
/**
|
||||
* Updates the specified registry using the specified revision.
|
||||
*
|
||||
* @param revision revision
|
||||
* @param registryDTO the registry dto
|
||||
* @return the updated registry registry entity
|
||||
*/
|
||||
RegistryEntity updateRegistry(Revision revision, RegistryDTO registryDTO);
|
||||
|
||||
/**
|
||||
* Deletes the specified registry using the specified revision.
|
||||
*
|
||||
* @param revision revision
|
||||
* @param registryId id
|
||||
* @return the deleted registry entity
|
||||
*/
|
||||
RegistryEntity deleteRegistry(Revision revision, String registryId);
|
||||
|
||||
// ----------------------------------------
|
||||
// History methods
|
||||
// ----------------------------------------
|
||||
|
|
|
@ -98,6 +98,7 @@ public class NiFiWebApiResourceConfig extends ResourceConfig {
|
|||
register(ctx.getBean("accessResource"));
|
||||
register(ctx.getBean("accessPolicyResource"));
|
||||
register(ctx.getBean("tenantsResource"));
|
||||
register(ctx.getBean("versionsResource"));
|
||||
|
||||
// exception mappers
|
||||
register(AccessDeniedExceptionMapper.class);
|
||||
|
|
|
@ -16,32 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.nifi.action.Action;
|
||||
import org.apache.nifi.action.Component;
|
||||
import org.apache.nifi.action.FlowChangeAction;
|
||||
|
@ -141,6 +116,7 @@ import org.apache.nifi.reporting.BulletinQuery;
|
|||
import org.apache.nifi.reporting.BulletinRepository;
|
||||
import org.apache.nifi.reporting.ComponentType;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.util.Tuple;
|
||||
import org.apache.nifi.web.api.dto.AccessPolicyDTO;
|
||||
import org.apache.nifi.web.api.dto.AccessPolicySummaryDTO;
|
||||
import org.apache.nifi.web.api.dto.AffectedComponentDTO;
|
||||
|
@ -179,6 +155,7 @@ import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
|
|||
import org.apache.nifi.web.api.dto.ProcessorDTO;
|
||||
import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
|
||||
import org.apache.nifi.web.api.dto.PropertyHistoryDTO;
|
||||
import org.apache.nifi.web.api.dto.RegistryDTO;
|
||||
import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
|
||||
import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO;
|
||||
import org.apache.nifi.web.api.dto.ReportingTaskDTO;
|
||||
|
@ -236,6 +213,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
|
|||
import org.apache.nifi.web.api.entity.ProcessGroupStatusSnapshotEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.RegistryEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupPortEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
|
||||
|
@ -279,7 +257,30 @@ import org.apache.nifi.web.util.SnippetUtils;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Implementation of NiFiServiceFacade that performs revision checking.
|
||||
|
@ -330,6 +331,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
|
||||
private AuthorizableLookup authorizableLookup;
|
||||
|
||||
private Map<String, Tuple<Revision, RegistryDTO>> registryCache = new HashMap<>();
|
||||
|
||||
// -----------------------------------------
|
||||
// Synchronization methods
|
||||
// -----------------------------------------
|
||||
|
@ -2257,6 +2260,45 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return entityFactory.createControllerServiceEntity(snapshot, null, permissions, null);
|
||||
}
|
||||
|
||||
private RegistryEntity createRegistryEntity(final Revision updatedRevision, final RegistryDTO registryDTO) {
|
||||
final RegistryEntity entity = new RegistryEntity();
|
||||
entity.setId(registryDTO.getId());
|
||||
entity.setPermissions(dtoFactory.createPermissionsDto(authorizableLookup.getController()));
|
||||
entity.setRevision(dtoFactory.createRevisionDTO(updatedRevision));
|
||||
entity.setComponent(registryDTO);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntity createRegistry(Revision revision, RegistryDTO registryDTO) {
|
||||
registryCache.put(registryDTO.getId(), new Tuple(revision, registryDTO));
|
||||
return createRegistryEntity(revision, registryDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntity getRegistry(String registryId) {
|
||||
final Tuple<Revision, RegistryDTO> registry = registryCache.get(registryId);
|
||||
return createRegistry(registry.getKey(), registry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RegistryEntity> getRegistries() {
|
||||
return registryCache.values().stream()
|
||||
.map(registry -> createRegistry(registry.getKey(), registry.getValue()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntity updateRegistry(Revision revision, RegistryDTO registryDTO) {
|
||||
registryCache.put(registryDTO.getId(), new Tuple(revision, registryDTO));
|
||||
return createRegistryEntity(revision, registryDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryEntity deleteRegistry(Revision revision, String registryId) {
|
||||
final Tuple<Revision, RegistryDTO> registry = registryCache.remove(registryId);
|
||||
return createRegistryEntity(registry.getKey(), registry.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportingTaskEntity createReportingTask(final Revision revision, final ReportingTaskDTO reportingTaskDTO) {
|
||||
|
@ -3504,7 +3546,7 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return null;
|
||||
}
|
||||
|
||||
final VersionControlInformationDTO versionControlDto = dtoFactory.createVersionControlInformationDto(versionControlInfo);
|
||||
final VersionControlInformationDTO versionControlDto = dtoFactory.createVersionControlInformationDto(processGroup);
|
||||
final RevisionDTO groupRevision = dtoFactory.createRevisionDTO(revisionManager.getRevision(groupId));
|
||||
return entityFactory.createVersionControlInformationEntity(versionControlDto, groupRevision);
|
||||
}
|
||||
|
@ -3555,7 +3597,19 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
final RevisionUpdate<VersionControlInformationDTO> snapshot = updateComponent(revision,
|
||||
group,
|
||||
() -> processGroupDAO.updateVersionControlInformation(versionControlInfo, versionedComponentMapping),
|
||||
processGroup -> dtoFactory.createVersionControlInformationDto(processGroup.getVersionControlInformation()));
|
||||
processGroup -> dtoFactory.createVersionControlInformationDto(processGroup));
|
||||
|
||||
return entityFactory.createVersionControlInformationEntity(snapshot.getComponent(), dtoFactory.createRevisionDTO(snapshot.getLastModification()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionControlInformationEntity deleteVersionControl(final Revision revision, final String processGroupId) {
|
||||
final ProcessGroup group = processGroupDAO.getProcessGroup(processGroupId);
|
||||
|
||||
final RevisionUpdate<VersionControlInformationDTO> snapshot = updateComponent(revision,
|
||||
group,
|
||||
() -> processGroupDAO.disconnectVersionControl(processGroupId),
|
||||
processGroup -> dtoFactory.createVersionControlInformationDto(group));
|
||||
|
||||
return entityFactory.createVersionControlInformationEntity(snapshot.getComponent(), dtoFactory.createRevisionDTO(snapshot.getLastModification()));
|
||||
}
|
||||
|
@ -3835,12 +3889,6 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return entityFactory.createProcessGroupEntity(snapshot.getComponent(), updatedRevision, permissions, status, bulletinEntities);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setFlowRegistryClient(final FlowRegistryClient client) {
|
||||
this.flowRegistryClient = client;
|
||||
}
|
||||
|
||||
private AuthorizationResult authorizeAction(final Action action) {
|
||||
final String sourceId = action.getSourceId();
|
||||
final Component type = action.getSourceType();
|
||||
|
@ -4194,4 +4242,28 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
public void setLeaderElectionManager(final LeaderElectionManager leaderElectionManager) {
|
||||
this.leaderElectionManager = leaderElectionManager;
|
||||
}
|
||||
|
||||
public void setFlowRegistryClient(FlowRegistryClient flowRegistryClient) {
|
||||
this.flowRegistryClient = flowRegistryClient;
|
||||
|
||||
// temp code to load the registry client cache
|
||||
final Set<String> registryIdentifiers = flowRegistryClient.getRegistryIdentifiers();
|
||||
if (registryIdentifiers != null) {
|
||||
|
||||
for (final String registryIdentifier : registryIdentifiers) {
|
||||
final FlowRegistry flowRegistry = flowRegistryClient.getFlowRegistry(registryIdentifier);
|
||||
|
||||
final RegistryDTO registry = new RegistryDTO();
|
||||
registry.setId(registryIdentifier);
|
||||
registry.setName(flowRegistry.getName());
|
||||
registry.setUri(flowRegistry.getURL());
|
||||
registry.setDescription("Default client for storing Flow Revisions to the local disk.");
|
||||
|
||||
final RegistryEntity registryEntity = new RegistryEntity();
|
||||
registryEntity.setComponent(registry);
|
||||
|
||||
registryCache.put(registryIdentifier, new Tuple(new Revision(0L, null, registryIdentifier), registry));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.apache.nifi.web.api.dto.BulletinDTO;
|
|||
import org.apache.nifi.web.api.dto.ClusterDTO;
|
||||
import org.apache.nifi.web.api.dto.ControllerServiceDTO;
|
||||
import org.apache.nifi.web.api.dto.NodeDTO;
|
||||
import org.apache.nifi.web.api.dto.RegistryDTO;
|
||||
import org.apache.nifi.web.api.dto.ReportingTaskDTO;
|
||||
import org.apache.nifi.web.api.entity.BulletinEntity;
|
||||
import org.apache.nifi.web.api.entity.ClusterEntity;
|
||||
|
@ -45,12 +46,16 @@ import org.apache.nifi.web.api.entity.ControllerServiceEntity;
|
|||
import org.apache.nifi.web.api.entity.Entity;
|
||||
import org.apache.nifi.web.api.entity.HistoryEntity;
|
||||
import org.apache.nifi.web.api.entity.NodeEntity;
|
||||
import org.apache.nifi.web.api.entity.RegistryEntity;
|
||||
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
|
||||
import org.apache.nifi.web.api.request.ClientIdParameter;
|
||||
import org.apache.nifi.web.api.request.DateTimeParameter;
|
||||
import org.apache.nifi.web.api.request.LongParameter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.POST;
|
||||
|
@ -81,6 +86,17 @@ public class ControllerResource extends ApplicationResource {
|
|||
private ReportingTaskResource reportingTaskResource;
|
||||
private ControllerServiceResource controllerServiceResource;
|
||||
|
||||
/**
|
||||
* Populate the uri's for the specified registry.
|
||||
*
|
||||
* @param registryEntity registry
|
||||
* @return dtos
|
||||
*/
|
||||
public RegistryEntity populateRemainingRegistryEntityContent(final RegistryEntity registryEntity) {
|
||||
registryEntity.setUri(generateResourceUri("controller", "registries", registryEntity.getId()));
|
||||
return registryEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorizes access to the flow.
|
||||
*/
|
||||
|
@ -290,6 +306,288 @@ public class ControllerResource extends ApplicationResource {
|
|||
);
|
||||
}
|
||||
|
||||
// ----------
|
||||
// registries
|
||||
// ----------
|
||||
|
||||
/**
|
||||
* Creates a new Registry.
|
||||
*
|
||||
* @param httpServletRequest request
|
||||
* @param requestRegistryEntity A registryEntity.
|
||||
* @return A registryEntity.
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("registries")
|
||||
@ApiOperation(
|
||||
value = "Creates a new registry",
|
||||
response = RegistryEntity.class,
|
||||
authorizations = {
|
||||
@Authorization(value = "Write - /controller")
|
||||
}
|
||||
)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
}
|
||||
)
|
||||
|
||||
public Response createRegistry(
|
||||
@Context final HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The registry configuration details.",
|
||||
required = true
|
||||
) final RegistryEntity requestRegistryEntity) {
|
||||
|
||||
if (requestRegistryEntity == null || requestRegistryEntity.getComponent() == null) {
|
||||
throw new IllegalArgumentException("Registry details must be specified.");
|
||||
}
|
||||
|
||||
if (requestRegistryEntity.getRevision() == null || (requestRegistryEntity.getRevision().getVersion() == null || requestRegistryEntity.getRevision().getVersion() != 0)) {
|
||||
throw new IllegalArgumentException("A revision of 0 must be specified when creating a new Registry.");
|
||||
}
|
||||
|
||||
final RegistryDTO requestReportingTask = requestRegistryEntity.getComponent();
|
||||
if (requestReportingTask.getId() != null) {
|
||||
throw new IllegalArgumentException("Registry ID cannot be specified.");
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.POST, requestRegistryEntity);
|
||||
}
|
||||
|
||||
return withWriteLock(
|
||||
serviceFacade,
|
||||
requestRegistryEntity,
|
||||
lookup -> {
|
||||
authorizeController(RequestAction.WRITE);
|
||||
},
|
||||
null,
|
||||
(registryEntity) -> {
|
||||
final RegistryDTO registry = registryEntity.getComponent();
|
||||
|
||||
// set the processor id as appropriate
|
||||
registry.setId(generateUuid());
|
||||
|
||||
// create the reporting task and generate the json
|
||||
final Revision revision = getRevision(registryEntity, registry.getId());
|
||||
final RegistryEntity entity = serviceFacade.createRegistry(revision, registry);
|
||||
populateRemainingRegistryEntityContent(entity);
|
||||
|
||||
// build the response
|
||||
return generateCreatedResponse(URI.create(entity.getUri()), entity).build();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specified registry.
|
||||
*
|
||||
* @param id The id of the registry to retrieve
|
||||
* @return A registryEntity.
|
||||
*/
|
||||
@GET
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/registries/{id}")
|
||||
@ApiOperation(
|
||||
value = "Gets a registry",
|
||||
response = RegistryEntity.class,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /controller")
|
||||
}
|
||||
)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
}
|
||||
)
|
||||
public Response getRegistry(
|
||||
@ApiParam(
|
||||
value = "The registry id.",
|
||||
required = true
|
||||
)
|
||||
@PathParam("id") final String id) {
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
|
||||
// authorize access
|
||||
authorizeController(RequestAction.READ);
|
||||
|
||||
// get the registry
|
||||
final RegistryEntity entity = serviceFacade.getRegistry(id);
|
||||
populateRemainingRegistryEntityContent(entity);
|
||||
|
||||
return generateOkResponse(entity).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the specified registry.
|
||||
*
|
||||
* @param httpServletRequest request
|
||||
* @param id The id of the controller service to update.
|
||||
* @param requestRegsitryEntity A controllerServiceEntity.
|
||||
* @return A controllerServiceEntity.
|
||||
*/
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/registries/{id}")
|
||||
@ApiOperation(
|
||||
value = "Updates a registry",
|
||||
response = RegistryEntity.class,
|
||||
authorizations = {
|
||||
@Authorization(value = "Write - /controller")
|
||||
}
|
||||
)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
}
|
||||
)
|
||||
public Response updateControllerService(
|
||||
@Context HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The registry id.",
|
||||
required = true
|
||||
)
|
||||
@PathParam("id") final String id,
|
||||
@ApiParam(
|
||||
value = "The registry configuration details.",
|
||||
required = true
|
||||
) final RegistryEntity requestRegsitryEntity) {
|
||||
|
||||
if (requestRegsitryEntity == null || requestRegsitryEntity.getComponent() == null) {
|
||||
throw new IllegalArgumentException("Registry details must be specified.");
|
||||
}
|
||||
|
||||
if (requestRegsitryEntity.getRevision() == null) {
|
||||
throw new IllegalArgumentException("Revision must be specified.");
|
||||
}
|
||||
|
||||
// ensure the ids are the same
|
||||
final RegistryDTO requestRegistryDTO = requestRegsitryEntity.getComponent();
|
||||
if (!id.equals(requestRegistryDTO.getId())) {
|
||||
throw new IllegalArgumentException(String.format("The registry id (%s) in the request body does not equal the "
|
||||
+ "registry id of the requested resource (%s).", requestRegistryDTO.getId(), id));
|
||||
}
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.PUT, requestRegsitryEntity);
|
||||
}
|
||||
|
||||
// handle expects request (usually from the cluster manager)
|
||||
final Revision requestRevision = getRevision(requestRegsitryEntity, id);
|
||||
return withWriteLock(
|
||||
serviceFacade,
|
||||
requestRegsitryEntity,
|
||||
requestRevision,
|
||||
lookup -> {
|
||||
authorizeController(RequestAction.WRITE);
|
||||
},
|
||||
null,
|
||||
(revision, registryEntity) -> {
|
||||
final RegistryDTO registry = registryEntity.getComponent();
|
||||
|
||||
// update the controller service
|
||||
final RegistryEntity entity = serviceFacade.updateRegistry(revision, registry);
|
||||
populateRemainingRegistryEntityContent(entity);
|
||||
|
||||
return generateOkResponse(entity).build();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified registry.
|
||||
*
|
||||
* @param httpServletRequest request
|
||||
* @param version The revision is used to verify the client is working with
|
||||
* the latest version of the flow.
|
||||
* @param clientId Optional client id. If the client id is not specified, a
|
||||
* new one will be generated. This value (whether specified or generated) is
|
||||
* included in the response.
|
||||
* @param id The id of the registry to remove.
|
||||
* @return A entity containing the client id and an updated revision.
|
||||
*/
|
||||
@DELETE
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("/registries/{id}")
|
||||
@ApiOperation(
|
||||
value = "Deletes a reistry",
|
||||
response = RegistryEntity.class,
|
||||
authorizations = {
|
||||
@Authorization(value = "Write - /controller")
|
||||
}
|
||||
)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
}
|
||||
)
|
||||
public Response deleteRegistry(
|
||||
@Context HttpServletRequest httpServletRequest,
|
||||
@ApiParam(
|
||||
value = "The revision is used to verify the client is working with the latest version of the flow.",
|
||||
required = false
|
||||
)
|
||||
@QueryParam(VERSION) final LongParameter version,
|
||||
@ApiParam(
|
||||
value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.",
|
||||
required = false
|
||||
)
|
||||
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
||||
@ApiParam(
|
||||
value = "The registry id.",
|
||||
required = true
|
||||
)
|
||||
@PathParam("id") final String id) {
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
final RegistryEntity requestRegistryEntity = new RegistryEntity();
|
||||
requestRegistryEntity.setId(id);
|
||||
|
||||
// handle expects request (usually from the cluster manager)
|
||||
final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
|
||||
return withWriteLock(
|
||||
serviceFacade,
|
||||
requestRegistryEntity,
|
||||
requestRevision,
|
||||
lookup -> {
|
||||
authorizeController(RequestAction.WRITE);
|
||||
},
|
||||
null,
|
||||
(revision, registryEntity) -> {
|
||||
// delete the specified registry
|
||||
final RegistryEntity entity = serviceFacade.deleteRegistry(revision, registryEntity.getId());
|
||||
return generateOkResponse(entity).build();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Bulletin.
|
||||
*
|
||||
|
|
|
@ -39,13 +39,18 @@ import org.apache.nifi.controller.service.ControllerServiceNode;
|
|||
import org.apache.nifi.controller.service.ControllerServiceState;
|
||||
import org.apache.nifi.groups.ProcessGroup;
|
||||
import org.apache.nifi.nar.NarClassLoaders;
|
||||
import org.apache.nifi.registry.bucket.Bucket;
|
||||
import org.apache.nifi.registry.flow.FlowRegistry;
|
||||
import org.apache.nifi.registry.flow.FlowRegistryClient;
|
||||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.web.IllegalClusterResourceRequestException;
|
||||
import org.apache.nifi.web.NiFiCoreException;
|
||||
import org.apache.nifi.web.NiFiServiceFacade;
|
||||
import org.apache.nifi.web.ResourceNotFoundException;
|
||||
import org.apache.nifi.web.Revision;
|
||||
import org.apache.nifi.web.api.dto.AboutDTO;
|
||||
import org.apache.nifi.web.api.dto.BannerDTO;
|
||||
import org.apache.nifi.web.api.dto.BucketDTO;
|
||||
import org.apache.nifi.web.api.dto.BulletinBoardDTO;
|
||||
import org.apache.nifi.web.api.dto.BulletinQueryDTO;
|
||||
import org.apache.nifi.web.api.dto.ClusterDTO;
|
||||
|
@ -64,6 +69,8 @@ import org.apache.nifi.web.api.entity.AboutEntity;
|
|||
import org.apache.nifi.web.api.entity.ActionEntity;
|
||||
import org.apache.nifi.web.api.entity.ActivateControllerServicesEntity;
|
||||
import org.apache.nifi.web.api.entity.BannerEntity;
|
||||
import org.apache.nifi.web.api.entity.BucketEntity;
|
||||
import org.apache.nifi.web.api.entity.BucketsEntity;
|
||||
import org.apache.nifi.web.api.entity.BulletinBoardEntity;
|
||||
import org.apache.nifi.web.api.entity.ClusteSummaryEntity;
|
||||
import org.apache.nifi.web.api.entity.ClusterSearchResultsEntity;
|
||||
|
@ -84,6 +91,8 @@ import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
|
|||
import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.ProcessorTypesEntity;
|
||||
import org.apache.nifi.web.api.entity.RegistriesEntity;
|
||||
import org.apache.nifi.web.api.entity.RegistryEntity;
|
||||
import org.apache.nifi.web.api.entity.RemoteProcessGroupStatusEntity;
|
||||
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
|
||||
import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity;
|
||||
|
@ -112,6 +121,7 @@ import javax.ws.rs.WebApplicationException;
|
|||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
|
@ -148,8 +158,11 @@ public class FlowResource extends ApplicationResource {
|
|||
private TemplateResource templateResource;
|
||||
private ProcessGroupResource processGroupResource;
|
||||
private ControllerServiceResource controllerServiceResource;
|
||||
private ControllerResource controllerResource;
|
||||
private ReportingTaskResource reportingTaskResource;
|
||||
|
||||
private FlowRegistryClient flowRegistryClient;
|
||||
|
||||
public FlowResource() {
|
||||
super();
|
||||
}
|
||||
|
@ -1317,6 +1330,98 @@ public class FlowResource extends ApplicationResource {
|
|||
return generateOkResponse(entity).build();
|
||||
}
|
||||
|
||||
// ----------
|
||||
// registries
|
||||
// ----------
|
||||
|
||||
@GET
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("registries")
|
||||
@ApiOperation(value = "Gets the listing of available registries", response = RegistriesEntity.class, authorizations = {
|
||||
@Authorization(value = "Read - /flow")
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
})
|
||||
public Response getRegistries() {
|
||||
authorizeFlow();
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
|
||||
final Set<RegistryEntity> registries = serviceFacade.getRegistries();
|
||||
registries.forEach(registry -> controllerResource.populateRemainingRegistryEntityContent(registry));
|
||||
|
||||
final RegistriesEntity registryEntities = new RegistriesEntity();
|
||||
registryEntities.setRegistries(registries);
|
||||
|
||||
return generateOkResponse(registryEntities).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("registries/{id}/buckets")
|
||||
@ApiOperation(value = "Gets the buckets from the specified registry for the current user", response = BucketsEntity.class, authorizations = {
|
||||
@Authorization(value = "Read - /flow")
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
@ApiResponse(code = 403, message = "Client is not authorized to make this request."),
|
||||
@ApiResponse(code = 404, message = "The specified resource could not be found."),
|
||||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
})
|
||||
public Response getBuckets(
|
||||
@ApiParam(
|
||||
value = "The registry id.",
|
||||
required = true
|
||||
)
|
||||
@PathParam("id") String id) {
|
||||
|
||||
authorizeFlow();
|
||||
|
||||
try {
|
||||
final FlowRegistry flowRegistry = flowRegistryClient.getFlowRegistry(id);
|
||||
if (flowRegistry == null) {
|
||||
throw new IllegalArgumentException("The specified registry id is unknown to this NiFi.");
|
||||
}
|
||||
|
||||
final Set<Bucket> userBuckets = flowRegistry.getBuckets(NiFiUserUtils.getNiFiUser());
|
||||
|
||||
final BucketsEntity bucketsEntity = new BucketsEntity();
|
||||
|
||||
if (userBuckets != null) {
|
||||
|
||||
final Set<BucketEntity> bucketSet = new HashSet<>();
|
||||
for (final Bucket userBucket : userBuckets) {
|
||||
final BucketDTO bucket = new BucketDTO();
|
||||
bucket.setId(userBucket.getIdentifier());
|
||||
bucket.setName(userBucket.getName());
|
||||
bucket.setDescription(userBucket.getDescription());
|
||||
bucket.setCreated(userBucket.getCreatedTimestamp());
|
||||
|
||||
final BucketEntity bucketEntity = new BucketEntity();
|
||||
bucketEntity.setBucket(bucket);
|
||||
|
||||
bucketSet.add(bucketEntity);
|
||||
}
|
||||
|
||||
bucketsEntity.setBuckets(bucketSet);
|
||||
}
|
||||
|
||||
return generateOkResponse(bucketsEntity).build();
|
||||
} catch (final IOException ioe) {
|
||||
throw new NiFiCoreException("Unable to obtain bucket listing: " + ioe.getMessage(), ioe);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------
|
||||
// bulletin board
|
||||
// --------------
|
||||
|
@ -2524,6 +2629,10 @@ public class FlowResource extends ApplicationResource {
|
|||
this.processGroupResource = processGroupResource;
|
||||
}
|
||||
|
||||
public void setControllerResource(ControllerResource controllerResource) {
|
||||
this.controllerResource = controllerResource;
|
||||
}
|
||||
|
||||
public void setControllerServiceResource(ControllerServiceResource controllerServiceResource) {
|
||||
this.controllerServiceResource = controllerServiceResource;
|
||||
}
|
||||
|
@ -2535,4 +2644,8 @@ public class FlowResource extends ApplicationResource {
|
|||
public void setAuthorizer(Authorizer authorizer) {
|
||||
this.authorizer = authorizer;
|
||||
}
|
||||
|
||||
public void setFlowRegistryClient(FlowRegistryClient flowRegistryClient) {
|
||||
this.flowRegistryClient = flowRegistryClient;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
|
||||
package org.apache.nifi.web.api;
|
||||
|
||||
import com.sun.jersey.api.client.ClientResponse.Status;
|
||||
import com.sun.jersey.api.core.ResourceContext;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
|
@ -84,9 +82,9 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
@ -109,8 +107,6 @@ import java.util.stream.Collectors;
|
|||
public class VersionsResource extends ApplicationResource {
|
||||
private static final Logger logger = LoggerFactory.getLogger(VersionsResource.class);
|
||||
|
||||
@Context
|
||||
private ResourceContext resourceContext;
|
||||
private NiFiServiceFacade serviceFacade;
|
||||
private Authorizer authorizer;
|
||||
private ComponentLifecycle clusterComponentLifecycle;
|
||||
|
@ -128,12 +124,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
private ActiveRequest activeRequest = null;
|
||||
private final Object activeRequestMonitor = new Object();
|
||||
|
||||
|
||||
@GET
|
||||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("process-groups/{id}")
|
||||
@ApiOperation(value = "Gets the Version Control information for a process group", response = VersionControlInformationEntity.class, authorizations = {
|
||||
@ApiOperation(value = "Gets the Version Control information for a process group", response = VersionControlInformationEntity.class, notes = NON_GUARANTEED_ENDPOINT, authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}")
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
|
@ -144,6 +139,7 @@ public class VersionsResource extends ApplicationResource {
|
|||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
})
|
||||
public Response getVersionInformation(@ApiParam(value = "The process group id.", required = true) @PathParam("id") final String groupId) {
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
return replicate(HttpMethod.GET);
|
||||
}
|
||||
|
@ -155,9 +151,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
});
|
||||
|
||||
// get the version control information for this process group
|
||||
final VersionControlInformationEntity entity = serviceFacade.getVersionControlInformation(groupId);
|
||||
VersionControlInformationEntity entity = serviceFacade.getVersionControlInformation(groupId);
|
||||
if (entity == null) {
|
||||
throw new ResourceNotFoundException("Process Group with ID " + groupId + " is not currently under Version Control");
|
||||
final ProcessGroupEntity processGroup = serviceFacade.getProcessGroup(groupId);
|
||||
entity = new VersionControlInformationEntity();
|
||||
entity.setProcessGroupRevision(processGroup.getRevision());
|
||||
}
|
||||
|
||||
return generateOkResponse(entity).build();
|
||||
|
@ -168,7 +166,10 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("start-requests")
|
||||
@ApiOperation(value = "Creates a request so that a Process Group can be placed under Version Control or have its Version Control configuration changed", response = VersionControlInformationEntity.class)
|
||||
@ApiOperation(
|
||||
value = "Creates a request so that a Process Group can be placed under Version Control or have its Version Control configuration changed",
|
||||
response = VersionControlInformationEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
|
@ -186,6 +187,7 @@ public class VersionsResource extends ApplicationResource {
|
|||
serviceFacade,
|
||||
/* entity */ null,
|
||||
lookup -> {
|
||||
// TODO - pass in PG ID to authorize
|
||||
},
|
||||
/* verifier */ null,
|
||||
requestEntity -> {
|
||||
|
@ -213,7 +215,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("start-requests/{id}")
|
||||
@ApiOperation(value = "Updates the request with the given ID", response = VersionControlInformationEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "Updates the request with the given ID",
|
||||
response = VersionControlInformationEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Write - /process-groups/{uuid}")
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
|
@ -301,7 +307,9 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("start-requests/{id}")
|
||||
@ApiOperation(value = "Deletes the request with the given ID")
|
||||
@ApiOperation(
|
||||
value = "Deletes the request with the given ID",
|
||||
notes = NON_GUARANTEED_ENDPOINT)
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
@ApiResponse(code = 401, message = "Client could not be authenticated."),
|
||||
|
@ -343,7 +351,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("process-groups/{id}")
|
||||
@ApiOperation(value = "Begins version controlling the Process Group with the given ID", response = VersionControlInformationEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "Begins version controlling the Process Group with the given ID",
|
||||
response = VersionControlInformationEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}")
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
|
@ -545,7 +557,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("process-groups/{id}")
|
||||
@ApiOperation(value = "Stops version controlling the Process Group with the given ID", response = VersionControlInformationEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "Stops version controlling the Process Group with the given ID",
|
||||
response = VersionControlInformationEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}"),
|
||||
@Authorization(value = "Write - /process-groups/{uuid}"),
|
||||
})
|
||||
|
@ -557,10 +573,14 @@ public class VersionsResource extends ApplicationResource {
|
|||
@ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.")
|
||||
})
|
||||
public Response stopVersionControl(
|
||||
@ApiParam(value = "The version is used to verify the client is working with the latest version of the flow.", required = false) @QueryParam(VERSION) final LongParameter version,
|
||||
|
||||
@ApiParam(value = "If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response.", required = false) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
||||
|
||||
@ApiParam(
|
||||
value = "The version is used to verify the client is working with the latest version of the flow.",
|
||||
required = false)
|
||||
@QueryParam(VERSION) final LongParameter version,
|
||||
@ApiParam(
|
||||
value = "If the client id is not specified, a new one will be generated. This value (whether specified or generated) is included in the response.",
|
||||
required = false)
|
||||
@QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId,
|
||||
@ApiParam("The process group id.") @PathParam("id") final String groupId) throws IOException {
|
||||
|
||||
if (isReplicateRequest()) {
|
||||
|
@ -584,8 +604,8 @@ public class VersionsResource extends ApplicationResource {
|
|||
}
|
||||
},
|
||||
(revision, groupEntity) -> {
|
||||
// set the version control info to null
|
||||
final VersionControlInformationEntity entity = serviceFacade.setVersionControlInformation(requestRevision, groupId, null, null);
|
||||
// disconnect from version control
|
||||
final VersionControlInformationEntity entity = serviceFacade.deleteVersionControl(requestRevision, groupId);
|
||||
|
||||
// generate the response
|
||||
return generateOkResponse(entity).build();
|
||||
|
@ -597,8 +617,10 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("process-groups/{id}")
|
||||
@ApiOperation(value = "For a Process Group that is already under Version Control, this will update the version of the flow to a different version",
|
||||
@ApiOperation(
|
||||
value = "For a Process Group that is already under Version Control, this will update the version of the flow to a different version",
|
||||
response = VersionControlInformationEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}"),
|
||||
@Authorization(value = "Write - /process-groups/{uuid}")
|
||||
|
@ -686,8 +708,10 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("update-requests/{id}")
|
||||
@ApiOperation(value = "Returns the Update Request with the given ID",
|
||||
@ApiOperation(
|
||||
value = "Returns the Update Request with the given ID",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
|
@ -705,8 +729,10 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("revert-requests/{id}")
|
||||
@ApiOperation(value = "Returns the Revert Request with the given ID",
|
||||
@ApiOperation(
|
||||
value = "Returns the Revert Request with the given ID",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
|
@ -750,7 +776,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("update-requests/{id}")
|
||||
@ApiOperation(value = "Deletes the Update Request with the given ID", response = VersionedFlowUpdateRequestEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "Deletes the Update Request with the given ID",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
|
@ -767,7 +797,11 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.WILDCARD)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("revert-requests/{id}")
|
||||
@ApiOperation(value = "Deletes the Revert Request with the given ID", response = VersionedFlowUpdateRequestEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "Deletes the Revert Request with the given ID",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
})
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."),
|
||||
|
@ -813,8 +847,12 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("update-requests/process-groups/{id}")
|
||||
@ApiOperation(value = "For a Process Group that is already under Version Control, this will initiate the action of changing "
|
||||
+ "from a specific version of the flow in the Flow Registry to a different version of the flow.", response = VersionedFlowUpdateRequestEntity.class, authorizations = {
|
||||
@ApiOperation(
|
||||
value = "For a Process Group that is already under Version Control, this will initiate the action of changing "
|
||||
+ "from a specific version of the flow in the Flow Registry to a different version of the flow.",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}"),
|
||||
@Authorization(value = "Write - /process-groups/{uuid}")
|
||||
})
|
||||
|
@ -970,9 +1008,13 @@ public class VersionsResource extends ApplicationResource {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("revert-requests/process-groups/{id}")
|
||||
@ApiOperation(value = "For a Process Group that is already under Version Control, this will initiate the action of reverting "
|
||||
@ApiOperation(
|
||||
value = "For a Process Group that is already under Version Control, this will initiate the action of reverting "
|
||||
+ "any changes that have been made to the Process Group since it was last synchronized with the Flow Registry. This will result in the "
|
||||
+ "flow matching the Versioned Flow that exists in the Flow Registry.", response = VersionedFlowUpdateRequestEntity.class, authorizations = {
|
||||
+ "flow matching the Versioned Flow that exists in the Flow Registry.",
|
||||
response = VersionedFlowUpdateRequestEntity.class,
|
||||
notes = NON_GUARANTEED_ENDPOINT,
|
||||
authorizations = {
|
||||
@Authorization(value = "Read - /process-groups/{uuid}"),
|
||||
@Authorization(value = "Write - /process-groups/{uuid}")
|
||||
})
|
||||
|
@ -1250,7 +1292,7 @@ public class VersionsResource extends ApplicationResource {
|
|||
private <T> T getResponseEntity(final NodeResponse nodeResponse, final Class<T> clazz) {
|
||||
T entity = (T) nodeResponse.getUpdatedEntity();
|
||||
if (entity == null) {
|
||||
entity = nodeResponse.getClientResponse().getEntity(clazz);
|
||||
entity = nodeResponse.getClientResponse().readEntity(clazz);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
package org.apache.nifi.web.api.concurrent;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface AsynchronousWebRequest<T> {
|
||||
|
||||
/**
|
||||
|
@ -67,7 +67,7 @@ public interface AsynchronousWebRequest<T> {
|
|||
/**
|
||||
* Indicates the reason that the request failed, or <code>null</code> if the request has not failed
|
||||
*
|
||||
* @param explanation the reason that the request failed, or <code>null</code> if the request has not failed
|
||||
* @return the reason that the request failed, or <code>null</code> if the request has not failed
|
||||
*/
|
||||
String getFailureReason();
|
||||
|
||||
|
|
|
@ -16,33 +16,7 @@
|
|||
*/
|
||||
package org.apache.nifi.web.api.dto;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.action.Action;
|
||||
|
@ -139,6 +113,7 @@ import org.apache.nifi.provenance.lineage.LineageEdge;
|
|||
import org.apache.nifi.provenance.lineage.LineageNode;
|
||||
import org.apache.nifi.provenance.lineage.ProvenanceEventLineageNode;
|
||||
import org.apache.nifi.registry.ComponentVariableRegistry;
|
||||
import org.apache.nifi.registry.flow.FlowRegistryClient;
|
||||
import org.apache.nifi.registry.flow.VersionControlInformation;
|
||||
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedConnection;
|
||||
import org.apache.nifi.registry.flow.mapping.InstantiatedVersionedControllerService;
|
||||
|
@ -209,6 +184,32 @@ import org.apache.nifi.web.api.entity.VariableEntity;
|
|||
import org.apache.nifi.web.controller.ControllerFacade;
|
||||
import org.apache.nifi.web.revision.RevisionManager;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class DtoFactory {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -225,6 +226,7 @@ public final class DtoFactory {
|
|||
private EntityFactory entityFactory;
|
||||
private Authorizer authorizer;
|
||||
private NiFiProperties properties;
|
||||
private FlowRegistryClient flowRegistryClient;
|
||||
|
||||
public ControllerConfigurationDTO createControllerConfigurationDto(final ControllerFacade controllerFacade) {
|
||||
final ControllerConfigurationDTO dto = new ControllerConfigurationDTO();
|
||||
|
@ -242,6 +244,7 @@ public final class DtoFactory {
|
|||
dto.setSupportsManagedAuthorizer(AuthorizerCapabilityDetection.isManagedAuthorizer(authorizer));
|
||||
dto.setSupportsConfigurableUsersAndGroups(AuthorizerCapabilityDetection.isConfigurableUserGroupProvider(authorizer));
|
||||
dto.setSupportsConfigurableAuthorizer(AuthorizerCapabilityDetection.isConfigurableAccessPolicyProvider(authorizer));
|
||||
dto.setSupportsFlowVersioning(CollectionUtils.isNotEmpty(flowRegistryClient.getRegistryIdentifiers()));
|
||||
|
||||
final Date now = new Date();
|
||||
dto.setTimeOffset(TimeZone.getDefault().getOffset(now.getTime()));
|
||||
|
@ -1687,6 +1690,9 @@ public final class DtoFactory {
|
|||
dto.setId(group.getIdentifier());
|
||||
dto.setName(group.getName());
|
||||
|
||||
final VersionControlInformationDTO versionControlInformation = createVersionControlInformationDto(group);
|
||||
dto.setVersionControlInformation(versionControlInformation);
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
|
@ -2145,7 +2151,7 @@ public final class DtoFactory {
|
|||
dto.setComments(group.getComments());
|
||||
dto.setName(group.getName());
|
||||
dto.setVersionedComponentId(group.getVersionedComponentId().orElse(null));
|
||||
dto.setVersionControlInformation(createVersionControlInformationDto(group.getVersionControlInformation()));
|
||||
dto.setVersionControlInformation(createVersionControlInformationDto(group));
|
||||
|
||||
final Map<String, String> variables = group.getVariableRegistry().getVariableMap().entrySet().stream()
|
||||
.collect(Collectors.toMap(entry -> entry.getKey().getName(), entry -> entry.getValue()));
|
||||
|
@ -2169,12 +2175,18 @@ public final class DtoFactory {
|
|||
return dto;
|
||||
}
|
||||
|
||||
public VersionControlInformationDTO createVersionControlInformationDto(final VersionControlInformation versionControlInfo) {
|
||||
public VersionControlInformationDTO createVersionControlInformationDto(final ProcessGroup group) {
|
||||
if (group == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final VersionControlInformation versionControlInfo = group.getVersionControlInformation();
|
||||
if (versionControlInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final VersionControlInformationDTO dto = new VersionControlInformationDTO();
|
||||
dto.setGroupId(group.getIdentifier());
|
||||
dto.setRegistryId(versionControlInfo.getRegistryIdentifier());
|
||||
dto.setBucketId(versionControlInfo.getBucketIdentifier());
|
||||
dto.setFlowId(versionControlInfo.getFlowIdentifier());
|
||||
|
@ -3722,4 +3734,8 @@ public final class DtoFactory {
|
|||
public void setProperties(final NiFiProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public void setFlowRegistryClient(FlowRegistryClient flowRegistryClient) {
|
||||
this.flowRegistryClient = flowRegistryClient;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -213,6 +213,7 @@ public final class EntityFactory {
|
|||
|
||||
public ProcessGroupEntity createProcessGroupEntity(final ProcessGroupDTO dto, final RevisionDTO revision, final PermissionsDTO permissions,
|
||||
final ProcessGroupStatusDTO status, final List<BulletinEntity> bulletins) {
|
||||
|
||||
final ProcessGroupEntity entity = new ProcessGroupEntity();
|
||||
entity.setRevision(revision);
|
||||
if (dto != null) {
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.dao;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.apache.nifi.controller.ScheduledState;
|
||||
import org.apache.nifi.controller.service.ControllerServiceState;
|
||||
import org.apache.nifi.groups.ProcessGroup;
|
||||
|
@ -28,6 +24,10 @@ import org.apache.nifi.web.api.dto.ProcessGroupDTO;
|
|||
import org.apache.nifi.web.api.dto.VariableRegistryDTO;
|
||||
import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public interface ProcessGroupDAO {
|
||||
|
||||
/**
|
||||
|
@ -112,7 +112,7 @@ public interface ProcessGroupDAO {
|
|||
* @param groupId the ID of the process group
|
||||
* @param proposedSnapshot Flow the new version of the flow
|
||||
* @param versionControlInformation the new Version Control Information
|
||||
* @param the seed value to use for generating ID's for new components
|
||||
* @param componentIdSeed the seed value to use for generating ID's for new components
|
||||
* @return the process group
|
||||
*/
|
||||
ProcessGroup updateProcessGroupFlow(String groupId, VersionedFlowSnapshot proposedSnapshot, VersionControlInformationDTO versionControlInformation, String componentIdSeed,
|
||||
|
@ -127,6 +127,14 @@ public interface ProcessGroupDAO {
|
|||
*/
|
||||
ProcessGroup updateVersionControlInformation(VersionControlInformationDTO versionControlInformation, Map<String, String> versionedComponentMapping);
|
||||
|
||||
/**
|
||||
* Disconnects the specified group from version control.
|
||||
*
|
||||
* @param groupId group id
|
||||
* @return the corresponding Process Group
|
||||
*/
|
||||
ProcessGroup disconnectVersionControl(String groupId);
|
||||
|
||||
/**
|
||||
* Updates the specified variable registry
|
||||
*
|
||||
|
|
|
@ -16,13 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.web.dao.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.apache.nifi.connectable.Connectable;
|
||||
import org.apache.nifi.connectable.Port;
|
||||
import org.apache.nifi.connectable.Position;
|
||||
|
@ -43,6 +36,13 @@ import org.apache.nifi.web.api.dto.VersionControlInformationDTO;
|
|||
import org.apache.nifi.web.api.entity.VariableEntity;
|
||||
import org.apache.nifi.web.dao.ProcessGroupDAO;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGroupDAO {
|
||||
|
||||
private FlowController flowController;
|
||||
|
@ -246,6 +246,12 @@ public class StandardProcessGroupDAO extends ComponentDAO implements ProcessGrou
|
|||
return group;
|
||||
}
|
||||
|
||||
public ProcessGroup disconnectVersionControl(final String groupId) {
|
||||
final ProcessGroup group = locateProcessGroup(flowController, groupId);
|
||||
group.disconnectVersionControl();
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProcessGroup updateProcessGroupFlow(final String groupId, final VersionedFlowSnapshot proposedSnapshot, final VersionControlInformationDTO versionControlInformation,
|
||||
final String componentIdSeed, final boolean verifyNotModified) {
|
||||
|
|
|
@ -17,19 +17,6 @@
|
|||
|
||||
package org.apache.nifi.web.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
|
||||
import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
|
||||
|
@ -55,7 +42,18 @@ import org.apache.nifi.web.api.entity.ScheduleComponentsEntity;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.sun.jersey.core.util.MultivaluedMapImpl;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.MultivaluedHashMap;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ClusterReplicationComponentLifecycle implements ComponentLifecycle {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClusterReplicationComponentLifecycle.class);
|
||||
|
@ -155,8 +153,9 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
|
|||
* Periodically polls the process group with the given ID, waiting for all processors whose ID's are given to have the given Scheduled State.
|
||||
*
|
||||
* @param user the user making the request
|
||||
* @param originalUri the original uri
|
||||
* @param groupId the ID of the Process Group to poll
|
||||
* @param processorIds the ID of all Processors whose state should be equal to the given desired state
|
||||
* @param processors the Processors whose state should be equal to the given desired state
|
||||
* @param desiredState the desired state for all processors with the ID's given
|
||||
* @param pause the Pause that can be used to wait between polling
|
||||
* @return <code>true</code> if successful, <code>false</code> if unable to wait for processors to reach the desired state
|
||||
|
@ -172,7 +171,7 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
|
|||
}
|
||||
|
||||
final Map<String, String> headers = new HashMap<>();
|
||||
final MultivaluedMap<String, String> requestEntity = new MultivaluedMapImpl();
|
||||
final MultivaluedMap<String, String> requestEntity = new MultivaluedHashMap<>();
|
||||
|
||||
boolean continuePolling = true;
|
||||
while (continuePolling) {
|
||||
|
@ -217,7 +216,7 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
|
|||
private <T> T getResponseEntity(final NodeResponse nodeResponse, final Class<T> clazz) {
|
||||
T entity = (T) nodeResponse.getUpdatedEntity();
|
||||
if (entity == null) {
|
||||
entity = nodeResponse.getClientResponse().getEntity(clazz);
|
||||
entity = nodeResponse.getClientResponse().readEntity(clazz);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
@ -354,7 +353,7 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
|
|||
}
|
||||
|
||||
final Map<String, String> headers = new HashMap<>();
|
||||
final MultivaluedMap<String, String> requestEntity = new MultivaluedMapImpl();
|
||||
final MultivaluedMap<String, String> requestEntity = new MultivaluedHashMap<>();
|
||||
|
||||
boolean continuePolling = true;
|
||||
while (continuePolling) {
|
||||
|
@ -405,7 +404,7 @@ public class ClusterReplicationComponentLifecycle implements ComponentLifecycle
|
|||
* Updates the affected controller services in the specified updateRequest with the serviceEntities.
|
||||
*
|
||||
* @param serviceEntities service entities
|
||||
* @param updateRequest update request
|
||||
* @param affectedServices affected services
|
||||
*/
|
||||
private void updateAffectedControllerServices(final Set<ControllerServiceEntity> serviceEntities, final Map<String, AffectedComponentEntity> affectedServices) {
|
||||
// update the affected components
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
|
||||
package org.apache.nifi.web.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.controller.ScheduledState;
|
||||
import org.apache.nifi.controller.service.ControllerServiceState;
|
||||
|
@ -38,6 +32,12 @@ import org.apache.nifi.web.revision.RevisionManager;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LocalComponentLifecycle implements ComponentLifecycle {
|
||||
private static final Logger logger = LoggerFactory.getLogger(LocalComponentLifecycle.class);
|
||||
|
||||
|
@ -232,7 +232,7 @@ public class LocalComponentLifecycle implements ComponentLifecycle {
|
|||
* Periodically polls the process group with the given ID, waiting for all controller services whose ID's are given to have the given Controller Service State.
|
||||
*
|
||||
* @param groupId the ID of the Process Group to poll
|
||||
* @param serviceIds the ID of all Controller Services whose state should be equal to the given desired state
|
||||
* @param affectedServices all Controller Services whose state should be equal to the given desired state
|
||||
* @param desiredState the desired state for all services with the ID's given
|
||||
* @param pause the Pause that can be used to wait between polling
|
||||
* @param user the user that is retrieving the controller services
|
||||
|
@ -275,7 +275,7 @@ public class LocalComponentLifecycle implements ComponentLifecycle {
|
|||
* Updates the affected controller services in the specified updateRequest with the serviceEntities.
|
||||
*
|
||||
* @param serviceEntities service entities
|
||||
* @param updateRequest update request
|
||||
* @param affectedServices all Controller Services whose state should be equal to the given desired state
|
||||
*/
|
||||
private void updateAffectedControllerServices(final Set<ControllerServiceEntity> serviceEntities, final Map<String, AffectedComponentEntity> affectedServices) {
|
||||
// update the affected components
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
<property name="authorizer" ref="authorizer"/>
|
||||
<property name="bulletinRepository" ref="bulletinRepository"/>
|
||||
<property name="properties" ref="nifiProperties"/>
|
||||
<property name="flowRegistryClient" ref="flowRegistryClient" />
|
||||
</bean>
|
||||
|
||||
<!-- snippet utils -->
|
||||
|
@ -208,6 +209,7 @@
|
|||
<property name="remoteProcessGroupResource" ref="remoteProcessGroupResource"/>
|
||||
<property name="connectionResource" ref="connectionResource"/>
|
||||
<property name="templateResource" ref="templateResource"/>
|
||||
<property name="controllerResource" ref="controllerResource"/>
|
||||
<property name="controllerServiceResource" ref="controllerServiceResource"/>
|
||||
<property name="reportingTaskResource" ref="reportingTaskResource"/>
|
||||
<property name="processGroupResource" ref="processGroupResource"/>
|
||||
|
@ -215,6 +217,7 @@
|
|||
<property name="clusterCoordinator" ref="clusterCoordinator"/>
|
||||
<property name="requestReplicator" ref="requestReplicator" />
|
||||
<property name="flowController" ref="flowController" />
|
||||
<property name="flowRegistryClient" ref="flowRegistryClient" />
|
||||
</bean>
|
||||
<bean id="resourceResource" class="org.apache.nifi.web.api.ResourceResource" scope="singleton">
|
||||
<property name="serviceFacade" ref="serviceFacade"/>
|
||||
|
|
|
@ -475,6 +475,7 @@
|
|||
<include>${staging.dir}/js/nf/canvas/nf-draggable.js</include>
|
||||
<include>${staging.dir}/js/nf/canvas/nf-connectable.js</include>
|
||||
<include>${staging.dir}/js/nf/canvas/nf-graph.js</include>
|
||||
<include>${staging.dir}/js/nf/canvas/nf-flow-version.js</include>
|
||||
<include>${staging.dir}/js/nf/nf-filtered-dialog-common.js</include>
|
||||
<include>${staging.dir}/js/nf/nf-status-history.js</include>
|
||||
<include>${staging.dir}/js/nf/canvas/nf-queue-listing.js</include>
|
||||
|
|
|
@ -57,6 +57,7 @@ nf.canvas.script.tags=<script type="text/javascript" src="js/nf/nf-ng-bridge.js?
|
|||
<script type="text/javascript" src="js/nf/canvas/nf-draggable.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/canvas/nf-connectable.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/canvas/nf-graph.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/canvas/nf-flow-version.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/nf-filtered-dialog-common.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/nf-status-history.js?${project.version}"></script>\n\
|
||||
<script type="text/javascript" src="js/nf/canvas/nf-queue-listing.js?${project.version}"></script>\n\
|
||||
|
|
|
@ -115,6 +115,8 @@
|
|||
<jsp:include page="/WEB-INF/partials/canvas/instantiate-template-dialog.jsp"/>
|
||||
<jsp:include page="/WEB-INF/partials/canvas/fill-color-dialog.jsp"/>
|
||||
<jsp:include page="/WEB-INF/partials/canvas/connections-dialog.jsp"/>
|
||||
<jsp:include page="/WEB-INF/partials/canvas/save-flow-version-dialog.jsp"/>
|
||||
<jsp:include page="/WEB-INF/partials/canvas/registry-configuration-dialog.jsp"/>
|
||||
<div id="canvas-container" class="unselectable"></div>
|
||||
<div id="canvas-tooltips">
|
||||
<div id="processor-tooltips"></div>
|
||||
|
|
|
@ -22,56 +22,56 @@
|
|||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.processor}}"
|
||||
id="processor-component"
|
||||
class="component-button icon icon-processor"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.processorComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.inputPort}}"
|
||||
id="port-in-component"
|
||||
class="component-button icon icon-port-in"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.inputPortComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.outputPort}}"
|
||||
id="port-out-component"
|
||||
class="component-button icon icon-port-out"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.outputPortComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.processGroup}}"
|
||||
id="group-component"
|
||||
class="component-button icon icon-group"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.groupComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.remoteProcessGroup}}"
|
||||
id="group-remote-component"
|
||||
class="component-button icon icon-group-remote"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.remoteGroupComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.funnel}}"
|
||||
id="funnel-component"
|
||||
class="component-button icon icon-funnel"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.funnelComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.template}}"
|
||||
id="template-component"
|
||||
class="component-button icon icon-template"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.templateComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
<button title="{{appCtrl.serviceProvider.headerCtrl.toolboxCtrl.config.type.label}}"
|
||||
id="label-component"
|
||||
class="component-button icon icon-label"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWrite();"
|
||||
ng-disabled="!appCtrl.nf.CanvasUtils.canWriteCurrentGroup();"
|
||||
nf-draggable="appCtrl.serviceProvider.headerCtrl.toolboxCtrl.draggableComponentConfig(appCtrl.serviceProvider.headerCtrl.toolboxCtrl.labelComponent);">
|
||||
<span class="component-button-grip"></span>
|
||||
</button>
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<%--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--%>
|
||||
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
|
||||
<div id="registry-configuration-dialog" layout="column" class="hidden medium-dialog">
|
||||
<div class="dialog-content">
|
||||
<div class="setting">
|
||||
<div class="setting-name">Name</div>
|
||||
<div class="setting-field">
|
||||
<span id="registry-id" class="hidden"></span>
|
||||
<input type="text" id="registry-name" class="setting-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Location</div>
|
||||
<div class="setting-field">
|
||||
<input type="text" id="registry-location" class="setting-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Description</div>
|
||||
<div class="setting-field">
|
||||
<textarea id="registry-description" class="setting-input"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,54 @@
|
|||
<%--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
--%>
|
||||
<%@ page contentType="text/html" pageEncoding="UTF-8" session="false" %>
|
||||
<div id="save-flow-version-dialog" layout="column" class="hidden large-dialog">
|
||||
<div class="dialog-content">
|
||||
<div class="setting">
|
||||
<div class="setting-name">Registry</div>
|
||||
<div class="setting-field">
|
||||
<div id="flow-version-registry-combo"></div>
|
||||
<div id="flow-version-registry" class="hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Location</div>
|
||||
<div class="setting-field">
|
||||
<div id="flow-version-bucket-combo"></div>
|
||||
<div id="flow-version-bucket" class="hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Name</div>
|
||||
<div class="setting-field">
|
||||
<span id="flow-version-process-group-id" class="hidden"></span>
|
||||
<input type="text" id="flow-version-name" class="setting-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Description</div>
|
||||
<div class="setting-field">
|
||||
<textarea id="flow-version-description" class="setting-input"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<div class="setting-name">Change Comments</div>
|
||||
<div class="setting-field">
|
||||
<textarea id="flow-version-change-comments" class="setting-input"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -62,6 +62,9 @@
|
|||
<div id="reporting-tasks-tab-content" class="configuration-tab controller-settings-table">
|
||||
<div id="reporting-tasks-table" class="settings-table"></div>
|
||||
</div>
|
||||
<div id="registries-tab-content" class="configuration-tab controller-settings-table">
|
||||
<div id="registries-table" class="settings-table"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="settings-refresh-container">
|
||||
|
|
|
@ -212,6 +212,14 @@ div.progress-label {
|
|||
height: 575px;
|
||||
}
|
||||
|
||||
/*
|
||||
Flow Version
|
||||
*/
|
||||
|
||||
#flow-version-description, #flow-version-change-comments {
|
||||
height: 85px;
|
||||
}
|
||||
|
||||
/*
|
||||
Variable Registry
|
||||
*/
|
||||
|
@ -251,6 +259,14 @@ div.slick-cell div.overridden {
|
|||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
/*
|
||||
Registry configuration dialog
|
||||
*/
|
||||
|
||||
#registry-description {
|
||||
height: 85px;
|
||||
}
|
||||
|
||||
/*
|
||||
General dialog styles.
|
||||
*/
|
||||
|
|
|
@ -422,6 +422,14 @@ text.process-group-name {
|
|||
font-size: 14px;
|
||||
}
|
||||
|
||||
text.version-control {
|
||||
font-family: FontAwesome;
|
||||
font-size: 18px;
|
||||
fill: rgba(0, 255, 0, 0.65);
|
||||
stroke: rgba(0, 0, 0, 0.65);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
text.process-group-contents-count {
|
||||
fill: #775351;
|
||||
font-size: 15px;
|
||||
|
|
|
@ -278,6 +278,11 @@ rect.birdseye-brush {
|
|||
top: 8px;
|
||||
}
|
||||
|
||||
span.breadcrumb-version-control {
|
||||
color: #0f0;
|
||||
text-shadow: 0px 0px 1px #000;
|
||||
}
|
||||
|
||||
#breadcrumbs-left-border {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
|
|
@ -74,6 +74,21 @@
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the version control information for the specified process group.
|
||||
*
|
||||
* @param processGroupId
|
||||
* @param versionControlInformation
|
||||
*/
|
||||
updateVersionControlInformation: function (processGroupId, versionControlInformation) {
|
||||
$.each(this.breadcrumbs, function (_, breadcrumbEntity) {
|
||||
if (breadcrumbEntity.id === processGroupId) {
|
||||
breadcrumbEntity.breadcrumb.versionControlInformation = versionControlInformation;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset the breadcrumbs.
|
||||
*/
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
*/
|
||||
getContextName: function () {
|
||||
var selection = nfCanvasUtils.getSelection();
|
||||
var canRead = nfCanvasUtils.canReadFromGroup();
|
||||
var canRead = nfCanvasUtils.canReadCurrentGroup();
|
||||
|
||||
if (selection.empty()) {
|
||||
if (canRead) {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
'nf.Shell',
|
||||
'nf.VariableRegistry',
|
||||
'nf.ComponentState',
|
||||
'nf.FlowVersion',
|
||||
'nf.Draggable',
|
||||
'nf.Birdseye',
|
||||
'nf.Connection',
|
||||
|
@ -55,8 +56,8 @@
|
|||
'nf.ComponentVersion',
|
||||
'nf.QueueListing',
|
||||
'nf.StatusHistory'],
|
||||
function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory) {
|
||||
return (nf.Actions = factory($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory));
|
||||
function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory) {
|
||||
return (nf.Actions = factory($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory));
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof module === 'object') {
|
||||
module.exports = (nf.Actions =
|
||||
|
@ -74,6 +75,7 @@
|
|||
require('nf.Shell'),
|
||||
require('nf.VariableRegistry'),
|
||||
require('nf.ComponentState'),
|
||||
require('nf.FlowVersion'),
|
||||
require('nf.Draggable'),
|
||||
require('nf.Birdseye'),
|
||||
require('nf.Connection'),
|
||||
|
@ -111,6 +113,7 @@
|
|||
root.nf.Shell,
|
||||
root.nf.VariableRegistry,
|
||||
root.nf.ComponentState,
|
||||
root.nf.FlowVersion,
|
||||
root.nf.Draggable,
|
||||
root.nf.Birdseye,
|
||||
root.nf.Connection,
|
||||
|
@ -134,7 +137,7 @@
|
|||
root.nf.QueueListing,
|
||||
root.nf.StatusHistory);
|
||||
}
|
||||
}(this, function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory) {
|
||||
}(this, function ($, d3, nfCanvasUtils, nfCommon, nfDialog, nfClient, nfErrorHandler, nfClipboard, nfSnippet, nfGoto, nfNgBridge, nfShell, nfVariableRegistry, nfComponentState, nfFlowVersion, nfDraggable, nfBirdseye, nfConnection, nfGraph, nfProcessGroupConfiguration, nfProcessorConfiguration, nfProcessorDetails, nfLabelConfiguration, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupDetails, nfPortConfiguration, nfPortDetails, nfConnectionConfiguration, nfConnectionDetails, nfPolicyManagement, nfRemoteProcessGroup, nfLabel, nfProcessor, nfRemoteProcessGroupPorts, nfComponentVersion, nfQueueListing, nfStatusHistory) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
|
@ -1236,6 +1239,51 @@
|
|||
nfComponentState.showState(processor, nfCanvasUtils.isConfigurable(selection));
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the flow version dialog.
|
||||
*/
|
||||
saveFlowVersion: function (selection) {
|
||||
if (selection.empty()) {
|
||||
nfFlowVersion.showFlowVersionDialog(nfCanvasUtils.getGroupId());
|
||||
} else if (selection.size() === 1) {
|
||||
var selectionData = selection.datum();
|
||||
if (nfCanvasUtils.isProcessGroup(selection)) {
|
||||
nfFlowVersion.showFlowVersionDialog(selectionData.id);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reverts outstanding changes.
|
||||
*/
|
||||
revertFlowChanges: function (selection) {
|
||||
if (selection.empty()) {
|
||||
nfFlowVersion.revertFlowChanges(nfCanvasUtils.getGroupId());
|
||||
} else if (selection.size() === 1) {
|
||||
var selectionData = selection.datum();
|
||||
nfFlowVersion.revertFlowChanges(selectionData.id);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Changes the flow version.
|
||||
*/
|
||||
changeFlowVersion: function (selection) {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnects a Process Group from flow versioning.
|
||||
*/
|
||||
disconnectFlowVersioning: function (selection) {
|
||||
if (selection.empty()) {
|
||||
nfFlowVersion.disconnectFlowVersioning(nfCanvasUtils.getGroupId());
|
||||
} else if (selection.size() === 1) {
|
||||
var selectionData = selection.datum();
|
||||
nfFlowVersion.disconnectFlowVersioning(selectionData.id);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the variable registry for the specified selection of the current group if the selection is emtpy.
|
||||
*
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
'nf.QueueListing',
|
||||
'nf.VariableRegistry',
|
||||
'nf.ComponentState',
|
||||
'nf.FlowVersion',
|
||||
'nf.ComponentVersion',
|
||||
'nf.Draggable',
|
||||
'nf.Connectable',
|
||||
|
@ -82,8 +83,8 @@
|
|||
'nf.ng.Canvas.OperateCtrl',
|
||||
'nf.ng.BreadcrumbsDirective',
|
||||
'nf.ng.DraggableDirective'],
|
||||
function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
|
||||
return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective);
|
||||
function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
|
||||
return factory($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective);
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof module === 'object') {
|
||||
module.exports = factory(require('jquery'),
|
||||
|
@ -106,6 +107,7 @@
|
|||
require('nf.QueueListing'),
|
||||
require('nf.VariableRegistry'),
|
||||
require('nf.ComponentState'),
|
||||
require('nf.FlowVersion'),
|
||||
require('nf.ComponentVersion'),
|
||||
require('nf.Draggable'),
|
||||
require('nf.Connectable'),
|
||||
|
@ -170,6 +172,7 @@
|
|||
root.nf.QueueListing,
|
||||
root.nf.VariableRegistry,
|
||||
root.nf.ComponentState,
|
||||
root.nf.FlowVersion,
|
||||
root.nf.ComponentVersion,
|
||||
root.nf.Draggable,
|
||||
root.nf.Connectable,
|
||||
|
@ -214,7 +217,7 @@
|
|||
root.nf.ng.BreadcrumbsDirective,
|
||||
root.nf.ng.DraggableDirective);
|
||||
}
|
||||
}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
|
||||
}(this, function ($, angular, nfCommon, nfCanvasUtils, nfErrorHandler, nfClient, nfClusterSummary, nfDialog, nfStorage, nfCanvas, nfGraph, nfContextMenu, nfQuickSelect, nfShell, nfSettings, nfActions, nfSnippet, nfQueueListing, nfVariableRegistry, nfComponentState, nfFlowVersion, nfComponentVersion, nfDraggable, nfConnectable, nfStatusHistory, nfBirdseye, nfConnectionConfiguration, nfControllerService, nfReportingTask, nfPolicyManagement, nfProcessorConfiguration, nfProcessGroupConfiguration, nfControllerServices, nfRemoteProcessGroupConfiguration, nfRemoteProcessGroupPorts, nfPortConfiguration, nfLabelConfiguration, nfProcessorDetails, nfPortDetails, nfConnectionDetails, nfRemoteProcessGroupDetails, nfGoto, nfNgBridge, appCtrl, appConfig, serviceProvider, breadcrumbsCtrl, headerCtrl, flowStatusCtrl, globalMenuCtrl, toolboxCtrl, processorComponent, inputPortComponent, outputPortComponent, processGroupComponent, remoteProcessGroupComponent, funnelComponent, templateComponent, labelComponent, graphControlsCtrl, navigateCtrl, operateCtrl, breadcrumbsDirective, draggableDirective) {
|
||||
|
||||
var config = {
|
||||
urls: {
|
||||
|
@ -334,6 +337,7 @@
|
|||
nfCanvas.setManagedAuthorizer(configDetails.supportsManagedAuthorizer);
|
||||
nfCanvas.setConfigurableAuthorizer(configDetails.supportsConfigurableAuthorizer);
|
||||
nfCanvas.setConfigurableUsersAndGroups(configDetails.supportsConfigurableUsersAndGroups);
|
||||
nfCanvas.setSupportsFlowVersioning(configDetails.supportsFlowVersioning);
|
||||
|
||||
// init nfStorage
|
||||
nfStorage.init();
|
||||
|
@ -352,6 +356,7 @@
|
|||
nfQueueListing.init();
|
||||
nfVariableRegistry.init();
|
||||
nfComponentState.init();
|
||||
nfFlowVersion.init();
|
||||
nfComponentVersion.init(nfSettings);
|
||||
|
||||
// initialize the component behaviors
|
||||
|
|
|
@ -1819,6 +1819,13 @@
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether this NiFi supports flow versioning.
|
||||
*/
|
||||
supportsFlowVersioning: function () {
|
||||
return nfCanvas.supportsFlowVersioning();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether the authorizer is managed.
|
||||
*/
|
||||
|
@ -1884,7 +1891,7 @@
|
|||
*
|
||||
* @returns {boolean} can write
|
||||
*/
|
||||
canReadFromGroup: function () {
|
||||
canReadCurrentGroup: function () {
|
||||
return nfCanvas.canRead();
|
||||
},
|
||||
|
||||
|
@ -1893,7 +1900,7 @@
|
|||
*
|
||||
* @returns {boolean} can write
|
||||
*/
|
||||
canWrite: function () {
|
||||
canWriteCurrentGroup: function () {
|
||||
return nfCanvas.canWrite();
|
||||
},
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
var permissions = null;
|
||||
var parentGroupId = null;
|
||||
var managedAuthorizer = false;
|
||||
var supportsFlowVersioning = false;
|
||||
var configurableAuthorizer = false;
|
||||
var configurableUsersAndGroups = false;
|
||||
var svg = null;
|
||||
|
@ -908,6 +909,23 @@
|
|||
return managedAuthorizer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set whether this NiFi supports flow versioning.
|
||||
*
|
||||
* @param bool Whether this NiFi supports flow versioning
|
||||
*/
|
||||
setSupportsFlowVersioning: function (bool) {
|
||||
supportsFlowVersioning = bool;
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
supportsFlowVersioning: function () {
|
||||
return supportsFlowVersioning;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set whether the authorizer is configurable.
|
||||
*
|
||||
|
|
|
@ -230,7 +230,7 @@
|
|||
applyFilter();
|
||||
});
|
||||
|
||||
// initialize the processor configuration dialog
|
||||
// initialize the component state dialog
|
||||
$('#component-state-dialog').modal({
|
||||
scrollableContentStyle: 'scrollable',
|
||||
headerText: 'Component State',
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
/* global nf */
|
||||
|
||||
/**
|
||||
* Views state for a given component.
|
||||
* Handles changing the version of a component bundle.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
* @param {selection} selection The selection of currently selected components
|
||||
*/
|
||||
var canCreateTemplate = function (selection) {
|
||||
return nfCanvasUtils.canWrite() && (selection.empty() || nfCanvasUtils.canRead(selection));
|
||||
return nfCanvasUtils.canWriteCurrentGroup() && (selection.empty() || nfCanvasUtils.canRead(selection));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -106,7 +106,7 @@
|
|||
* @param {selection} selection The selection of currently selected components
|
||||
*/
|
||||
var canUploadTemplate = function (selection) {
|
||||
return nfCanvasUtils.canWrite() && selection.empty();
|
||||
return nfCanvasUtils.canWriteCurrentGroup() && selection.empty();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -369,6 +369,89 @@
|
|||
return nfCanvasUtils.isProcessGroup(selection);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the current selection supports flow versioning.
|
||||
*
|
||||
* @param selection
|
||||
*/
|
||||
var supportsFlowVersioning = function (selection) {
|
||||
if (nfCanvasUtils.supportsFlowVersioning() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selection.empty()) {
|
||||
return nfCanvasUtils.canReadCurrentGroup() && nfCanvasUtils.canWriteCurrentGroup();
|
||||
}
|
||||
|
||||
if (isProcessGroup(selection) === true) {
|
||||
return nfCanvasUtils.canRead(selection) && nfCanvasUtils.canModify(selection);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the current selection supports starting flow versioning.
|
||||
*
|
||||
* @param selection
|
||||
*/
|
||||
var supportsStartFlowVersioning = function (selection) {
|
||||
// ensure this selection supports flow versioning above
|
||||
if (supportsFlowVersioning(selection) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selection.empty()) {
|
||||
// check bread crumbs for version control information in the current group
|
||||
var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs();
|
||||
if (breadcrumbEntities.length > 0) {
|
||||
var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1];
|
||||
if (breadcrumbEntity.permissions.canRead) {
|
||||
return nfCommon.isUndefinedOrNull(breadcrumbEntity.breadcrumb.versionControlInformation);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check the selection for version control information
|
||||
var processGroupData = selection.datum();
|
||||
return nfCommon.isUndefinedOrNull(processGroupData.component.versionControlInformation);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the current selection supports stopping flow versioning.
|
||||
*
|
||||
* @param selection
|
||||
*/
|
||||
var supportsStopFlowVersioning = function (selection) {
|
||||
// ensure this selection supports flow versioning above
|
||||
if (supportsFlowVersioning(selection) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selection.empty()) {
|
||||
// check bread crumbs for version control information in the current group
|
||||
var breadcrumbEntities = nfNgBridge.injector.get('breadcrumbsCtrl').getBreadcrumbs();
|
||||
if (breadcrumbEntities.length > 0) {
|
||||
var breadcrumbEntity = breadcrumbEntities[breadcrumbEntities.length - 1];
|
||||
if (breadcrumbEntity.permissions.canRead) {
|
||||
return nfCommon.isDefinedAndNotNull(breadcrumbEntity.breadcrumb.versionControlInformation);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check the selection for version control information
|
||||
var processGroupData = selection.datum();
|
||||
return nfCommon.isDefinedAndNotNull(processGroupData.component.versionControlInformation);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the current selection could have provenance.
|
||||
*
|
||||
|
@ -548,6 +631,16 @@
|
|||
{id: 'show-details-menu-item', condition: hasDetails, menuItem: {clazz: 'fa fa-gear', text: 'View configuration', action: 'showDetails'}},
|
||||
{id: 'variable-registry-menu-item', condition: hasVariables, menuItem: {clazz: 'fa', text: 'Variables', action: 'openVariableRegistry'}},
|
||||
{separator: true},
|
||||
{id: 'version-menu-item', groupMenuItem: {clazz: 'fa', text: 'Version'}, menuItems: [
|
||||
{id: 'start-version-control-menu-item', condition: supportsStartFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Start version control', action: 'saveFlowVersion'}},
|
||||
{separator: true},
|
||||
{id: 'commit-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa fa-floppy-o', text: 'Commit local changes', action: 'saveFlowVersion'}},
|
||||
{id: 'revert-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Revert local changes', action: 'revertFlowChanges'}},
|
||||
{id: 'change-version-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Change version', action: 'changeFlowVersion'}},
|
||||
{separator: true},
|
||||
{id: 'stop-version-control-menu-item', condition: supportsStopFlowVersioning, menuItem: {clazz: 'fa', text: 'Stop version control', action: 'disconnectFlowVersioning'}}
|
||||
]},
|
||||
{separator: true},
|
||||
{id: 'enter-group-menu-item', condition: isProcessGroup, menuItem: {clazz: 'fa fa-sign-in', text: 'Enter group', action: 'enterGroup'}},
|
||||
{separator: true},
|
||||
{id: 'start-menu-item', condition: isRunnable, menuItem: {clazz: 'fa fa-play', text: 'Start', action: 'start'}},
|
||||
|
|
|
@ -0,0 +1,476 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* global define, module, require, exports */
|
||||
|
||||
/**
|
||||
* Handles versioning.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['jquery',
|
||||
'nf.ng.Bridge',
|
||||
'nf.ErrorHandler',
|
||||
'nf.Dialog',
|
||||
'nf.Common',
|
||||
'nf.Client',
|
||||
'nf.CanvasUtils',
|
||||
'nf.ProcessGroup',
|
||||
'nf.Graph'],
|
||||
function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph) {
|
||||
return (nf.FlowVersion = factory($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph));
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof module === 'object') {
|
||||
module.exports = (nf.FlowVerison =
|
||||
factory(require('jquery'),
|
||||
require('nf.ng.Bridge'),
|
||||
require('nf.ErrorHandler'),
|
||||
require('nf.Dialog'),
|
||||
require('nf.Common'),
|
||||
require('nf.Client'),
|
||||
require('nf.CanvasUtils'),
|
||||
require('nf.ProcessGroup'),
|
||||
require('nf.Graph')));
|
||||
} else {
|
||||
nf.FlowVersion = factory(root.$,
|
||||
root.nf.ng.Bridge,
|
||||
root.nf.ErrorHandler,
|
||||
root.nf.Dialog,
|
||||
root.nf.Common,
|
||||
root.nf.Client,
|
||||
root.nf.CanvasUtils,
|
||||
root.nf.ProcessGroup,
|
||||
root.nf.Graph);
|
||||
}
|
||||
}(this, function ($, nfNgBridge, nfErrorHandler, nfDialog, nfCommon, nfClient, nfCanvasUtils, nfProcessGroup, nfGraph) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Reset the dialog.
|
||||
*/
|
||||
var resetDialog = function () {
|
||||
$('#flow-version-registry-combo').combo('destroy').hide();
|
||||
$('#flow-version-bucket-combo').combo('destroy').hide();
|
||||
|
||||
$('#flow-version-registry').text('').hide();
|
||||
$('#flow-version-bucket').text('').hide();
|
||||
|
||||
$('#flow-version-name').val('');
|
||||
$('#flow-version-description').val('');
|
||||
$('#flow-version-change-comments').val('');
|
||||
|
||||
$('#flow-version-process-group-id').removeData('versionControlInformation').removeData('revision').text('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the buckets for the specified registryIdentifier for the current user.
|
||||
*
|
||||
* @param registryIdentifier
|
||||
* @returns {*}
|
||||
*/
|
||||
var loadBuckets = function (registryIdentifier) {
|
||||
return $.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/flow/registries/' + encodeURIComponent(registryIdentifier) + '/buckets',
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
var buckets = [];
|
||||
|
||||
if (nfCommon.isDefinedAndNotNull(response.buckets) && response.buckets.length > 0) {
|
||||
response.buckets.sort(function (a, b) {
|
||||
return a.bucket.name > b.bucket.name;
|
||||
});
|
||||
|
||||
$.each(response.buckets, function (_, bucketEntity) {
|
||||
var bucket = bucketEntity.bucket;
|
||||
buckets.push({
|
||||
text: bucket.name,
|
||||
value: bucket.id,
|
||||
description: nfCommon.escapeHtml(bucket.description)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
buckets.push({
|
||||
text: 'No available buckets',
|
||||
value: null,
|
||||
optionClass: 'unset',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
// load the buckets
|
||||
$('#flow-version-bucket-combo').combo('destroy').combo({
|
||||
options: buckets,
|
||||
select: selectBucket
|
||||
});
|
||||
}).fail(function () {
|
||||
$('#save-flow-version-dialog').modal('refreshButtons');
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
};
|
||||
|
||||
/**
|
||||
* Select handler for the registries combo.
|
||||
*
|
||||
* @param selectedOption
|
||||
*/
|
||||
var selectRegistry = function (selectedOption) {
|
||||
if (selectedOption.disabled === true) {
|
||||
$('#flow-version-bucket-combo').combo('destroy').combo({
|
||||
options: [{
|
||||
text: 'No available buckets',
|
||||
value: null,
|
||||
optionClass: 'unset',
|
||||
disabled: true
|
||||
}]
|
||||
});
|
||||
|
||||
$('#save-flow-version-dialog').modal('refreshButtons');
|
||||
} else {
|
||||
loadBuckets(selectedOption.value);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Select handler for the buckets combo.
|
||||
*
|
||||
* @param selectedOption
|
||||
*/
|
||||
var selectBucket = function (selectedOption) {
|
||||
$('#save-flow-version-dialog').modal('refreshButtons');
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves a flow version.
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
var saveFlowVersion = function () {
|
||||
var processGroupId = $('#flow-version-process-group-id').text();
|
||||
var processGroupRevision = $('#flow-version-process-group-id').data('revision');
|
||||
|
||||
var saveFlowVersionRequest = {
|
||||
processGroupRevision: nfClient.getRevision({
|
||||
revision: {
|
||||
version: processGroupRevision.version
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
var versionControlInformation = $('#flow-version-process-group-id').data('versionControlInformation');
|
||||
if (nfCommon.isDefinedAndNotNull(versionControlInformation)) {
|
||||
saveFlowVersionRequest['versionedFlow'] = {
|
||||
registryId: versionControlInformation.registryId,
|
||||
bucketId: versionControlInformation.bucketId,
|
||||
flowId: versionControlInformation.flowId,
|
||||
flowName: $('#flow-version-name').val(),
|
||||
description: $('#flow-version-description').val(),
|
||||
comments: $('#flow-version-change-comments').val()
|
||||
}
|
||||
} else {
|
||||
var selectedRegistry = $('#flow-version-registry-combo').combo('getSelectedOption');
|
||||
var selectedBucket = $('#flow-version-bucket-combo').combo('getSelectedOption');
|
||||
|
||||
saveFlowVersionRequest['versionedFlow'] = {
|
||||
registryId: selectedRegistry.value,
|
||||
bucketId: selectedBucket.value,
|
||||
flowName: $('#flow-version-name').val(),
|
||||
description: $('#flow-version-description').val(),
|
||||
comments: $('#flow-version-change-comments').val()
|
||||
}
|
||||
}
|
||||
|
||||
return $.ajax({
|
||||
type: 'POST',
|
||||
data: JSON.stringify(saveFlowVersionRequest),
|
||||
url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
};
|
||||
|
||||
return {
|
||||
init: function () {
|
||||
// initialize the flow version dialog
|
||||
$('#save-flow-version-dialog').modal({
|
||||
scrollableContentStyle: 'scrollable',
|
||||
headerText: 'Save Flow Version',
|
||||
buttons: [{
|
||||
buttonText: 'Save',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
disabled: function () {
|
||||
if ($('#flow-version-registry-combo').is(':visible')) {
|
||||
var selectedRegistry = $('#flow-version-registry-combo').combo('getSelectedOption');
|
||||
var selectedBucket = $('#flow-version-bucket-combo').combo('getSelectedOption');
|
||||
|
||||
if (nfCommon.isDefinedAndNotNull(selectedRegistry) && nfCommon.isDefinedAndNotNull(selectedBucket)) {
|
||||
return selectedRegistry.disabled === true || selectedBucket.disabled === true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
var processGroupId = $('#flow-version-process-group-id').text();
|
||||
|
||||
saveFlowVersion().done(function (response) {
|
||||
// refresh either selected PG or bread crumb to reflect connected/tracking status
|
||||
if (nfCanvasUtils.getGroupId() === processGroupId) {
|
||||
nfNgBridge.injector.get('breadcrumbsCtrl').updateVersionControlInformation(processGroupId, response.versionControlInformation);
|
||||
nfNgBridge.digest();
|
||||
} else {
|
||||
nfProcessGroup.reload(processGroupId);
|
||||
}
|
||||
|
||||
// close the dialog
|
||||
$('#save-flow-version-dialog').modal('hide');
|
||||
});
|
||||
}
|
||||
}
|
||||
}, {
|
||||
buttonText: 'Cancel',
|
||||
color: {
|
||||
base: '#E3E8EB',
|
||||
hover: '#C7D2D7',
|
||||
text: '#004849'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}],
|
||||
handler: {
|
||||
close: function () {
|
||||
resetDialog();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the flow version dialog.
|
||||
*
|
||||
* @param processGroupId
|
||||
*/
|
||||
showFlowVersionDialog: function (processGroupId) {
|
||||
return $.Deferred(function (deferred) {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
// record the revision
|
||||
$('#flow-version-process-group-id').data('revision', response.processGroupRevision).text(processGroupId);
|
||||
|
||||
if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) {
|
||||
var versionControlInformation = response.versionControlInformation;
|
||||
|
||||
// update the registry and bucket visibility
|
||||
$('#flow-version-registry').text(versionControlInformation.registryId).show();
|
||||
$('#flow-version-bucket').text(versionControlInformation.bucketId).show();
|
||||
|
||||
$('#flow-version-name').val('');
|
||||
$('#flow-version-description').val('');
|
||||
|
||||
// record the versionControlInformation
|
||||
$('#flow-version-process-group-id').data('versionControlInformation', versionControlInformation)
|
||||
|
||||
deferred.resolve();
|
||||
} else {
|
||||
// update the registry and bucket visibility
|
||||
$('#flow-version-registry-combo').show();
|
||||
$('#flow-version-bucket-combo').show();
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/flow/registries',
|
||||
dataType: 'json'
|
||||
}).done(function (registriesResponse) {
|
||||
var registries = [];
|
||||
|
||||
if (nfCommon.isDefinedAndNotNull(registriesResponse.registries) && registriesResponse.registries.length > 0) {
|
||||
registriesResponse.registries.sort(function (a, b) {
|
||||
return a.component.name > b.component.name;
|
||||
});
|
||||
|
||||
$.each(registriesResponse.registries, function (_, registryEntity) {
|
||||
var registry = registryEntity.component;
|
||||
registries.push({
|
||||
text: registry.name,
|
||||
value: registry.id,
|
||||
description: nfCommon.escapeHtml(registry.description)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
registries.push({
|
||||
text: 'No available registries',
|
||||
value: null,
|
||||
optionClass: 'unset',
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
||||
// load the registries
|
||||
$('#flow-version-registry-combo').combo({
|
||||
options: registries,
|
||||
select: selectRegistry
|
||||
});
|
||||
|
||||
deferred.resolve();
|
||||
}).fail(function () {
|
||||
deferred.reject();
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
}
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
}).done(function () {
|
||||
$('#save-flow-version-dialog').modal('show');
|
||||
}).fail(function () {
|
||||
$('#save-flow-version-dialog').modal('refreshButtons');
|
||||
}).promise();
|
||||
},
|
||||
|
||||
/**
|
||||
* Reverts changes for the specified Process Group.
|
||||
*
|
||||
* @param processGroupId
|
||||
*/
|
||||
revertFlowChanges: function (processGroupId) {
|
||||
// prompt the user before reverting
|
||||
nfDialog.showYesNoDialog({
|
||||
headerText: 'Revert Changes',
|
||||
dialogContent: 'Are you sure you want to revert changes? All flow configuration changes will be reverted to the last version.',
|
||||
noText: 'Cancel',
|
||||
yesText: 'Revert',
|
||||
yesHandler: function () {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) {
|
||||
var revertFlowVersionRequest = {
|
||||
processGroupRevision: nfClient.getRevision({
|
||||
revision: {
|
||||
version: response.processGroupRevision.version
|
||||
}
|
||||
}),
|
||||
versionControlInformation: response.versionControlInformation
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
data: JSON.stringify(revertFlowVersionRequest),
|
||||
url: '../nifi-api/versions/revert-requests/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (response) {
|
||||
// TODO update multi step to show user the ramifications of reverting for confirmation
|
||||
|
||||
if (nfCanvasUtils.getGroupId() === processGroupId) {
|
||||
// if reverting current PG... reload/refresh this group/canvas
|
||||
// TODO consider implementing this differently
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/flow/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
nfGraph.set(response.processGroupFlow.flow);
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
} else {
|
||||
// if reverting selected PG... reload selected PG to update counts, etc
|
||||
nfProcessGroup.reload(processGroupId);
|
||||
}
|
||||
|
||||
nfDialog.showOkDialog({
|
||||
headerText: 'Revert Changes',
|
||||
dialogContent: 'This Process Group has been reverted.'
|
||||
});
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
} else {
|
||||
nfDialog.showOkDialog({
|
||||
headerText: 'Revert Changes',
|
||||
dialogContent: 'This Process Group is not currently under version control.'
|
||||
});
|
||||
}
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Disconnects the specified Process Group from flow versioning.
|
||||
*
|
||||
* @param processGroupId
|
||||
*/
|
||||
disconnectFlowVersioning: function (processGroupId) {
|
||||
// prompt the user before disconnecting
|
||||
nfDialog.showYesNoDialog({
|
||||
headerText: 'Disconnect',
|
||||
dialogContent: 'Are you sure you want to disconnect?',
|
||||
noText: 'Cancel',
|
||||
yesText: 'Disconnect',
|
||||
yesHandler: function () {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId),
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
if (nfCommon.isDefinedAndNotNull(response.versionControlInformation)) {
|
||||
var revision = nfClient.getRevision({
|
||||
revision: {
|
||||
version: response.processGroupRevision.version
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: '../nifi-api/versions/process-groups/' + encodeURIComponent(processGroupId) + '?' + $.param(revision),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (response) {
|
||||
// refresh either selected PG or bread crumb to reflect disconnected status
|
||||
if (nfCanvasUtils.getGroupId() === processGroupId) {
|
||||
nfNgBridge.injector.get('breadcrumbsCtrl').updateVersionControlInformation(processGroupId, undefined);
|
||||
nfNgBridge.digest();
|
||||
} else {
|
||||
nfProcessGroup.reload(processGroupId);
|
||||
}
|
||||
|
||||
nfDialog.showOkDialog({
|
||||
headerText: 'Disconnect',
|
||||
dialogContent: 'This Process Group has been disconnected.'
|
||||
});
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
} else {
|
||||
nfDialog.showOkDialog({
|
||||
headerText: 'Disconnect',
|
||||
dialogContent: 'This Process Group is not currently under version control.'
|
||||
})
|
||||
}
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}));
|
|
@ -215,7 +215,7 @@
|
|||
$('#process-group-configuration').data('process-group', {
|
||||
'permissions': {
|
||||
canRead: false,
|
||||
canWrite: nfCanvasUtils.canWrite()
|
||||
canWrite: nfCanvasUtils.canWriteCurrentGroup()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -180,6 +180,15 @@
|
|||
'class': 'process-group-name'
|
||||
});
|
||||
|
||||
// process group name
|
||||
processGroup.append('text')
|
||||
.attr({
|
||||
'x': 3,
|
||||
'y': 17,
|
||||
'class': 'version-control'
|
||||
})
|
||||
.text('\uf00c');
|
||||
|
||||
// always support selecting and navigation
|
||||
processGroup.on('dblclick', function (d) {
|
||||
// enter this group on double click
|
||||
|
@ -868,12 +877,18 @@
|
|||
}).append('title').text(function (d) {
|
||||
return d.component.name;
|
||||
});
|
||||
|
||||
// update version control information
|
||||
processGroup.select('text.version-control').style('visibility', nfCommon.isDefinedAndNotNull(processGroupData.component.versionControlInformation) ? 'visible' : 'hidden');
|
||||
} else {
|
||||
// clear the process group comments
|
||||
details.select('text.process-group-comments').text(null);
|
||||
|
||||
// clear the process group name
|
||||
processGroup.select('text.process-group-name').text(null);
|
||||
|
||||
// update version control information
|
||||
processGroup.select('text.version-control').style('visibility', false);
|
||||
}
|
||||
|
||||
// populate the stats
|
||||
|
|
|
@ -81,7 +81,9 @@
|
|||
controllerConfig: '../nifi-api/controller/config',
|
||||
reportingTaskTypes: '../nifi-api/flow/reporting-task-types',
|
||||
createReportingTask: '../nifi-api/controller/reporting-tasks',
|
||||
reportingTasks: '../nifi-api/flow/reporting-tasks'
|
||||
reportingTasks: '../nifi-api/flow/reporting-tasks',
|
||||
createRegistry: '../nifi-api/controller/registries',
|
||||
registries: '../nifi-api/flow/registries'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -464,6 +466,94 @@
|
|||
return addTask;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the specified entity.
|
||||
*/
|
||||
var addRegistry = function () {
|
||||
var registryEntity = {
|
||||
'revision': nfClient.getRevision({
|
||||
'revision': {
|
||||
'version': 0
|
||||
}
|
||||
}),
|
||||
'component': {
|
||||
'name': $('#registry-name').val(),
|
||||
'uri': $('#registry-location').val(),
|
||||
'description': $('#registry-description').val()
|
||||
}
|
||||
};
|
||||
|
||||
// add the new registry
|
||||
var addRegistry = $.ajax({
|
||||
type: 'POST',
|
||||
url: config.urls.createRegistry,
|
||||
data: JSON.stringify(registryEntity),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (registryEntity) {
|
||||
// add the item
|
||||
var registriesGrid = $('#registries-table').data('gridInstance');
|
||||
var registriesData = registriesGrid.getData();
|
||||
registriesData.addItem($.extend({
|
||||
type: 'Registry'
|
||||
}, registryEntity));
|
||||
|
||||
// resort
|
||||
registriesData.reSort();
|
||||
registriesGrid.invalidate();
|
||||
|
||||
// select the new reporting task
|
||||
var row = registriesData.getRowById(registryEntity.id);
|
||||
nfFilteredDialogCommon.choseRow(registriesGrid, row);
|
||||
registriesGrid.scrollRowIntoView(row);
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
|
||||
// hide the dialog
|
||||
$('#registry-configuration-dialog').modal('hide');
|
||||
|
||||
return addRegistry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the registry with the specified id.
|
||||
*
|
||||
* @param registryId
|
||||
*/
|
||||
var updateRegistry = function (registryId) {
|
||||
var registriesGrid = $('#registries-table').data('gridInstance');
|
||||
var registriesData = registriesGrid.getData();
|
||||
|
||||
var registryEntity = registriesData.getItemById(registryId);
|
||||
var requestRegistryEntity = {
|
||||
'revision': nfClient.getRevision(registryEntity),
|
||||
'component': {
|
||||
'id': registryId,
|
||||
'name': $('#registry-name').val(),
|
||||
'uri': $('#registry-location').val(),
|
||||
'description': $('#registry-description').val()
|
||||
}
|
||||
};
|
||||
|
||||
// add the new reporting task
|
||||
var updateRegistry = $.ajax({
|
||||
type: 'PUT',
|
||||
url: registryEntity.uri,
|
||||
data: JSON.stringify(requestRegistryEntity),
|
||||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (registryEntity) {
|
||||
// add the item
|
||||
registriesData.updateItem(registryId, $.extend({
|
||||
type: 'Registry'
|
||||
}, registryEntity));
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
|
||||
// hide the dialog
|
||||
$('#registry-configuration-dialog').modal('hide');
|
||||
|
||||
return updateRegistry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the new reporting task dialog.
|
||||
*/
|
||||
|
@ -783,6 +873,20 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// initialize the registry configuration dialog
|
||||
$('#registry-configuration-dialog').modal({
|
||||
scrollableContentStyle: 'scrollable',
|
||||
headerText: 'Add Registry',
|
||||
handler: {
|
||||
close: function () {
|
||||
$('#registry-id').text('');
|
||||
$('#registry-name').val('');
|
||||
$('#registry-location').val('');
|
||||
$('#registry-description').val('');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1090,6 +1194,228 @@
|
|||
});
|
||||
};
|
||||
|
||||
var initRegistriesTable = function () {
|
||||
|
||||
var locationFormatter = function (row, cell, value, columnDef, dataContext) {
|
||||
if (!dataContext.permissions.canRead) {
|
||||
return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
|
||||
}
|
||||
|
||||
return nfCommon.escapeHtml(dataContext.component.uri);
|
||||
};
|
||||
|
||||
var descriptionFormatter = function (row, cell, value, columnDef, dataContext) {
|
||||
if (!dataContext.permissions.canRead) {
|
||||
return '<span class="blank">' + nfCommon.escapeHtml(dataContext.id) + '</span>';
|
||||
}
|
||||
|
||||
return nfCommon.escapeHtml(dataContext.component.description);
|
||||
};
|
||||
|
||||
var registriesActionFormatter = function (row, cell, value, columnDef, dataContext) {
|
||||
var markup = '';
|
||||
|
||||
if (nfCommon.canModifyController()) {
|
||||
// edit registry
|
||||
markup += '<div title="Edit" class="pointer edit-registry fa fa-pencil" style="margin-top: 2px; margin-right: 3px;" ></div>';
|
||||
|
||||
// remove registry
|
||||
markup += '<div title="Remove" class="pointer remove-registry fa fa-trash" style="margin-top: 2px; margin-right: 3px;" ></div>';
|
||||
}
|
||||
|
||||
return markup;
|
||||
};
|
||||
|
||||
// define the column model for the reporting tasks table
|
||||
var registriesColumnModel = [
|
||||
{
|
||||
id: 'name',
|
||||
name: 'Name',
|
||||
field: 'name',
|
||||
formatter: nameFormatter,
|
||||
sortable: true,
|
||||
resizable: true
|
||||
},
|
||||
{
|
||||
id: 'uri',
|
||||
name: 'Location',
|
||||
field: 'uri',
|
||||
formatter: locationFormatter,
|
||||
sortable: true,
|
||||
resizable: true
|
||||
},
|
||||
{
|
||||
id: 'description',
|
||||
name: 'Description',
|
||||
field: 'description',
|
||||
formatter: descriptionFormatter,
|
||||
sortable: true,
|
||||
resizable: true
|
||||
}
|
||||
];
|
||||
|
||||
// action column should always be last
|
||||
registriesColumnModel.push({
|
||||
id: 'actions',
|
||||
name: ' ',
|
||||
resizable: false,
|
||||
formatter: registriesActionFormatter,
|
||||
sortable: false,
|
||||
width: 90,
|
||||
maxWidth: 90
|
||||
});
|
||||
|
||||
// initialize the dataview
|
||||
var registriesData = new Slick.Data.DataView({
|
||||
inlineFilters: false
|
||||
});
|
||||
registriesData.setItems([]);
|
||||
|
||||
// initialize the sort
|
||||
sort({
|
||||
columnId: 'name',
|
||||
sortAsc: true
|
||||
}, registriesData);
|
||||
|
||||
// initialize the grid
|
||||
var registriesGrid = new Slick.Grid('#registries-table', registriesData, registriesColumnModel, gridOptions);
|
||||
registriesGrid.setSelectionModel(new Slick.RowSelectionModel());
|
||||
registriesGrid.registerPlugin(new Slick.AutoTooltips());
|
||||
registriesGrid.setSortColumn('name', true);
|
||||
registriesGrid.onSort.subscribe(function (e, args) {
|
||||
sort({
|
||||
columnId: args.sortCol.id,
|
||||
sortAsc: args.sortAsc
|
||||
}, registriesData);
|
||||
});
|
||||
|
||||
// configure a click listener
|
||||
registriesGrid.onClick.subscribe(function (e, args) {
|
||||
var target = $(e.target);
|
||||
|
||||
// get the service at this row
|
||||
var registryEntity = registriesData.getItem(args.row);
|
||||
|
||||
// determine the desired action
|
||||
if (registriesGrid.getColumns()[args.cell].id === 'actions') {
|
||||
if (target.hasClass('edit-registry')) {
|
||||
editRegistry(registryEntity);
|
||||
} else if (target.hasClass('remove-registry')) {
|
||||
promptToRemoveRegistry(registryEntity);
|
||||
}
|
||||
} else if (registriesGrid.getColumns()[args.cell].id === 'moreDetails') {
|
||||
// if (target.hasClass('view-reporting-task')) {
|
||||
// nfReportingTask.showDetails(reportingTaskEntity);
|
||||
// } else if (target.hasClass('reporting-task-usage')) {
|
||||
// // close the settings dialog
|
||||
// $('#shell-close-button').click();
|
||||
//
|
||||
// // open the documentation for this reporting task
|
||||
// nfShell.showPage('../nifi-docs/documentation?' + $.param({
|
||||
// select: reportingTaskEntity.component.type,
|
||||
// group: reportingTaskEntity.component.bundle.group,
|
||||
// artifact: reportingTaskEntity.component.bundle.artifact,
|
||||
// version: reportingTaskEntity.component.bundle.version
|
||||
// })).done(function () {
|
||||
// nfSettings.showSettings();
|
||||
// });
|
||||
// }
|
||||
}
|
||||
});
|
||||
|
||||
// wire up the dataview to the grid
|
||||
registriesData.onRowCountChanged.subscribe(function (e, args) {
|
||||
registriesGrid.updateRowCount();
|
||||
registriesGrid.render();
|
||||
});
|
||||
registriesData.onRowsChanged.subscribe(function (e, args) {
|
||||
registriesGrid.invalidateRows(args.rows);
|
||||
registriesGrid.render();
|
||||
});
|
||||
registriesData.syncGridSelection(registriesGrid, true);
|
||||
|
||||
// hold onto an instance of the grid
|
||||
$('#registries-table').data('gridInstance', registriesGrid);
|
||||
};
|
||||
|
||||
/**
|
||||
* Edits the specified registry entity.
|
||||
*
|
||||
* @param registryEntity
|
||||
*/
|
||||
var editRegistry = function (registryEntity) {
|
||||
// populate the dialog
|
||||
$('#registry-id').text(registryEntity.id);
|
||||
$('#registry-name').val(registryEntity.component.name);
|
||||
$('#registry-location').val(registryEntity.component.uri);
|
||||
$('#registry-description').val(registryEntity.component.description);
|
||||
|
||||
// show the dialog
|
||||
$('#registry-configuration-dialog').modal('setButtonModel', [{
|
||||
buttonText: 'Update',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
updateRegistry(registryEntity.id);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
buttonText: 'Cancel',
|
||||
color: {
|
||||
base: '#E3E8EB',
|
||||
hover: '#C7D2D7',
|
||||
text: '#004849'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}]).modal('show');
|
||||
};
|
||||
|
||||
/**
|
||||
* Prompts the user before attempting to delete the specified registry.
|
||||
*
|
||||
* @param {object} registryEntity
|
||||
*/
|
||||
var promptToRemoveRegistry = function (registryEntity) {
|
||||
// prompt for deletion
|
||||
nfDialog.showYesNoDialog({
|
||||
headerText: 'Delete Registry',
|
||||
dialogContent: 'Delete registry \'' + nfCommon.escapeHtml(registryEntity.component.name) + '\'?',
|
||||
yesHandler: function () {
|
||||
removeRegistry(registryEntity);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes the specified registry.
|
||||
*
|
||||
* @param {object} registryEntity
|
||||
*/
|
||||
var removeRegistry = function (registryEntity) {
|
||||
var revision = nfClient.getRevision(registryEntity);
|
||||
$.ajax({
|
||||
type: 'DELETE',
|
||||
url: registryEntity.uri + '?' + $.param({
|
||||
version: revision.version,
|
||||
clientId: revision.clientId
|
||||
}),
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
// remove the task
|
||||
var registryGrid = $('#registries-table').data('gridInstance');
|
||||
var registryData = registryGrid.getData();
|
||||
registryData.deleteItem(registryEntity.id);
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the settings.
|
||||
*/
|
||||
|
@ -1158,6 +1484,9 @@
|
|||
// load the reporting tasks
|
||||
var reportingTasks = loadReportingTasks();
|
||||
|
||||
// load the registries
|
||||
var registries = loadRegistries();
|
||||
|
||||
// return a deferred for all parts of the settings
|
||||
return $.when(settings, controllerServicesXhr, reportingTasks).done(function (settingsResult, controllerServicesResult) {
|
||||
var controllerServicesResponse = controllerServicesResult[0];
|
||||
|
@ -1198,6 +1527,32 @@
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the registries.
|
||||
*/
|
||||
var loadRegistries = function () {
|
||||
return $.ajax({
|
||||
type: 'GET',
|
||||
url: config.urls.registries,
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
var registries = [];
|
||||
$.each(response.registries, function (_, registryEntity) {
|
||||
registries.push($.extend({
|
||||
type: 'Registry'
|
||||
}, registryEntity));
|
||||
});
|
||||
|
||||
var registriesGrid = $('#registries-table').data('gridInstance');
|
||||
var registriesData = registriesGrid.getData();
|
||||
|
||||
// update the registries
|
||||
registriesData.setItems(registries);
|
||||
registriesData.reSort();
|
||||
registriesGrid.invalidate();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the process group configuration.
|
||||
*/
|
||||
|
@ -1241,6 +1596,9 @@
|
|||
}, {
|
||||
name: 'Reporting Tasks',
|
||||
tabContentId: 'reporting-tasks-tab-content'
|
||||
}, {
|
||||
name: 'Registries',
|
||||
tabContentId: 'registries-tab-content'
|
||||
}],
|
||||
select: function () {
|
||||
var tab = $(this).text();
|
||||
|
@ -1267,6 +1625,9 @@
|
|||
} else if (tab === 'Reporting Tasks') {
|
||||
$('#settings-save').hide();
|
||||
return 'Create a new reporting task';
|
||||
} else if (tab === 'Registries') {
|
||||
$('#settings-save').hide();
|
||||
return 'Register a new registry';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -1276,7 +1637,7 @@
|
|||
|
||||
if (tab === 'Reporting Task Controller Services') {
|
||||
$('#controller-cs-availability').show();
|
||||
} else if (tab === 'Reporting Tasks') {
|
||||
} else if (tab === 'Reporting Tasks' || tab === 'Registries') {
|
||||
$('#controller-cs-availability').hide();
|
||||
}
|
||||
|
||||
|
@ -1315,6 +1676,32 @@
|
|||
|
||||
// set the initial focus
|
||||
$('#reporting-task-type-filter').focus();
|
||||
} else if (selectedTab === 'Registries') {
|
||||
$('#registry-configuration-dialog').modal('setButtonModel', [{
|
||||
buttonText: 'Add',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
addRegistry();
|
||||
}
|
||||
}
|
||||
}, {
|
||||
buttonText: 'Cancel',
|
||||
color: {
|
||||
base: '#E3E8EB',
|
||||
hover: '#C7D2D7',
|
||||
text: '#004849'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}]).modal('show');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1322,6 +1709,7 @@
|
|||
initGeneral();
|
||||
nfControllerServices.init(getControllerServicesTable(), nfSettings.showSettings);
|
||||
initReportingTasks();
|
||||
initRegistriesTable();
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@ limitations under the License.
|
|||
<span ng-if="separatorFunc(crumb.parentBreadcrumb)" style="margin: 0 12px;">
|
||||
»
|
||||
</span>
|
||||
<span ng-if="separatorFunc(crumb.breadcrumb.versionControlInformation)" class="breadcrumb-version-control fa fa-check" style="margin: 0 6px;"></span>
|
||||
<span class="link"
|
||||
ng-class="(highlightCrumbId === crumb.id) ? 'link-bold' : ''"
|
||||
ng-click="clickFunc(crumb.id)">
|
||||
|
|
Loading…
Reference in New Issue