Beispiel #1
0
func createCluster(context *cli.Context, rdwr config.ReadWriter, ecsClient ecsclient.ECSClient, cfnClient cloudformation.CloudformationClient, amiIds ami.ECSAmiIds) error {
	// Validate cli flags
	if !isIAMAcknowledged(context) {
		return fmt.Errorf("Please acknowledge that this command may create IAM resources with the '--%s' flag", capabilityIAMFlag)
	}
	ecsParams, err := config.NewCliParams(context, rdwr)
	if err != nil {
		return err
	}

	// Check if cfn stack already exists
	cfnClient.Initialize(ecsParams)
	stackName := ecsParams.GetCfnStackName()
	if err := cfnClient.ValidateStackExists(stackName); err == nil {
		return fmt.Errorf("A CloudFormation stack already exists for the cluster '%s'", ecsParams.Cluster)
	}

	// Populate cfn params
	cfnParams := cliFlagsToCfnStackParams(context)
	cfnParams.Add(cloudformation.ParameterKeyCluster, ecsParams.Cluster)

	// Check if key pair exists
	_, err = cfnParams.GetParameter(cloudformation.ParameterKeyKeyPairName)
	if err == cloudformation.ParameterNotFoundError {
		return fmt.Errorf("Please specify the keypair name with '--%s' flag", keypairNameFlag)
	} else if err != nil {
		return err
	}

	// Check if image id was supplied, else populate
	_, err = cfnParams.GetParameter(cloudformation.ParameterKeyAmiId)
	if err == cloudformation.ParameterNotFoundError {
		amiId, err := amiIds.Get(aws.StringValue(ecsParams.Config.Region))
		if err != nil {
			return err
		}
		cfnParams.Add(cloudformation.ParameterKeyAmiId, amiId)
	} else if err != nil {
		return err
	}
	if err := cfnParams.Validate(); err != nil {
		return err
	}

	// Create ECS cluster
	ecsClient.Initialize(ecsParams)
	if _, err := ecsClient.CreateCluster(ecsParams.Cluster); err != nil {
		return err
	}

	// Create cfn stack
	template := cloudformation.GetTemplate()
	if _, err := cfnClient.CreateStack(template, stackName, cfnParams); err != nil {
		return err
	}

	logrus.Info("Waiting for your cluster resources to be created")
	// Wait for stack creation
	return cfnClient.WaitUntilCreateComplete(stackName)
}
// validateCluster validates if the cluster exists in ECS and is in "ACTIVE" state.
func validateCluster(clusterName string, ecsClient ecsclient.ECSClient) error {
	isClusterActive, err := ecsClient.IsActiveCluster(clusterName)
	if err != nil {
		return err
	}

	if !isClusterActive {
		return fmt.Errorf("Cluster '%s' is not active. Ensure that it exists", clusterName)
	}

	return nil
}
func clusterPS(context *cli.Context, rdwr config.ReadWriter, ecsClient ecsclient.ECSClient) (project.InfoSet, error) {
	ecsParams, err := newCliParams(context, rdwr)
	if err != nil {
		return nil, err
	}

	// Validate that cluster exists in ECS
	ecsClient.Initialize(ecsParams)
	if err := validateCluster(ecsParams.Cluster, ecsClient); err != nil {
		return nil, err
	}
	ec2Client := ec2client.NewEC2Client(ecsParams)

	ecsContext := &ecscompose.Context{ECSClient: ecsClient, EC2Client: ec2Client}
	task := ecscompose.NewTask(ecsContext)
	return task.Info(false)
}
// scaleCluster executes the 'scale' command.
func scaleCluster(context *cli.Context, rdwr config.ReadWriter, ecsClient ecsclient.ECSClient, cfnClient cloudformation.CloudformationClient) error {
	// Validate cli flags
	if !isIAMAcknowledged(context) {
		return fmt.Errorf("Please acknowledge that this command may create IAM resources with the '--%s' flag", capabilityIAMFlag)
	}

	size, err := getClusterSize(context)
	if err != nil {
		return err
	}
	if size == "" {
		return fmt.Errorf("Missing required flag '--%s'", asgMaxSizeFlag)
	}

	ecsParams, err := newCliParams(context, rdwr)
	if err != nil {
		return err
	}

	// Validate that cluster exists in ECS
	ecsClient.Initialize(ecsParams)
	if err := validateCluster(ecsParams.Cluster, ecsClient); err != nil {
		return err
	}

	// Validate that we have a cfn stack for the cluster
	cfnClient.Initialize(ecsParams)
	stackName := ecsParams.GetCfnStackName()
	if err := cfnClient.ValidateStackExists(stackName); err != nil {
		return fmt.Errorf("CloudFormation stack not found for cluster '%s'", ecsParams.Cluster)
	}

	// Populate update params for the cfn stack
	cfnParams := cloudformation.NewCfnStackParamsForUpdate()
	cfnParams.Add(cloudformation.ParameterKeyAsgMaxSize, size)

	// Update the stack.
	if _, err := cfnClient.UpdateStack(stackName, cfnParams); err != nil {
		return err
	}

	logrus.Info("Waiting for your cluster resources to be updated...")
	return cfnClient.WaitUntilUpdateComplete(stackName)
}
func deleteCluster(context *cli.Context, rdwr config.ReadWriter, ecsClient ecsclient.ECSClient, cfnClient cloudformation.CloudformationClient) error {
	// Validate cli flags
	if !isForceSet(context) {
		return fmt.Errorf("Missing required flag '--%s'", forceFlag)
		// TODO prompt override for force
	}
	ecsParams, err := newCliParams(context, rdwr)
	if err != nil {
		return err
	}

	// Validate that cluster exists in ECS
	ecsClient.Initialize(ecsParams)
	if err := validateCluster(ecsParams.Cluster, ecsClient); err != nil {
		return err
	}

	// Validate that a cfn stack exists for the cluster
	cfnClient.Initialize(ecsParams)
	stackName := ecsParams.GetCfnStackName()
	if err := cfnClient.ValidateStackExists(stackName); err != nil {
		return fmt.Errorf("CloudFormation stack not found for cluster '%s'", ecsParams.Cluster)
	}

	// Delete cfn stack
	if err := cfnClient.DeleteStack(stackName); err != nil {
		return err
	}
	logrus.Info("Waiting for your cluster resources to be deleted...")
	if err := cfnClient.WaitUntilDeleteComplete(stackName); err != nil {
		return err
	}

	// Delete cluster in ECS
	if _, err := ecsClient.DeleteCluster(ecsParams.Cluster); err != nil {
		return err
	}

	return nil
}
func createCluster(context *cli.Context, rdwr config.ReadWriter, ecsClient ecsclient.ECSClient, cfnClient cloudformation.CloudformationClient, amiIds ami.ECSAmiIds) error {
	// Validate cli flags
	if !isIAMAcknowledged(context) {
		return fmt.Errorf("Please acknowledge that this command may create IAM resources with the '--%s' flag", capabilityIAMFlag)
	}
	ecsParams, err := newCliParams(context, rdwr)
	if err != nil {
		return err
	}

	// Check if cluster is specified
	if ecsParams.Cluster == "" {
		return fmt.Errorf("Please configure a cluster using the configure command.")
	}

	// Check if cfn stack already exists
	cfnClient.Initialize(ecsParams)
	stackName := ecsParams.GetCfnStackName()
	var deleteStack bool
	if err := cfnClient.ValidateStackExists(stackName); err == nil {
		if !isForceSet(context) {
			return fmt.Errorf("A CloudFormation stack already exists for the cluster '%s'. Please specify '--%s' to clean up your existing resources.", ecsParams.Cluster, forceFlag)
		}
		deleteStack = true
	}

	// Populate cfn params
	cfnParams := cliFlagsToCfnStackParams(context)
	cfnParams.Add(cloudformation.ParameterKeyCluster, ecsParams.Cluster)

	// Check if key pair exists
	_, err = cfnParams.GetParameter(cloudformation.ParameterKeyKeyPairName)
	if err == cloudformation.ParameterNotFoundError {
		return fmt.Errorf("Please specify the keypair name with '--%s' flag", keypairNameFlag)
	} else if err != nil {
		return err
	}

	// Check if vpc and AZs are not both specified.
	if validateMutuallyExclusiveParams(cfnParams, cloudformation.ParameterKeyVPCAzs, cloudformation.ParameterKeyVpcId) {
		return fmt.Errorf("You can only specify '--%s' or '--%s'", vpcIdFlag, vpcAzFlag)
	}

	// Check if 2 AZs are specified
	if validateCommaSeparatedParam(cfnParams, cloudformation.ParameterKeyVPCAzs, 2, 2) {
		return fmt.Errorf("You must specify 2 comma-separated availability zones with the '--%s' flag", vpcAzFlag)
	}

	// Check if vpc exists when security group is specified
	if validateDependentParams(cfnParams, cloudformation.ParameterKeySecurityGroup, cloudformation.ParameterKeyVpcId) {
		return fmt.Errorf("You have selected a security group. Please specify a VPC with the '--%s' flag", vpcIdFlag)
	}

	// Check only one security group is specified
	if validateCommaSeparatedParam(cfnParams, cloudformation.ParameterKeySecurityGroup, 1, 1) {
		return fmt.Errorf("You can only specify one security group with the '--%s' flag", securityGroupFlag)
	}

	// Check if subnets exists when vpc is specified
	if validateDependentParams(cfnParams, cloudformation.ParameterKeyVpcId, cloudformation.ParameterKeySubnetIds) {
		return fmt.Errorf("You have selected a VPC. Please specify 2 comma-separated subnets with the '--%s' flag", subnetIdsFlag)
	}

	// Check if vpc exists when subnets is specified
	if validateDependentParams(cfnParams, cloudformation.ParameterKeySubnetIds, cloudformation.ParameterKeyVpcId) {
		return fmt.Errorf("You have selected subnets. Please specify a VPC with the '--%s' flag", vpcIdFlag)
	}

	// Check if 2 subnets are specified
	if validateCommaSeparatedParam(cfnParams, cloudformation.ParameterKeySubnetIds, 2, 2) {
		return fmt.Errorf("You must specify 2 comma-separated subnets with the '--%s' flag", subnetIdsFlag)
	}

	// Check if image id was supplied, else populate
	_, err = cfnParams.GetParameter(cloudformation.ParameterKeyAmiId)
	if err == cloudformation.ParameterNotFoundError {
		amiId, err := amiIds.Get(aws.StringValue(ecsParams.Config.Region))
		if err != nil {
			return err
		}
		cfnParams.Add(cloudformation.ParameterKeyAmiId, amiId)
	} else if err != nil {
		return err
	}
	if err := cfnParams.Validate(); err != nil {
		return err
	}

	// Create ECS cluster
	ecsClient.Initialize(ecsParams)
	if _, err := ecsClient.CreateCluster(ecsParams.Cluster); err != nil {
		return err
	}

	// Delete cfn stack
	if deleteStack {
		if err := cfnClient.DeleteStack(stackName); err != nil {
			return err
		}
		logrus.Info("Waiting for your CloudFormation stack resources to be deleted...")
		if err := cfnClient.WaitUntilDeleteComplete(stackName); err != nil {
			return err
		}
	}

	// Create cfn stack
	template := cloudformation.GetTemplate()
	if _, err := cfnClient.CreateStack(template, stackName, cfnParams); err != nil {
		return err
	}

	logrus.Info("Waiting for your cluster resources to be created...")
	// Wait for stack creation
	return cfnClient.WaitUntilCreateComplete(stackName)
}