diff --git a/CHANGELOG.md b/CHANGELOG.md index cbfa4c39eb3..cef697bcc84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ The Change Log summarizes the changes in Cloudbreak. - update HDP version (2.6.0.3 -> 2.6.1.0) - update Ambari version (2.5.0.3 -> 2.5.1.0) - +- disable Knox from CB if blueprint contains Knox ## [v1.15.0] diff --git a/shell/src/main/java/com/sequenceiq/cloudbreak/shell/commands/common/ClusterCommands.java b/shell/src/main/java/com/sequenceiq/cloudbreak/shell/commands/common/ClusterCommands.java index ec099ad8ebb..08a367e29aa 100644 --- a/shell/src/main/java/com/sequenceiq/cloudbreak/shell/commands/common/ClusterCommands.java +++ b/shell/src/main/java/com/sequenceiq/cloudbreak/shell/commands/common/ClusterCommands.java @@ -1,15 +1,21 @@ package com.sequenceiq.cloudbreak.shell.commands.common; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import org.apache.http.MethodNotSupportedException; import org.springframework.shell.core.annotation.CliAvailabilityIndicator; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.sequenceiq.cloudbreak.api.model.AmbariRepoDetailsJson; @@ -35,6 +41,7 @@ import com.sequenceiq.cloudbreak.shell.completion.HostGroup; import com.sequenceiq.cloudbreak.shell.model.Hints; import com.sequenceiq.cloudbreak.shell.model.HostgroupEntry; +import com.sequenceiq.cloudbreak.shell.model.InstanceGroupEntry; import com.sequenceiq.cloudbreak.shell.model.MarathonHostgroupEntry; import com.sequenceiq.cloudbreak.shell.model.NodeCountEntry; import com.sequenceiq.cloudbreak.shell.model.OutPutType; @@ -77,7 +84,7 @@ public boolean createAvailable() { public String createCluster( @CliOption(key = "userName", unspecifiedDefaultValue = "admin", help = "Username of the Ambari server") String userName, @CliOption(key = "password", unspecifiedDefaultValue = "admin", help = "Password of the Ambari server") String password, - @CliOption(key = "description", help = "Description of the blueprint") String description, + @CliOption(key = "description", help = "Description of the cluster") String description, @CliOption(key = "ambariVersion", help = "Ambari version (e.g. 2.4.0.0-748)") String ambariVersion, @CliOption(key = "ambariRepoBaseURL", help = "Ambari repo base url: http://public-repo-1.hortonworks.com/ambari/centos6/2.x/updates") String ambariRepoBaseURL, @@ -198,6 +205,30 @@ public String createCluster( clusterRequest.setBlueprintInputs(new HashSet<>()); clusterRequest.setCustomQueue(customQueue); + if (enableKnoxGateway) { + // Check if Knox is configured in selected blueprint + List gatewayIgList = shellContext.getInstanceGroups().values() + .stream() + .filter(e -> e.getType().equals("GATEWAY")).collect(Collectors.toList()); + List gatewayIgNameList = new ArrayList<>(); + + for (Map.Entry entry : shellContext.getInstanceGroups().entrySet()) { + for (InstanceGroupEntry gatewayIg : gatewayIgList) { + if (Objects.equals(gatewayIg, entry.getValue())) { + gatewayIgNameList.add(entry.getKey()); + } + } + } + Map> componentMap = getComponentMap(shellContext.getBlueprintText()); + + for (String gatewayIgName : gatewayIgNameList) { + if (componentMap.get(gatewayIgName).contains("KNOX_GATEWAY")) { + throw shellContext.exceptionTransformer().transformToRuntimeException( + "Please select another blueprint! Knox gateway is enabled but it is present in the blueprint's gateway hostgroup as well."); + } + } + } + GatewayJson gateway = new GatewayJson(); gateway.setEnableGateway(enableKnoxGateway); gateway.setExposedServices(ImmutableList.of(ExposedService.ALL.name())); @@ -642,6 +673,24 @@ public String upgradeCluster( return "Upgrade request successfully sent"; } + private Map> getComponentMap(String json) { + Map> map = new HashMap<>(); + try { + JsonNode hostGroups = shellContext.objectMapper().readTree(json.getBytes()).get("host_groups"); + for (JsonNode hostGroup : hostGroups) { + List components = new ArrayList<>(); + JsonNode componentsNodes = hostGroup.get("components"); + for (JsonNode componentsNode : componentsNodes) { + components.add(componentsNode.get("name").asText()); + } + map.put(hostGroup.get("name").asText(), components); + } + } catch (IOException e) { + map = new HashMap<>(); + } + return map; + } + @Override public ShellContext shellContext() { return shellContext; diff --git a/shell/src/main/java/com/sequenceiq/cloudbreak/shell/model/InstanceGroupEntry.java b/shell/src/main/java/com/sequenceiq/cloudbreak/shell/model/InstanceGroupEntry.java index f603cf34876..8facc245fd8 100644 --- a/shell/src/main/java/com/sequenceiq/cloudbreak/shell/model/InstanceGroupEntry.java +++ b/shell/src/main/java/com/sequenceiq/cloudbreak/shell/model/InstanceGroupEntry.java @@ -45,4 +45,30 @@ public void setType(String type) { public Map getAttributes() { return attributes; } + + //BEGIN GENERATED CODE + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + InstanceGroupEntry that = (InstanceGroupEntry) o; + + if (templateId != null ? !templateId.equals(that.templateId) : that.templateId != null) return false; + if (nodeCount != null ? !nodeCount.equals(that.nodeCount) : that.nodeCount != null) return false; + if (type != null ? !type.equals(that.type) : that.type != null) return false; + if (securityGroupId != null ? !securityGroupId.equals(that.securityGroupId) : that.securityGroupId != null) return false; + return attributes != null ? attributes.equals(that.attributes) : that.attributes == null; + } + + @Override + public int hashCode() { + int result = templateId != null ? templateId.hashCode() : 0; + result = 31 * result + (nodeCount != null ? nodeCount.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + result = 31 * result + (securityGroupId != null ? securityGroupId.hashCode() : 0); + result = 31 * result + (attributes != null ? attributes.hashCode() : 0); + return result; + } + //END GENERATED CODE } diff --git a/web/app/static/js/controllers/clusterController.js b/web/app/static/js/controllers/clusterController.js index fff6de3a268..d12ad2bfd68 100644 --- a/web/app/static/js/controllers/clusterController.js +++ b/web/app/static/js/controllers/clusterController.js @@ -275,6 +275,8 @@ angular.module('uluwatuControllers').controller('clusterController', ['$scope', $scope.cluster.hostGroups = hostGroups; $scope.cluster.activeGroup = $scope.cluster.hostGroups[0].name; } + + $scope.showBlueprintKnoxError(); } $scope.isUndefined = function(variable) { @@ -1516,6 +1518,7 @@ angular.module('uluwatuControllers').controller('clusterController', ['$scope', ig.type = 'CORE' } }); + $scope.showBlueprintKnoxError(); } $scope.ambariServerSelected = function() { @@ -1533,6 +1536,33 @@ angular.module('uluwatuControllers').controller('clusterController', ['$scope', return result } + $scope.blueprintKnoxError = false; + + $scope.showBlueprintKnoxError = function() { + var result = false; + var actualBp = $filter('filter')($rootScope.blueprints, { + id: $scope.cluster.blueprintId + }, true); + actualBp[0].ambariBlueprint.host_groups.forEach(function (group) { + if (!result) { + var gatewayGroup = $filter('filter')($scope.cluster.instanceGroups, { + group: group.name, + type: 'GATEWAY' + }, true); + if (gatewayGroup && gatewayGroup[0]) { + var knoxGateway = $filter('filter')(group.components, { + name: 'KNOX_GATEWAY' + }, true); + if (knoxGateway && knoxGateway[0]) { + result = true; + } + } + } + }); + $scope.blueprintKnoxError = result; + return result; + } + $scope.showSecurityGroupKnoxWarning = function(instanceGroup) { var result = false; if ($rootScope.securitygroups && diff --git a/web/app/static/messages.properties b/web/app/static/messages.properties index 6c04b19b07c..98051951cde 100644 --- a/web/app/static/messages.properties +++ b/web/app/static/messages.properties @@ -517,6 +517,7 @@ "use_custom_container_popup": "Please use certified containers", "custom_image_id_placeholder": "ami-xxxxxxxx", "cluster_form_blueprint_validate_label": "Validate Blueprint", + "cluster_form_blueprint_knox_error": "Please select another blueprint! Knox gateway is enabled but it is present in the blueprint's gateway hostgroup as well.", "cluster_form_hostgroup_label": "Hostgroup Configuration", "cluster_form_hostgroup_template_label": "Template", "cluster_form_hostgroup_ambari_label": "Ambari Server", diff --git a/web/app/static/tags/stack/clusterform.tag b/web/app/static/tags/stack/clusterform.tag index 82405d35a97..4c2f01982c7 100644 --- a/web/app/static/tags/stack/clusterform.tag +++ b/web/app/static/tags/stack/clusterform.tag @@ -18,12 +18,12 @@ {{msg.cluster_form_ambari_cluster_tag}} {{msg.cluster_form_ambari_network_tag}} {{msg.cluster_form_ambari_blueprint_tag}} - {{msg.cluster_form_ambari_filesystem_tag}} - {{msg.cluster_form_ambari_failure_tag}} - {{msg.cluster_form_ambari_repo_tag}} - {{msg.cluster_form_ambari_hdprepo_tag}} - {{msg.cluster_form_ambari_database_tag}} - {{msg.cluster_form_ambari_launch_tag}} + {{msg.cluster_form_ambari_filesystem_tag}} + {{msg.cluster_form_ambari_failure_tag}} + {{msg.cluster_form_ambari_repo_tag}} + {{msg.cluster_form_ambari_hdprepo_tag}} + {{msg.cluster_form_ambari_database_tag}} + {{msg.cluster_form_ambari_launch_tag}}
diff --git a/web/app/static/tags/stack/configurehostgroups.tag b/web/app/static/tags/stack/configurehostgroups.tag index 1bf2abde3ea..04198d63845 100644 --- a/web/app/static/tags/stack/configurehostgroups.tag +++ b/web/app/static/tags/stack/configurehostgroups.tag @@ -3,6 +3,7 @@
+
{{msg.cluster_form_blueprint_knox_error}}
@@ -152,15 +153,15 @@
- +
-
-