Skip to content

Commit

Permalink
CLOUD-80489 Disable Knox from CB if blueprint contains Knox
Browse files Browse the repository at this point in the history
  • Loading branch information
pdarvasi authored and akanto committed Jun 9, 2017
1 parent 930a1c2 commit 3928e12
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 11 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -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]

Expand Down
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<InstanceGroupEntry> gatewayIgList = shellContext.getInstanceGroups().values()
.stream()
.filter(e -> e.getType().equals("GATEWAY")).collect(Collectors.toList());
List<String> gatewayIgNameList = new ArrayList<>();

for (Map.Entry<String, InstanceGroupEntry> entry : shellContext.getInstanceGroups().entrySet()) {
for (InstanceGroupEntry gatewayIg : gatewayIgList) {
if (Objects.equals(gatewayIg, entry.getValue())) {
gatewayIgNameList.add(entry.getKey());
}
}
}
Map<String, List<String>> 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()));
Expand Down Expand Up @@ -642,6 +673,24 @@ public String upgradeCluster(
return "Upgrade request successfully sent";
}

private Map<String, List<String>> getComponentMap(String json) {
Map<String, List<String>> map = new HashMap<>();
try {
JsonNode hostGroups = shellContext.objectMapper().readTree(json.getBytes()).get("host_groups");
for (JsonNode hostGroup : hostGroups) {
List<String> 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;
Expand Down
Expand Up @@ -45,4 +45,30 @@ public void setType(String type) {
public Map<String, Object> 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
}
30 changes: 30 additions & 0 deletions web/app/static/js/controllers/clusterController.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -1516,6 +1518,7 @@ angular.module('uluwatuControllers').controller('clusterController', ['$scope',
ig.type = 'CORE'
}
});
$scope.showBlueprintKnoxError();
}

$scope.ambariServerSelected = function() {
Expand All @@ -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 &&
Expand Down
1 change: 1 addition & 0 deletions web/app/static/messages.properties
Expand Up @@ -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",
Expand Down
12 changes: 6 additions & 6 deletions web/app/static/tags/stack/clusterform.tag
Expand Up @@ -18,12 +18,12 @@
<a type="button" ng-class="{'btn-info': configureCluster, 'btn-default': !configureCluster}" class="btn btn-info ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureCluster')">{{msg.cluster_form_ambari_cluster_tag}}</a>
<a type="button" ng-class="{'btn-info': configureSecurity, 'btn-default': !configureSecurity}" ng-disabled="!cluster.name || !cluster.region || isUserDefinedTagsInvalid()" ng-if="activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS'" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureSecurity')">{{msg.cluster_form_ambari_network_tag}}</a>
<a type="button" ng-class="{'btn-info': configureHostGroups, 'btn-default': !configureHostGroups}" ng-disabled="!cluster.name || isUserDefinedTagsInvalid() || (activeCredential !== undefined && (!cluster.region || (activeCredential.cloudPlatform !== 'BYOS' && !cluster.networkId)))" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureHostGroups')">{{msg.cluster_form_ambari_blueprint_tag}}</a>
<a type="button" ng-class="{'btn-info': configureFileSystem, 'btn-default': !configureFileSystem}" ng-disabled="!cluster.name || !cluster.region || !cluster.networkId || !cluster.blueprintId || !ambariServerSelected()" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureFileSystem')" ng-if="activeCredential.cloudPlatform == 'AZURE' || activeCredential.cloudPlatform == 'GCP'">{{msg.cluster_form_ambari_filesystem_tag}}</a>
<a type="button" ng-class="{'btn-info': configureFailureAction, 'btn-default': !configureFailureAction}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureFailureAction')" ng-disabled="!cluster.name || !cluster.region || !cluster.networkId || !cluster.blueprintId || !ambariServerSelected()" ng-if="(activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && showAdvancedOptionForm">{{msg.cluster_form_ambari_failure_tag}}</a>
<a type="button" ng-class="{'btn-info': configureAmbariRepository, 'btn-default': !configureAmbariRepository}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureAmbariRepository')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected()" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_repo_tag}}</a>
<a type="button" ng-class="{'btn-info': configureHdpRepository, 'btn-default': !configureHdpRepository}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureHdpRepository')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected()" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_hdprepo_tag}}</a>
<a type="button" ng-class="{'btn-info': configureAmbariDatabase, 'btn-default': !configureAmbariDatabase}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureAmbariDatabase')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected()" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_database_tag}}</a>
<a type="button" ng-class="{'btn-info': configureReview, 'btn-default': !configureReview}" class="btn ng-binding" role="presentation wizard-button" ng-click="showWizardActualElement('configureReview')" ng-if="!clusterCreationForm.$invalid && ambariServerSelected()">{{msg.cluster_form_ambari_launch_tag}}</a>
<a type="button" ng-class="{'btn-info': configureFileSystem, 'btn-default': !configureFileSystem}" ng-disabled="!cluster.name || !cluster.region || !cluster.networkId || !cluster.blueprintId || !ambariServerSelected() || (cluster.gateway.enableGateway && blueprintKnoxError)" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureFileSystem')" ng-if="activeCredential.cloudPlatform == 'AZURE' || activeCredential.cloudPlatform == 'GCP'">{{msg.cluster_form_ambari_filesystem_tag}}</a>
<a type="button" ng-class="{'btn-info': configureFailureAction, 'btn-default': !configureFailureAction}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureFailureAction')" ng-disabled="!cluster.name || !cluster.region || !cluster.networkId || !cluster.blueprintId || !ambariServerSelected() || (cluster.gateway.enableGateway && blueprintKnoxError)" ng-if="(activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && showAdvancedOptionForm">{{msg.cluster_form_ambari_failure_tag}}</a>
<a type="button" ng-class="{'btn-info': configureAmbariRepository, 'btn-default': !configureAmbariRepository}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureAmbariRepository')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected() || (cluster.gateway.enableGateway && blueprintKnoxError)" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_repo_tag}}</a>
<a type="button" ng-class="{'btn-info': configureHdpRepository, 'btn-default': !configureHdpRepository}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureHdpRepository')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected() || (cluster.gateway.enableGateway && blueprintKnoxError)" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_hdprepo_tag}}</a>
<a type="button" ng-class="{'btn-info': configureAmbariDatabase, 'btn-default': !configureAmbariDatabase}" class="btn ng-binding wizard-button" role="presentation" ng-click="showWizardActualElement('configureAmbariDatabase')" ng-disabled="!cluster.name || !cluster.blueprintId || ((activeCredential !== undefined && activeCredential.cloudPlatform !== 'BYOS') && (!cluster.region || !cluster.networkId)) || !ambariServerSelected() || (cluster.gateway.enableGateway && blueprintKnoxError)" ng-if="showAdvancedOptionForm">{{msg.cluster_form_ambari_database_tag}}</a>
<a type="button" ng-class="{'btn-info': configureReview, 'btn-default': !configureReview}" class="btn ng-binding" role="presentation wizard-button" ng-click="showWizardActualElement('configureReview')" ng-if="!clusterCreationForm.$invalid && ambariServerSelected() && !(cluster.gateway.enableGateway && blueprintKnoxError)">{{msg.cluster_form_ambari_launch_tag}}</a>
</div>

<form class="form-horizontal" role="form" name="$parent.clusterCreationForm" style="padding-top: 20px; padding-bottom: 20px;">
Expand Down

0 comments on commit 3928e12

Please sign in to comment.