diff --git a/cloudformation/eksnodegroup.yaml b/cloudformation/eksnodegroup.yaml new file mode 100644 index 000000000..8939494de --- /dev/null +++ b/cloudformation/eksnodegroup.yaml @@ -0,0 +1,329 @@ +--- +AWSTemplateFormatVersion: 2010-09-09 +Description: 'AWS Service Operator - Amazon EKS Node Group (aso-1otq2cgd9)' +Parameters: + Namespace: + Description: >- + This is the namespace for the Kubernetes object. + Type: String + ResourceVersion: + Type: String + Description: >- + This is the resource version for the Kubernetes object. + ResourceName: + Description: >- + This is the resource name for the Kubernetes object + Type: String + KeyName: + Description: The EC2 Key Pair to allow SSH access to the instances + Type: AWS::EC2::KeyPair::KeyName + NodeImageId: + Description: AMI id for the node instances. + Type: AWS::EC2::Image::Id + NodeInstanceType: + Description: EC2 instance type for the node instances + Type: String + Default: t3.medium + ConstraintDescription: Must be a valid EC2 instance type + AllowedValues: + - t2.small + - t2.medium + - t2.large + - t2.xlarge + - t2.2xlarge + - t3.nano + - t3.micro + - t3.small + - t3.medium + - t3.large + - t3.xlarge + - t3.2xlarge + - m3.medium + - m3.large + - m3.xlarge + - m3.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + - m4.10xlarge + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.12xlarge + - m5.24xlarge + - c4.large + - c4.xlarge + - c4.2xlarge + - c4.4xlarge + - c4.8xlarge + - c5.large + - c5.xlarge + - c5.2xlarge + - c5.4xlarge + - c5.9xlarge + - c5.18xlarge + - i3.large + - i3.xlarge + - i3.2xlarge + - i3.4xlarge + - i3.8xlarge + - i3.16xlarge + - r3.xlarge + - r3.2xlarge + - r3.4xlarge + - r3.8xlarge + - r4.large + - r4.xlarge + - r4.2xlarge + - r4.4xlarge + - r4.8xlarge + - r4.16xlarge + - x1.16xlarge + - x1.32xlarge + - p2.xlarge + - p2.8xlarge + - p2.16xlarge + - p3.2xlarge + - p3.8xlarge + - p3.16xlarge + - p3dn.24xlarge + - r5.large + - r5.xlarge + - r5.2xlarge + - r5.4xlarge + - r5.12xlarge + - r5.24xlarge + - r5d.large + - r5d.xlarge + - r5d.2xlarge + - r5d.4xlarge + - r5d.12xlarge + - r5d.24xlarge + - z1d.large + - z1d.xlarge + - z1d.2xlarge + - z1d.3xlarge + - z1d.6xlarge + - z1d.12xlarge + NodeAutoScalingGroupMinSize: + Description: Minimum size of Node Group ASG. + Type: Number + Default: 1 + NodeAutoScalingGroupMaxSize: + Description: Maximum size of Node Group ASG. Set to at least 1 greater than NodeAutoScalingGroupDesiredCapacity. + Type: Number + Default: 4 + NodeAutoScalingGroupDesiredCapacity: + Description: Desired capacity of Node Group ASG. + Type: Number + Default: 3 + NodeVolumeSize: + Description: Node volume size + Type: Number + Default: 20 + ClusterName: + Description: The cluster name provided when the cluster was created. If it is incorrect, nodes will not be able to join the cluster. + Type: String + BootstrapArguments: + Description: Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami + Type: String + Default: "" + NodeGroupName: + Description: Unique identifier for the Node Group. + Type: String + ClusterControlPlaneSecurityGroup: + Description: The security group of the cluster control plane. + Type: AWS::EC2::SecurityGroup::Id + VpcId: + Description: The VPC of the worker instances + Type: AWS::EC2::VPC::Id + Subnets: + Description: The subnets where workers can be created. + Type: List + +Metadata: + + AWS::CloudFormation::Interface: + ParameterGroups: + - Label: + default: EKS Cluster + Parameters: + - ClusterName + - ClusterControlPlaneSecurityGroup + - Label: + default: Worker Node Configuration + Parameters: + - NodeGroupName + - NodeAutoScalingGroupMinSize + - NodeAutoScalingGroupDesiredCapacity + - NodeAutoScalingGroupMaxSize + - NodeInstanceType + - NodeImageId + - NodeVolumeSize + - KeyName + - BootstrapArguments + - Label: + default: Worker Network Configuration + Parameters: + - VpcId + - Subnets + +Resources: + + NodeInstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + Path: "/" + Roles: + - !Ref NodeInstanceRole + + NodeInstanceRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: ec2.amazonaws.com + Action: sts:AssumeRole + Path: "/" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy + - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly + + NodeSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group for all nodes in the cluster + VpcId: !Ref VpcId + Tags: + - Key: !Sub kubernetes.io/cluster/${ClusterName} + Value: owned + + NodeSecurityGroupIngress: + Type: AWS::EC2::SecurityGroupIngress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow node to communicate with each other + GroupId: !Ref NodeSecurityGroup + SourceSecurityGroupId: !Ref NodeSecurityGroup + IpProtocol: -1 + FromPort: 0 + ToPort: 65535 + + NodeSecurityGroupFromControlPlaneIngress: + Type: AWS::EC2::SecurityGroupIngress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow worker Kubelets and pods to receive communication from the cluster control plane + GroupId: !Ref NodeSecurityGroup + SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup + IpProtocol: tcp + FromPort: 1025 + ToPort: 65535 + + ControlPlaneEgressToNodeSecurityGroup: + Type: AWS::EC2::SecurityGroupEgress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow the cluster control plane to communicate with worker Kubelet and pods + GroupId: !Ref ClusterControlPlaneSecurityGroup + DestinationSecurityGroupId: !Ref NodeSecurityGroup + IpProtocol: tcp + FromPort: 1025 + ToPort: 65535 + + NodeSecurityGroupFromControlPlaneOn443Ingress: + Type: AWS::EC2::SecurityGroupIngress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow pods running extension API servers on port 443 to receive communication from cluster control plane + GroupId: !Ref NodeSecurityGroup + SourceSecurityGroupId: !Ref ClusterControlPlaneSecurityGroup + IpProtocol: tcp + FromPort: 443 + ToPort: 443 + + ControlPlaneEgressToNodeSecurityGroupOn443: + Type: AWS::EC2::SecurityGroupEgress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow the cluster control plane to communicate with pods running extension API servers on port 443 + GroupId: !Ref ClusterControlPlaneSecurityGroup + DestinationSecurityGroupId: !Ref NodeSecurityGroup + IpProtocol: tcp + FromPort: 443 + ToPort: 443 + + ClusterControlPlaneSecurityGroupIngress: + Type: AWS::EC2::SecurityGroupIngress + DependsOn: NodeSecurityGroup + Properties: + Description: Allow pods to communicate with the cluster API Server + GroupId: !Ref ClusterControlPlaneSecurityGroup + SourceSecurityGroupId: !Ref NodeSecurityGroup + IpProtocol: tcp + ToPort: 443 + FromPort: 443 + + NodeGroup: + Type: AWS::AutoScaling::AutoScalingGroup + Properties: + DesiredCapacity: !Ref NodeAutoScalingGroupDesiredCapacity + LaunchConfigurationName: !Ref NodeLaunchConfig + MinSize: !Ref NodeAutoScalingGroupMinSize + MaxSize: !Ref NodeAutoScalingGroupMaxSize + VPCZoneIdentifier: !Ref Subnets + Tags: + - Key: Name + Value: !Sub ${ClusterName}-${NodeGroupName}-Node + PropagateAtLaunch: true + - Key: !Sub kubernetes.io/cluster/${ClusterName} + Value: owned + PropagateAtLaunch: true + UpdatePolicy: + AutoScalingRollingUpdate: + MaxBatchSize: 1 + MinInstancesInService: !Ref NodeAutoScalingGroupDesiredCapacity + PauseTime: PT5M + + NodeLaunchConfig: + Type: AWS::AutoScaling::LaunchConfiguration + Properties: + AssociatePublicIpAddress: true + IamInstanceProfile: !Ref NodeInstanceProfile + ImageId: !Ref NodeImageId + InstanceType: !Ref NodeInstanceType + KeyName: !Ref KeyName + SecurityGroups: + - !Ref NodeSecurityGroup + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: !Ref NodeVolumeSize + VolumeType: gp2 + DeleteOnTermination: true + UserData: + Fn::Base64: + !Sub | + #!/bin/bash + set -o xtrace + /etc/eks/bootstrap.sh ${ClusterName} ${BootstrapArguments} + /opt/aws/bin/cfn-signal --exit-code $? \ + --stack ${AWS::StackName} \ + --resource NodeGroup \ + --region ${AWS::Region} + +Outputs: + + NodeInstanceRole: + Description: The node instance role + Value: !GetAtt NodeInstanceRole.Arn + + NodeSecurityGroup: + Description: The security group for the node group + Value: !Ref NodeSecurityGroup diff --git a/cmd/aws-service-operator/main.go b/cmd/aws-service-operator/main.go index b3322432d..2e3f2368e 100644 --- a/cmd/aws-service-operator/main.go +++ b/cmd/aws-service-operator/main.go @@ -50,7 +50,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&awsRegion, "region", "r", "us-west-2", "AWS Region for resources to be created in") rootCmd.PersistentFlags().StringVarP(&logLevel, "loglevel", "l", "Info", "Log level for the CLI") rootCmd.PersistentFlags().StringVarP(&logFile, "logfile", "", "", "Log file for the CLI") - rootCmd.PersistentFlags().StringVarP(&resources, "resources", "", "cloudformationtemplate,dynamodb,ecrrepository,elasticache,s3bucket,snssubscription,snstopic,sqsqueue", "Comma delimited list of CRDs to deploy") + rootCmd.PersistentFlags().StringVarP(&resources, "resources", "", "cloudformationtemplate,dynamodb,ecrrepository,elasticache,s3bucket,snssubscription,snstopic,sqsqueue,eksnodegroup", "Comma delimited list of CRDs to deploy") rootCmd.PersistentFlags().StringVarP(&clusterName, "cluster-name", "i", "aws-operator", "Cluster name for the Application to run as, used to label the Cloudformation templated to avoid conflict") rootCmd.PersistentFlags().StringVarP(&bucket, "bucket", "b", "aws-operator", "To configure the operator you need a base bucket to contain the resources") rootCmd.PersistentFlags().StringVarP(&accountID, "account-id", "a", "", "AWS Account ID, this is used to configure outputs and operate on the proper account.") diff --git a/code-generation/pkg/codegen/assets/cft.go.templ b/code-generation/pkg/codegen/assets/cft.go.templ index 1a156f2de..34dfe5828 100644 --- a/code-generation/pkg/codegen/assets/cft.go.templ +++ b/code-generation/pkg/codegen/assets/cft.go.templ @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.{{.Spec.Kind}}.Name) @@ -161,6 +164,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.{{.Spec.Kind}}) (outpu NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.{{.Spec.Kind}}.Name) diff --git a/code-generation/pkg/codegen/templates.go b/code-generation/pkg/codegen/templates.go index 4633abcf7..556667d7b 100644 --- a/code-generation/pkg/codegen/templates.go +++ b/code-generation/pkg/codegen/templates.go @@ -88,7 +88,7 @@ func awsServiceOperatorYamlTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "aws-service-operator.yaml.templ", size: 2649, mode: os.FileMode(436), modTime: time.Unix(1553718410, 0)} + info := bindataFileInfo{name: "aws-service-operator.yaml.templ", size: 2649, mode: os.FileMode(436), modTime: time.Unix(1553719645, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -113,7 +113,7 @@ func baseGoTempl() (*asset, error) { return a, nil } -var _cftGoTempl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x59\x6d\x6f\x9b\xc8\x13\x7f\x0d\x9f\x62\xfe\x56\xd5\x3f\x44\x0e\xbe\xbe\xb5\x2e\x27\xf5\x9a\x3e\x44\xad\x92\x2a\x76\xdb\x17\x51\xd4\xae\x61\x8c\xb7\xc1\x2c\xc7\x2e\xf1\xf9\x2c\xbe\xfb\x69\x1f\x30\x0b\x36\x76\xdc\xf6\xda\xeb\xc9\xa8\x95\x61\x99\xf9\xcd\xe3\xce\xec\x84\xc1\x00\x7e\xd3\x17\x9c\x5f\xc1\xe5\xd5\x18\x9e\x9f\x5f\x8c\x61\xfc\xea\x62\x04\x2f\x2e\xde\x3c\x87\x5f\xd7\x97\x3b\x18\xc0\x78\x46\x39\x4c\x69\x82\x40\x39\x90\x42\xb0\x18\x53\xcc\x89\xc0\x08\xee\x29\x81\x4f\x64\xc1\x4f\x59\x26\x57\x58\x7e\x1a\xb2\x08\x63\x4c\x21\xcb\x59\x88\x9c\x7f\x92\x00\x17\x53\x58\xb2\xe2\xff\x11\x24\xf4\x0e\x41\xcc\x10\xc2\x19\x49\x63\x04\x92\x2e\xc5\x8c\xa6\x31\x90\x09\x2b\x04\x88\xb5\xa0\x39\xb9\x43\xc0\x88\x0a\x0e\x82\x29\x8e\x40\xe0\x3c\x4b\x24\x9a\xd6\x24\x55\xab\xd9\x5d\x3c\x30\x12\x07\x84\x73\x14\x1c\x22\x9a\x63\x28\x58\xbe\x0c\x5c\x37\x23\xe1\x1d\x89\x11\x56\xab\x60\x94\x61\x18\x5c\x23\x67\x45\x1e\x62\x70\x49\xe6\x58\x96\xae\x4b\xe7\x19\xcb\x05\x78\xae\xd3\xc3\x3c\x67\x39\xef\xb9\x4e\x2f\xa6\x62\x56\x4c\x82\x90\xcd\x07\x64\xc1\xe5\xff\x53\x1e\xdd\x9d\xc6\x4c\xde\xee\x26\xe0\x98\xdf\xd3\x10\x07\x61\xc2\x8a\x68\xca\xf2\x39\x11\x94\xa5\x3d\xd7\x21\x0b\xfe\xfe\x09\x49\xb2\x19\x79\x02\x2d\xfe\x84\x4c\x0c\x86\x66\x5e\xfb\x72\x20\xad\x23\x19\xe5\x83\xf6\x9b\x40\x8a\xbd\x37\x78\x9b\x1a\xed\x46\x0c\x59\x3a\xa5\xf1\xa1\x5c\x33\x4c\x32\x94\xfe\xf1\x5d\x19\x84\x4b\x5c\x40\x95\x06\x1c\x08\xa4\xb8\x00\x36\xf9\x8c\xa1\x70\xa7\x45\x1a\xca\xf7\x9e\x16\x04\xfa\x27\x78\xa6\x7e\xfa\x5d\xb1\x80\x13\xcb\x45\x41\x45\xf4\x9a\xa6\x51\x59\xf6\x41\xb0\x8c\x86\x4f\xaf\x2f\x81\x8b\x9c\xa6\xb1\x0f\x27\xcf\x1a\x1e\x86\x95\xeb\xe4\x28\x8a\x3c\x85\xc7\xcd\x37\x2b\xd7\x71\x9a\x68\xc3\x2e\x15\xfa\xae\xe3\x68\x65\x87\x8e\xbc\xf4\x7d\xdf\x05\x80\xb5\x02\x43\xd0\x57\xf5\xdc\x77\x9d\xd2\x2d\x95\x4b\x5a\x1a\x45\x38\xa5\x29\x72\x95\xa6\x5d\x36\x87\x53\xc1\x5d\xb1\xcc\xb0\xcd\xcc\x45\x5e\x84\x42\x5a\x65\x9c\x58\x5d\x0d\x67\xba\x2d\xcb\x76\xf9\xd0\xad\x75\x36\x50\xda\x95\x46\xf9\x91\x20\xe1\x9d\xd4\x0a\xb4\x1b\xb5\xde\xa9\x5c\x60\x53\x75\xcf\x25\x05\x4c\x08\xc7\x08\x98\xde\x7d\xad\x8d\xaf\x54\x52\xd1\xf7\x78\x3b\x40\x7e\x2d\xc1\xf3\x8d\x68\x2b\x68\x26\xbb\x82\x9a\x88\x07\x95\xa9\x49\xc1\x05\xe6\x72\xb1\x0f\xbd\x0e\x4f\xf6\xfa\xc0\x5b\x06\x07\x9a\x63\xeb\x32\xcf\x48\x88\xbe\x31\xfd\x25\x8a\xab\x42\x64\x85\xe0\xc6\x76\xcb\x5c\x66\x5e\x4c\x73\x36\x57\xcb\xe7\xc8\xc3\x9c\x4e\x50\x29\xca\x21\x24\x49\xd2\x6d\x72\x8d\xec\xf9\xe0\xcd\x49\x76\xa3\x0d\xbf\xd5\x3f\x7d\x50\x35\xc7\x97\x7e\xa8\x04\x0d\xcf\x60\x83\x6e\x55\xba\x0e\x47\xae\x5e\xae\xdd\xf2\xf4\xc3\x68\x84\x9c\x53\x96\xba\x0e\xbf\x0f\xe5\xbb\x66\xd1\x09\xe4\x16\x94\x6c\xbe\xeb\x3a\xca\x9a\x8b\xb4\x12\xd1\xa2\x6c\x1a\xa5\xc8\xe4\xb6\x59\x07\x43\x26\x3d\x59\xc8\xe8\x48\x75\x3c\x3b\x4c\xbe\xaf\x76\x40\x65\x80\x32\x49\xe9\x79\x1f\xb6\x60\xbd\xc7\x96\x12\xbe\xeb\xd0\xa9\xa2\xfd\xdf\x19\xa4\x34\x91\x2e\xa8\x72\x21\xa5\x89\x82\x91\xb8\x8e\x2c\x35\x4c\x00\x2f\x72\x04\x3a\xd5\x1d\x82\x72\xc0\x7b\xd9\x62\x18\xe7\x74\x92\xa0\xc2\x4a\x30\xf5\xb4\x0e\x5a\x3b\xee\x4b\xe8\x27\xdb\x80\x59\xce\x95\x73\x7a\x29\xd3\x61\xae\x02\x8f\x11\x2c\xa8\x98\x81\x98\x11\x61\x12\x40\xee\x80\x9e\xaf\x4d\x9c\xb2\x1c\x3e\xf6\x65\x4e\x48\x0b\x73\xd5\xc1\x1a\x22\x6f\x7e\xb9\x0d\xaa\x54\x92\x72\x4d\x50\x6f\x4e\x58\x21\xcc\x8b\xd7\xb8\xbc\x85\x33\xb0\x56\xde\x93\xa4\x40\x2d\xc0\xe8\x69\xd8\xb4\x13\x4c\x6d\xc9\x91\x08\xed\x48\x58\xd0\x24\x81\x50\x2d\x58\x99\x6a\x14\x47\xe0\x45\x96\x25\x14\x23\xc8\x48\x4e\xe6\xbc\x3b\x3b\x2d\x4c\x99\x9e\x5a\x2a\x9c\xb4\x72\xc3\xa2\xba\xb2\x42\x5c\x67\xee\x57\x66\x66\x38\x55\x8d\x5d\x1a\x33\x3c\x5b\xd7\x81\x97\x28\x94\xba\x2f\x2a\x9e\xb1\x21\x5a\xd7\x85\xc3\x6a\x41\xf5\x38\x5e\x66\x58\x96\xc1\x76\xec\x8e\x82\xf1\x60\x5e\x53\x55\xf6\xed\x36\xcb\xa3\x87\x6f\x35\xa7\x12\xf8\xee\xfa\xcd\xd0\xa6\xac\xfd\xa8\xc8\x2e\x99\xa0\x53\x1a\x2a\x89\x4f\xaf\x2f\xf9\x10\x6e\x6e\x4f\x4c\x39\x71\x1d\xc7\x69\xc8\xa8\x1a\x83\xe2\x2c\xfb\x55\x32\x6a\xaf\xaa\xa6\x60\x85\x46\xab\xff\x56\x26\x97\xd7\xbb\xb6\x88\xba\x6a\xb0\x5f\x63\xbd\xc7\x5c\xe6\xc5\x5e\x38\x43\xb7\x0d\xb1\x45\xe2\xbb\x4e\x5a\xb9\xbe\x13\x76\x1d\x9c\x2e\x15\x4d\xe4\x9c\xb0\xee\x35\x9d\x60\x56\x3f\x52\x70\x9b\x6d\xca\x77\x57\xab\x53\x53\x1f\x1e\x09\x96\x49\x28\x2d\xf2\x77\x16\x2d\x83\x51\x38\xc3\x39\x09\xde\xe6\xb2\x75\x0a\x8a\xbc\x2c\x65\x23\x3f\x95\xf5\x6d\xcb\xaa\xc1\x49\x91\xcb\x03\xb7\x84\x6a\xd0\xd4\xac\x26\x33\xe8\x5f\x18\x69\x5e\x29\x3b\x78\x8d\xcb\xb2\x5c\xad\x0c\xbf\x7e\x94\x94\x12\xa9\x57\xaf\x57\x69\x55\x96\x3d\x8d\x88\x09\xc7\x87\xc3\xc8\x7f\x65\x19\x5c\x4d\x3e\x07\xab\xd5\xa3\xc6\x7e\x31\x00\x23\x75\xa2\x51\x7c\x2a\x02\xf5\xa3\x62\xed\xd5\x82\xd3\x7d\xea\xab\x8a\xb9\xee\x34\x55\x90\x6a\xf3\xbd\x3d\x3a\xf7\xd7\x3c\xe7\x44\x90\xd5\xd5\xe4\xf3\x50\xa5\xc5\xa3\xe6\x99\x53\x9f\xb1\x86\x50\x57\x9c\x57\x9a\x6d\xb8\xe6\x97\x85\xcc\x2f\x77\x35\x33\xab\x2d\xca\x6d\x05\xb0\x43\xb7\xce\x94\xdb\x0c\x93\xa2\xef\xf5\xad\x73\x93\xdc\xca\x74\xba\xdc\x65\xbb\xf2\x9b\xef\xb7\xdc\x6c\x87\x5a\x25\x92\x87\x7f\xa8\xb4\x55\x01\x84\x9e\x5d\x07\x7a\x7e\x3b\x34\xbb\x74\x56\x18\x7b\x15\xde\xf0\xbc\x2e\x1a\x7e\x43\xb7\x07\x65\xb9\xc9\x47\xa7\x2d\x7b\x67\x4e\x5b\x4c\x07\x25\xf1\xfe\xac\x3d\x28\x4d\x7f\x70\x5e\x7e\xe3\x98\x6e\xb8\x61\x5b\xd6\xa9\xdb\xfa\xce\x75\xd4\x81\x05\x05\xe6\xaa\x6b\xde\xdc\xb6\x8f\x22\x6f\xab\xf7\xf2\x40\x6c\x11\x9f\x01\xc9\x32\x4c\x23\xaf\x5e\xeb\x83\x9d\xb6\xfe\xc3\xc9\xeb\xb6\xb2\x8f\x23\xb5\xfa\xc6\x3e\xda\xf0\x07\x35\x87\xbd\x8a\xed\xa8\x16\xdd\x75\xe2\x10\x50\xbf\x2b\xd8\xd6\x19\x29\x18\xa1\x58\xc7\x96\x5b\x50\x7e\xeb\x18\x32\x26\xf1\x66\x6e\x8e\x49\xfc\xa5\xe7\x90\xfd\x78\x5f\x76\x10\xe9\xc6\xfd\x92\x93\x48\x37\xda\x43\x8e\x22\xae\x23\x48\xdc\xb1\xa1\xc6\x44\xcd\x96\x8a\x60\x1d\x49\xf9\xd4\xdc\x3e\x63\x12\xfb\xbb\xa9\x6a\x7f\x76\x10\xda\xae\xe9\x20\x69\x5a\xec\x6f\xa6\xc8\x98\xc4\x5c\xd1\xfa\xae\x0b\x76\x01\x03\x3d\x6e\xda\xf3\x4c\x6b\xd6\xd4\x45\xcf\xcc\x52\xef\xb2\xa8\x39\x4b\x15\x6a\x41\x0d\x4f\xf8\x27\xe5\x82\xa6\xb1\x1e\xaa\xba\x67\x27\x0b\xc3\xd3\xec\xd1\xae\x3f\xbe\x74\x8f\x57\x16\xd0\xcf\x33\x5e\x19\x8b\x0f\x99\xaa\x0e\x66\x79\xe0\x30\x65\xf9\xef\x38\x4c\x1d\x87\xa9\xe3\x30\xf5\x6f\x18\xa6\xcc\x66\xff\x0e\x47\xd5\xe3\x04\xf5\x4f\x4c\x50\xf0\x5f\x9a\xa0\xbe\x5f\x32\x1e\xe7\xa6\xe3\xdc\x74\x9c\x9b\x8e\x73\xd3\x4f\x36\x37\xd9\xb3\xcc\xae\xb9\xe9\x1c\x13\x6c\xcc\x4d\x91\x5a\xa8\xbf\x41\x75\x8f\x4b\x16\xab\xe7\x83\xf7\x4d\x27\x9c\x7d\x9f\x36\xd7\x92\xf5\x7c\x50\x6e\xf8\xc7\xfe\xe6\x6c\x0f\x08\xd2\x5b\x1f\x6d\x47\xd9\x56\xec\x72\xd4\x07\x42\xc5\xbb\x54\xd0\x44\x91\x6a\xae\xe8\x50\x97\x6d\x05\xf9\xee\xce\xfb\xea\xef\xc2\x60\xf9\x6f\x9b\x49\xcf\xd8\x3c\x93\xbf\x9d\x0e\xfd\x3b\x00\x00\xff\xff\xd3\x02\x8f\xa7\xac\x24\x00\x00") +var _cftGoTempl = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x59\x7b\x6f\xa3\x48\x12\xff\x1b\x3e\x45\x1d\x1a\xed\x41\xe4\xe0\x9b\x7f\xad\xcb\x49\xd9\x64\x1f\xd1\xcc\x25\x51\xe2\x99\xd5\x29\x8a\x66\xdb\x50\xc6\x3d\xc1\x34\x47\x37\xc9\xf9\x2c\xbe\xfb\xa9\x1f\x40\x83\x8d\x1d\xcf\xee\xcd\x6a\x47\x46\x33\x32\x34\x55\xbf\x7a\x76\x55\x57\x18\x8f\xe1\x1f\xfa\x82\xcb\x1b\xb8\xbe\x99\xc2\x0f\x97\x57\x53\x98\xfe\x7c\x75\x0f\x3f\x5e\xbd\xff\x01\xfe\xde\x5c\xee\x78\x0c\xd3\x05\xe5\x30\xa7\x29\x02\xe5\x40\x4a\xc1\x12\xcc\xb0\x20\x02\x63\x78\xa6\x04\x7e\x25\x2f\xfc\x94\xe5\x72\x85\x15\xa7\x11\x8b\x31\xc1\x0c\xf2\x82\x45\xc8\xf9\xaf\x12\xe0\x6a\x0e\x2b\x56\xfe\x35\x86\x94\x3e\x21\x88\x05\x42\xb4\x20\x59\x82\x40\xb2\x95\x58\xd0\x2c\x01\x32\x63\xa5\x00\xd1\x08\x5a\x92\x27\x04\x8c\xa9\xe0\x20\x98\xe2\x08\x05\x2e\xf3\x54\xa2\x69\x4d\x32\xb5\x9a\x3f\x25\x63\x23\x71\x4c\x38\x47\xc1\x21\xa6\x05\x46\x82\x15\xab\xd0\x75\x73\x12\x3d\x91\x04\x61\xbd\x0e\xef\x73\x8c\xc2\x3b\xe4\xac\x2c\x22\x0c\xaf\xc9\x12\xab\xca\x75\xe9\x32\x67\x85\x00\xdf\x75\x3c\x2c\x0a\x56\x70\xcf\x75\xbc\x84\x8a\x45\x39\x0b\x23\xb6\x1c\x93\x17\x2e\xff\x9f\xf2\xf8\xe9\x34\x61\xf2\x76\x37\x01\xc7\xe2\x99\x46\x38\x8e\x52\x56\xc6\x73\x56\x2c\x89\xa0\x2c\xf3\x5c\x87\xbc\xf0\x8f\x6f\x49\x9a\x2f\xc8\x5b\xe8\xf1\xa7\x64\x66\x30\x34\x73\xe3\xcb\xb1\xb4\x8e\xe4\x94\x8f\xfb\x6f\x42\x29\xf6\xd9\xe0\x6d\x6a\xb4\x1b\x31\x62\xd9\x9c\x26\x87\x72\x2d\x30\xcd\x51\xfa\x27\x70\x65\x10\xae\xf1\x05\xea\x34\xe0\x40\x20\xc3\x17\x60\xb3\xcf\x18\x09\x77\x5e\x66\x91\x7c\xef\x6b\x41\xa0\x7f\xc2\x0b\xf5\x33\x1a\x8a\x05\x9c\x58\x2e\x0a\x6b\xa2\x77\x34\x8b\xab\x6a\x04\x82\xe5\x34\x3a\xbf\xbb\x06\x2e\x0a\x9a\x25\x01\x9c\x5c\x74\x3c\x0c\x6b\xd7\x29\x50\x94\x45\x06\xdf\x75\xdf\xac\x5d\xc7\xe9\xa2\x4d\x86\x54\x18\xb9\x8e\xa3\x95\x9d\x38\xf2\xd2\xf7\x23\x17\x00\x1a\x05\x26\xa0\xaf\xfa\x79\xe4\x3a\x95\x5b\x29\x97\xf4\x34\x8a\x71\x4e\x33\xe4\x2a\x4d\x87\x6c\x8e\xe6\x82\xbb\x62\x95\x63\x9f\x99\x8b\xa2\x8c\x84\xb4\xca\x38\xb1\xbe\x3a\xce\x74\x7b\x96\xed\xf2\xa1\xdb\xea\x6c\xa0\xb4\x2b\x8d\xf2\xf7\x82\x44\x4f\x52\x2b\xd0\x6e\xd4\x7a\x67\x72\x81\xcd\xd5\x3d\x97\x14\x30\x23\x1c\x63\x60\x7a\xf7\xf5\x36\xbe\x52\x49\x45\xdf\xe7\xfd\x00\x05\xad\x04\x3f\x30\xa2\xad\xa0\x99\xec\x0a\x5b\x22\x1e\xd6\xa6\xa6\x25\x17\x58\xc8\xc5\x11\x78\x03\x9e\xf4\x46\xc0\x7b\x06\x87\x9a\x63\xeb\x32\xcf\x49\x84\x81\x31\xfd\x27\x14\x37\xa5\xc8\x4b\xc1\x8d\xed\x96\xb9\xcc\xbc\x98\x17\x6c\xa9\x96\x2f\x91\x47\x05\x9d\xa1\x52\x94\x43\x44\xd2\x74\xd8\xe4\x16\xd9\x0f\xc0\x5f\x92\xfc\x41\x1b\xfe\xa8\x7f\x46\xa0\x6a\x4e\x20\xfd\x50\x0b\x9a\x9c\xc1\x06\xdd\xba\x72\x1d\x8e\x5c\xbd\x6c\xdc\x72\xfe\xcb\xfd\x3d\x72\x4e\x59\xe6\x3a\xfc\x39\x92\xef\xba\x45\x27\x94\x5b\x50\xb2\x05\xae\xeb\x28\x6b\xae\xb2\x5a\x44\x8f\xb2\x6b\x94\x22\x93\xdb\xa6\x09\x86\x4c\x7a\xf2\x22\xa3\x23\xd5\xf1\xed\x30\x05\x81\xda\x01\xb5\x01\xca\x24\xa5\xe7\x73\xd4\x83\xf5\xbf\xb3\x94\x08\x5c\x87\xce\x15\xed\x5f\xce\x20\xa3\xa9\x74\x41\x9d\x0b\x19\x4d\x15\x8c\xc4\x75\x64\xa9\x61\x02\x78\x59\x20\xd0\xb9\xee\x10\x94\x03\x3e\xcb\x16\xc3\x38\xa7\xb3\x14\x15\x56\x8a\x99\xaf\x75\xd0\xda\xf1\x40\x42\xbf\xdd\x06\xcc\x0a\xae\x9c\xe3\x65\x4c\x87\xb9\x0e\x3c\xc6\xf0\x42\xc5\x02\xc4\x82\x08\x93\x00\x72\x07\x78\x81\x36\x71\xce\x0a\xf8\x34\x92\x39\x21\x2d\x2c\x54\x07\xeb\x88\x7c\xf8\xdb\x63\x58\xa7\x92\x94\x6b\x82\xfa\x70\xc2\x4a\x61\x5e\xbc\xc3\xd5\x23\x9c\x81\xb5\xf2\x91\xa4\x25\x6a\x01\x46\x4f\xc3\xa6\x9d\x60\x6a\x4b\x81\x44\x68\x47\xc2\x0b\x4d\x53\x88\xd4\x82\x95\xa9\x46\x71\x04\x5e\xe6\x79\x4a\x31\x86\x9c\x14\x64\xc9\x87\xb3\xd3\xc2\x94\xe9\xa9\xa5\xc2\x49\x2f\x37\x2c\xaa\x1b\x2b\xc4\x6d\xe6\xfe\xc6\xcc\x8c\xe6\xaa\xb1\x4b\x63\x26\x67\x4d\x1d\xf8\x09\x85\x52\xf7\xc7\x9a\x67\x6a\x88\x9a\xba\x70\x58\x2d\xa8\x1f\xa7\xab\x1c\xab\x2a\xdc\x8e\x3d\x50\x30\x5e\xcd\x6b\xaa\xca\xbe\xdd\x66\x79\xf4\xf0\xad\xe6\xd4\x02\x3f\xdc\xbd\x9f\xd8\x94\xad\x1f\x15\xd9\x35\x13\x74\x4e\x23\x25\xf1\xfc\xee\x9a\x4f\xe0\xe1\xf1\xc4\x94\x13\xd7\x71\x9c\x8e\x8c\xba\x31\x28\x4e\xd5\x06\x2f\x48\x4e\x66\x34\xa5\x82\xe2\x2e\x56\xef\xe2\xfc\xf6\xfc\xfb\xab\xf7\x57\xd3\x7f\x7d\xba\x3a\xff\xa7\xd7\x00\xe8\x6c\xd6\x61\x51\x5d\xc5\x8a\xad\xb6\xff\x56\x66\xa7\xef\xdd\x59\x44\x43\x45\x3c\x68\xb1\x3e\x62\x21\x13\x6b\x2f\x9c\xa1\xdb\x86\xd8\x23\x09\x5c\x27\xab\x63\x37\x08\xdb\x44\x77\x48\x45\x13\x7a\x27\x6a\x9b\xd5\x20\x98\xd5\xd0\x14\xdc\x66\x9f\x0b\xdc\xf5\xfa\xd4\x14\x98\x37\x82\xe5\x12\x4a\x8b\xfc\x9e\xc5\xab\xf0\x3e\x5a\xe0\x92\x84\xb7\x85\xec\xbd\x32\x42\x55\x25\x4f\x02\xa7\xb2\x40\x6e\x59\x35\x38\x19\x72\x79\x62\x97\x50\x1d\x9a\x96\xd5\xa4\x16\xfd\x2f\xc6\x9a\x57\xca\x0e\xdf\xe1\xaa\xaa\xd6\x6b\xc3\xaf\x1f\x25\xa5\x44\xf2\xda\xf5\x3a\x2f\xab\xca\xd3\x88\x98\x72\x7c\x3d\x8c\xfc\x57\x55\xe1\xcd\xec\x73\xb8\x5e\xbf\xe9\x6c\x38\x03\x70\xaf\x8e\x44\x8a\x4f\x45\xa0\x7d\x54\xac\x5e\x2b\x38\xdb\xa7\xbe\x2a\xb9\x4d\xab\xaa\x83\xd4\x9a\xef\xef\xd1\x79\xd4\xf0\x5c\x12\x41\xd6\x37\xb3\xcf\x13\x95\x16\x6f\xba\x87\x56\x7d\x48\x9b\x40\x5b\xb2\x7e\xd6\x6c\x93\x86\x5f\x56\xc2\xa0\xda\xd5\x0d\xad\xbe\x2a\xb7\x15\xc0\x0e\xdd\x06\x53\x6e\x33\x4c\x8a\xde\x1b\x59\x07\x2f\xb9\xa1\xe9\x7c\xb5\xcb\x76\xe5\xb7\x20\xe8\xb9\xd9\x0e\xb5\x4a\x24\x1f\xff\xad\xd2\x56\x05\x10\x3c\xbb\x0e\x78\x41\x3f\x34\xbb\x74\x56\x18\x7b\x15\xde\xf0\xbc\x2e\x1a\x41\x47\xb7\x57\x65\xb9\xc9\x47\xa7\x2f\x7b\x67\x4e\x5b\x4c\x07\x25\xf1\xfe\xac\x3d\x28\x4d\xff\xe0\xbc\xfc\x9d\x63\xba\xe1\x86\x6d\x59\xa7\x6e\xdb\x3b\xd7\x51\x27\x1e\x14\x58\xa8\xb6\xfb\xf0\xd8\x3f\xcb\xdc\xd6\xef\xe5\x89\xda\x22\x3e\x03\x92\xe7\x98\xc5\x7e\xbb\x36\x02\x3b\x6d\x83\xd7\x93\xb7\x6d\x65\x1f\x47\x66\xf5\x8d\x7d\xb4\xd1\x1f\xd4\x1c\xf6\x2a\xb6\xa3\x5a\x0c\xd7\x89\x43\x40\x83\xa1\x60\x5b\x87\xac\xf0\x1e\x45\x13\x5b\x6e\x41\x05\xbd\x63\xc8\x94\x24\x9b\xb9\x39\x25\xc9\x97\x9e\x43\xf6\xe3\x7d\xd9\x41\x64\x18\xf7\x4b\x4e\x22\xc3\x68\xaf\x39\x8a\xb8\x8e\x20\xc9\xc0\x86\x9a\x12\x35\x9c\x2a\x82\x26\x92\xf2\xa9\xbb\x7d\xa6\x24\x09\x76\x53\xb5\xfe\x1c\x20\xb4\x5d\x33\x40\xd2\xb5\x38\xd8\x4c\x91\x29\x49\xb8\xa2\x0d\x5c\x17\xec\x02\x06\x7a\x5e\xb5\x07\xa2\xde\xb0\xaa\x8b\x9e\x19\xc6\x3e\xe4\x71\x77\x18\x2b\xd5\x82\x9a\xbe\xf0\x3f\x94\x0b\x9a\x25\x7a\x2a\x1b\x1e\xbe\x2c\x0c\x5f\xb3\xc7\xbb\xfe\x7a\x33\x3c\x9f\x59\x40\x7f\x9e\xf9\xcc\x58\x7c\xc8\x58\x76\x30\xcb\x2b\xa7\x31\xcb\x7f\xc7\x69\xec\x38\x8d\x1d\xa7\xb1\x6f\x62\x1a\x33\xd5\xe2\x2b\x9c\x75\x8f\x23\xd8\xff\x63\x04\x83\x6f\x69\x04\xfb\x7a\xc9\x78\x1c\xbc\x8e\x83\xd7\x71\xf0\x3a\x0e\x5e\x7f\xb2\xc1\xcb\x1e\x86\x76\x0d\x5e\x97\x98\x62\x67\xf0\x8a\xd5\x42\xfb\x15\x6c\x78\xde\xb2\x58\xfd\x00\xfc\xdf\x75\x44\xda\xf7\x71\xb5\x91\xac\x07\x8c\x6a\xc3\x3f\xf6\x57\x6f\x7b\xc2\x90\xde\xfa\x64\x3b\xca\xb6\x62\x97\xa3\x7e\x21\x54\x7c\xc8\x04\x4d\x15\xa9\xe6\x8a\x0f\x75\xd9\x56\x90\xaf\xee\xbc\xdf\xfc\x65\x1a\x2c\xff\x6d\x33\xe9\x82\x2d\x73\xf9\x3b\xe8\xd0\xff\x05\x00\x00\xff\xff\x03\x49\x27\x73\x2e\x25\x00\x00") func cftGoTemplBytes() ([]byte, error) { return bindataRead( @@ -128,7 +128,7 @@ func cftGoTempl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cft.go.templ", size: 9388, mode: os.FileMode(436), modTime: time.Unix(1544578164, 0)} + info := bindataFileInfo{name: "cft.go.templ", size: 9518, mode: os.FileMode(436), modTime: time.Unix(1553733152, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/configs/aws-service-operator.yaml b/configs/aws-service-operator.yaml index 2c9f2d9a2..8e19a30fb 100644 --- a/configs/aws-service-operator.yaml +++ b/configs/aws-service-operator.yaml @@ -68,6 +68,27 @@ items: scope: Namespaced version: v1alpha1 +- apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + name: eksnodegroups.service-operator.aws + spec: + group: service-operator.aws + names: + kind: EKSNodeGroup + listKind: EKSNodeGroupList + plural: eksnodegroups + shortNames: + - nodegroups + - nodegroup + - eksnodes + - eksnode + - ngs + - ng + singular: eksnodegroup + scope: Namespaced + version: v1alpha1 + - apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: diff --git a/examples/eksnodegroup.yaml b/examples/eksnodegroup.yaml new file mode 100644 index 000000000..923022ae6 --- /dev/null +++ b/examples/eksnodegroup.yaml @@ -0,0 +1,20 @@ +apiVersion: service-operator.aws/v1alpha1 +kind: EKSNodeGroup +metadata: + name: example-eks-nodegroup +spec: + clusterName: "" + node: + imageID: ami-XXXXX + instanceType: m5.large + volumeSize: 20 + # bootstrapArguments: "" + keyName: "" + autoScalingGroup: + minSize: 2 + maxSize: 4 + desiredCapacity: 3 + networking: + controlPlaneSecurityGroup: sg-XXXXX + vpcID: vpc-XXXXX + subnets: subnet-XXXXX,subnet-XXXXX,subnet-XXXXX \ No newline at end of file diff --git a/models/dynamodb.yaml b/models/dynamodb.yaml index 5b1347ffd..23634626f 100644 --- a/models/dynamodb.yaml +++ b/models/dynamodb.yaml @@ -107,4 +107,4 @@ spec: - key: tableARN value: "{{.Obj.Output.TableARN}}" - key: region - value: "{{.Config.Region}}" + value: "{{.Config.Region}}" \ No newline at end of file diff --git a/models/eksnodegroup.yaml b/models/eksnodegroup.yaml new file mode 100644 index 000000000..4fb448955 --- /dev/null +++ b/models/eksnodegroup.yaml @@ -0,0 +1,145 @@ +apiVersion: service-operator.aws/v1alpha1 +kind: ModelDefinition +metadata: + name: EKSNodeGroupResource +spec: + kind: EKSNodeGroup + type: Spec # can be Spec or Data + queue: true + useCloudFormation: true + resource: + name: eksnodegroup + plural: eksnodegroups + shortNames: + - name: nodegroups + - name: nodegroup + - name: eksnodes + - name: eksnode + - name: ngs + - name: ng + scope: Namespaced + body: + schema: + title: EKSNodeGroup + type: object + properties: + - key: nodeGroupName + type: resourceName + description: | + NodeGroupName is the name of the EKS Node Group to be created. + structKey: NodeGroupName + templateKey: NodeGroupName + - key: node + type: object + description: | + Node contains all the configuration for the nodes. + structKey: Node + templateKey: Node + properties: + - key: imageID + type: string + description: | + Image ID is the AMI ID + structKey: NodeImageId + templateKey: NodeImageId + - key: keyName + type: string + description: | + The EC2 Key Pair to allow SSH access to the instances + structKey: KeyName + templateKey: KeyName + - key: instanceType + type: string + description: | + Instance type for the node group. + structKey: NodeInstanceType + templateKey: NodeInstanceType + - key: volumeSize + type: int + description: | + Node volume size + structKey: NodeVolumeSize + templateKey: NodeVolumeSize + - key: bootstrapArguments + type: string + description: | + Arguments to pass to the bootstrap script. See files/bootstrap.sh in https://github.com/awslabs/amazon-eks-ami + structKey: BootstrapArguments + templateKey: BootstrapArguments + - key: autoScalingGroup + type: object + description: | + AutoScalingGroup contains all the ASG configs. + structKey: AutoScalingGroup + templateKey: AutoScalingGroup + properties: + - key: minSize + type: int + description: | + Minimum size of Node Group ASG. + structKey: NodeAutoScalingGroupMinSize + templateKey: NodeAutoScalingGroupMinSize + - key: maxSize + type: int + description: | + Minimum size of Node Group ASG. + structKey: NodeAutoScalingGroupMaxSize + templateKey: NodeAutoScalingGroupMaxSize + - key: desiredCapacity + type: int + description: | + Desired capacity of Node Group ASG. + structKey: NodeAutoScalingGroupDesiredCapacity + templateKey: NodeAutoScalingGroupDesiredCapacity + - key: networking + type: object + description: | + Networking configurations. + structKey: Networking + templateKey: Networking + properties: + - key: controlPlaneSecurityGroup + type: string + description: | + The security group of the cluster control plane. + structKey: ClusterControlPlaneSecurityGroup + templateKey: ClusterControlPlaneSecurityGroup + - key: vpcID + type: string + description: | + The VPC of the worker instances + structKey: VpcId + templateKey: VpcId + - key: subnets + type: string + description: | + The subnets where workers can be created. + structKey: Subnets + templateKey: Subnets + + + output: + schema: + type: object + properties: + - key: nodeInstanceRole + type: string + description: | + The node instance role + structKey: NodeInstanceRole + templateKey: NodeInstanceRole + - key: nodeSecurityGroup + type: string + description: | + The security group for the node group + structKey: NodeSecurityGroup + templateKey: NodeSecurityGroup + + additionalResources: + configMaps: + - name: eksNodeGroupCM + data: + - key: nodeInstanceRole + value: "{{.Obj.Output.NodeInstanceRole}}" + - key: nodeSecurityGroup + value: "{{.Obj.Output.NodeSecurityGroup}}" diff --git a/pkg/apis/service-operator.aws/v1alpha1/eksnodegroup.go b/pkg/apis/service-operator.aws/v1alpha1/eksnodegroup.go new file mode 100644 index 000000000..a5fd70204 --- /dev/null +++ b/pkg/apis/service-operator.aws/v1alpha1/eksnodegroup.go @@ -0,0 +1,93 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// EKSNodeGroup defines the base resource +type EKSNodeGroup struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + Spec EKSNodeGroupSpec `json:"spec"` + Status EKSNodeGroupStatus `json:"status"` + Output EKSNodeGroupOutput `json:"output"` + AdditionalResources EKSNodeGroupAdditionalResources `json:"additionalResources"` +} + +// EKSNodeGroupAutoScalingGroup defines the AutoScalingGroup resource for EKSNodeGroup +type EKSNodeGroupAutoScalingGroup struct { + NodeAutoScalingGroupMinSize int `json:"minSize"` + NodeAutoScalingGroupMaxSize int `json:"maxSize"` + NodeAutoScalingGroupDesiredCapacity int `json:"desiredCapacity"` +} + +// EKSNodeGroupNetworking defines the Networking resource for EKSNodeGroup +type EKSNodeGroupNetworking struct { + ClusterControlPlaneSecurityGroup string `json:"controlPlaneSecurityGroup"` + VpcId string `json:"vpcID"` + Subnets string `json:"subnets"` +} + +// EKSNodeGroupNode defines the Node resource for EKSNodeGroup +type EKSNodeGroupNode struct { + NodeImageId string `json:"imageID"` + KeyName string `json:"keyName"` + NodeInstanceType string `json:"instanceType"` + NodeVolumeSize int `json:"volumeSize"` + BootstrapArguments string `json:"bootstrapArguments"` +} + +// EKSNodeGroupSpec defines the Spec resource for EKSNodeGroup +type EKSNodeGroupSpec struct { + CloudFormationTemplateName string `json:"cloudFormationTemplateName"` + CloudFormationTemplateNamespace string `json:"cloudFormationTemplateNamespace"` + RollbackCount int `json:"rollbackCount"` + Node EKSNodeGroupNode `json:"node"` + AutoScalingGroup EKSNodeGroupAutoScalingGroup `json:"autoScalingGroup"` + Networking EKSNodeGroupNetworking `json:"networking"` +} + +// EKSNodeGroupOutput defines the output resource for EKSNodeGroup +type EKSNodeGroupOutput struct { + NodeInstanceRole string `json:"nodeInstanceRole"` + NodeSecurityGroup string `json:"nodeSecurityGroup"` +} + +// EKSNodeGroupStatus holds the status of the Cloudformation template +type EKSNodeGroupStatus struct { + ResourceStatus string `json:"resourceStatus"` + ResourceStatusReason string `json:"resourceStatusReason"` + StackID string `json:"stackID"` +} + +// EKSNodeGroupAdditionalResources holds the additional resources +type EKSNodeGroupAdditionalResources struct { + ConfigMaps []string `json:"configMaps"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// EKSNodeGroupList defines the list attribute for the EKSNodeGroup type +type EKSNodeGroupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []EKSNodeGroup `json:"items"` +} + +func init() { + localSchemeBuilder.Register(addEKSNodeGroupTypes) +} + +func addEKSNodeGroupTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &EKSNodeGroup{}, + &EKSNodeGroupList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/service-operator.aws/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/service-operator.aws/v1alpha1/zz_generated.deepcopy.go index 9533eaec7..142f0b15b 100644 --- a/pkg/apis/service-operator.aws/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/service-operator.aws/v1alpha1/zz_generated.deepcopy.go @@ -441,6 +441,189 @@ func (in *ECRRepositoryStatus) DeepCopy() *ECRRepositoryStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroup) DeepCopyInto(out *EKSNodeGroup) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status + out.Output = in.Output + in.AdditionalResources.DeepCopyInto(&out.AdditionalResources) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroup. +func (in *EKSNodeGroup) DeepCopy() *EKSNodeGroup { + if in == nil { + return nil + } + out := new(EKSNodeGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EKSNodeGroup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupAdditionalResources) DeepCopyInto(out *EKSNodeGroupAdditionalResources) { + *out = *in + if in.ConfigMaps != nil { + in, out := &in.ConfigMaps, &out.ConfigMaps + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupAdditionalResources. +func (in *EKSNodeGroupAdditionalResources) DeepCopy() *EKSNodeGroupAdditionalResources { + if in == nil { + return nil + } + out := new(EKSNodeGroupAdditionalResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupAutoScalingGroup) DeepCopyInto(out *EKSNodeGroupAutoScalingGroup) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupAutoScalingGroup. +func (in *EKSNodeGroupAutoScalingGroup) DeepCopy() *EKSNodeGroupAutoScalingGroup { + if in == nil { + return nil + } + out := new(EKSNodeGroupAutoScalingGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupList) DeepCopyInto(out *EKSNodeGroupList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]EKSNodeGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupList. +func (in *EKSNodeGroupList) DeepCopy() *EKSNodeGroupList { + if in == nil { + return nil + } + out := new(EKSNodeGroupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *EKSNodeGroupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupNetworking) DeepCopyInto(out *EKSNodeGroupNetworking) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupNetworking. +func (in *EKSNodeGroupNetworking) DeepCopy() *EKSNodeGroupNetworking { + if in == nil { + return nil + } + out := new(EKSNodeGroupNetworking) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupNode) DeepCopyInto(out *EKSNodeGroupNode) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupNode. +func (in *EKSNodeGroupNode) DeepCopy() *EKSNodeGroupNode { + if in == nil { + return nil + } + out := new(EKSNodeGroupNode) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupOutput) DeepCopyInto(out *EKSNodeGroupOutput) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupOutput. +func (in *EKSNodeGroupOutput) DeepCopy() *EKSNodeGroupOutput { + if in == nil { + return nil + } + out := new(EKSNodeGroupOutput) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupSpec) DeepCopyInto(out *EKSNodeGroupSpec) { + *out = *in + out.Node = in.Node + out.AutoScalingGroup = in.AutoScalingGroup + out.Networking = in.Networking + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupSpec. +func (in *EKSNodeGroupSpec) DeepCopy() *EKSNodeGroupSpec { + if in == nil { + return nil + } + out := new(EKSNodeGroupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EKSNodeGroupStatus) DeepCopyInto(out *EKSNodeGroupStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EKSNodeGroupStatus. +func (in *EKSNodeGroupStatus) DeepCopy() *EKSNodeGroupStatus { + if in == nil { + return nil + } + out := new(EKSNodeGroupStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ElastiCache) DeepCopyInto(out *ElastiCache) { *out = *in diff --git a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/eksnodegroup.go b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/eksnodegroup.go new file mode 100644 index 000000000..a7d38090a --- /dev/null +++ b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/eksnodegroup.go @@ -0,0 +1,154 @@ +/* +Licensed 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. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" + scheme "github.com/awslabs/aws-service-operator/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// EKSNodeGroupsGetter has a method to return a EKSNodeGroupInterface. +// A group's client should implement this interface. +type EKSNodeGroupsGetter interface { + EKSNodeGroups(namespace string) EKSNodeGroupInterface +} + +// EKSNodeGroupInterface has methods to work with EKSNodeGroup resources. +type EKSNodeGroupInterface interface { + Create(*v1alpha1.EKSNodeGroup) (*v1alpha1.EKSNodeGroup, error) + Update(*v1alpha1.EKSNodeGroup) (*v1alpha1.EKSNodeGroup, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.EKSNodeGroup, error) + List(opts v1.ListOptions) (*v1alpha1.EKSNodeGroupList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.EKSNodeGroup, err error) + EKSNodeGroupExpansion +} + +// eKSNodeGroups implements EKSNodeGroupInterface +type eKSNodeGroups struct { + client rest.Interface + ns string +} + +// newEKSNodeGroups returns a EKSNodeGroups +func newEKSNodeGroups(c *ServiceoperatorV1alpha1Client, namespace string) *eKSNodeGroups { + return &eKSNodeGroups{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the eKSNodeGroup, and returns the corresponding eKSNodeGroup object, and an error if there is any. +func (c *eKSNodeGroups) Get(name string, options v1.GetOptions) (result *v1alpha1.EKSNodeGroup, err error) { + result = &v1alpha1.EKSNodeGroup{} + err = c.client.Get(). + Namespace(c.ns). + Resource("eksnodegroups"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of EKSNodeGroups that match those selectors. +func (c *eKSNodeGroups) List(opts v1.ListOptions) (result *v1alpha1.EKSNodeGroupList, err error) { + result = &v1alpha1.EKSNodeGroupList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("eksnodegroups"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested eKSNodeGroups. +func (c *eKSNodeGroups) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("eksnodegroups"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a eKSNodeGroup and creates it. Returns the server's representation of the eKSNodeGroup, and an error, if there is any. +func (c *eKSNodeGroups) Create(eKSNodeGroup *v1alpha1.EKSNodeGroup) (result *v1alpha1.EKSNodeGroup, err error) { + result = &v1alpha1.EKSNodeGroup{} + err = c.client.Post(). + Namespace(c.ns). + Resource("eksnodegroups"). + Body(eKSNodeGroup). + Do(). + Into(result) + return +} + +// Update takes the representation of a eKSNodeGroup and updates it. Returns the server's representation of the eKSNodeGroup, and an error, if there is any. +func (c *eKSNodeGroups) Update(eKSNodeGroup *v1alpha1.EKSNodeGroup) (result *v1alpha1.EKSNodeGroup, err error) { + result = &v1alpha1.EKSNodeGroup{} + err = c.client.Put(). + Namespace(c.ns). + Resource("eksnodegroups"). + Name(eKSNodeGroup.Name). + Body(eKSNodeGroup). + Do(). + Into(result) + return +} + +// Delete takes name of the eKSNodeGroup and deletes it. Returns an error if one occurs. +func (c *eKSNodeGroups) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("eksnodegroups"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *eKSNodeGroups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("eksnodegroups"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched eKSNodeGroup. +func (c *eKSNodeGroups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.EKSNodeGroup, err error) { + result = &v1alpha1.EKSNodeGroup{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("eksnodegroups"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_eksnodegroup.go b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_eksnodegroup.go new file mode 100644 index 000000000..0f1cd47a7 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_eksnodegroup.go @@ -0,0 +1,125 @@ +/* +Licensed 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. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeEKSNodeGroups implements EKSNodeGroupInterface +type FakeEKSNodeGroups struct { + Fake *FakeServiceoperatorV1alpha1 + ns string +} + +var eksnodegroupsResource = schema.GroupVersionResource{Group: "serviceoperator.aws", Version: "v1alpha1", Resource: "eksnodegroups"} + +var eksnodegroupsKind = schema.GroupVersionKind{Group: "serviceoperator.aws", Version: "v1alpha1", Kind: "EKSNodeGroup"} + +// Get takes name of the eKSNodeGroup, and returns the corresponding eKSNodeGroup object, and an error if there is any. +func (c *FakeEKSNodeGroups) Get(name string, options v1.GetOptions) (result *v1alpha1.EKSNodeGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(eksnodegroupsResource, c.ns, name), &v1alpha1.EKSNodeGroup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.EKSNodeGroup), err +} + +// List takes label and field selectors, and returns the list of EKSNodeGroups that match those selectors. +func (c *FakeEKSNodeGroups) List(opts v1.ListOptions) (result *v1alpha1.EKSNodeGroupList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(eksnodegroupsResource, eksnodegroupsKind, c.ns, opts), &v1alpha1.EKSNodeGroupList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.EKSNodeGroupList{ListMeta: obj.(*v1alpha1.EKSNodeGroupList).ListMeta} + for _, item := range obj.(*v1alpha1.EKSNodeGroupList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested eKSNodeGroups. +func (c *FakeEKSNodeGroups) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(eksnodegroupsResource, c.ns, opts)) + +} + +// Create takes the representation of a eKSNodeGroup and creates it. Returns the server's representation of the eKSNodeGroup, and an error, if there is any. +func (c *FakeEKSNodeGroups) Create(eKSNodeGroup *v1alpha1.EKSNodeGroup) (result *v1alpha1.EKSNodeGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(eksnodegroupsResource, c.ns, eKSNodeGroup), &v1alpha1.EKSNodeGroup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.EKSNodeGroup), err +} + +// Update takes the representation of a eKSNodeGroup and updates it. Returns the server's representation of the eKSNodeGroup, and an error, if there is any. +func (c *FakeEKSNodeGroups) Update(eKSNodeGroup *v1alpha1.EKSNodeGroup) (result *v1alpha1.EKSNodeGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(eksnodegroupsResource, c.ns, eKSNodeGroup), &v1alpha1.EKSNodeGroup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.EKSNodeGroup), err +} + +// Delete takes name of the eKSNodeGroup and deletes it. Returns an error if one occurs. +func (c *FakeEKSNodeGroups) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(eksnodegroupsResource, c.ns, name), &v1alpha1.EKSNodeGroup{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeEKSNodeGroups) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(eksnodegroupsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.EKSNodeGroupList{}) + return err +} + +// Patch applies the patch and returns the patched eKSNodeGroup. +func (c *FakeEKSNodeGroups) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.EKSNodeGroup, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(eksnodegroupsResource, c.ns, name, data, subresources...), &v1alpha1.EKSNodeGroup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.EKSNodeGroup), err +} diff --git a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_service-operator.aws_client.go b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_service-operator.aws_client.go index 2cbc2d351..e9463b7a6 100644 --- a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_service-operator.aws_client.go +++ b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/fake/fake_service-operator.aws_client.go @@ -37,6 +37,10 @@ func (c *FakeServiceoperatorV1alpha1) ECRRepositories(namespace string) v1alpha1 return &FakeECRRepositories{c, namespace} } +func (c *FakeServiceoperatorV1alpha1) EKSNodeGroups(namespace string) v1alpha1.EKSNodeGroupInterface { + return &FakeEKSNodeGroups{c, namespace} +} + func (c *FakeServiceoperatorV1alpha1) ElastiCaches(namespace string) v1alpha1.ElastiCacheInterface { return &FakeElastiCaches{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/generated_expansion.go index ea2c87286..0e11c7958 100644 --- a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/generated_expansion.go @@ -21,6 +21,8 @@ type DynamoDBExpansion interface{} type ECRRepositoryExpansion interface{} +type EKSNodeGroupExpansion interface{} + type ElastiCacheExpansion interface{} type S3BucketExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/service-operator.aws_client.go b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/service-operator.aws_client.go index 7aa71fe53..cc395e639 100644 --- a/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/service-operator.aws_client.go +++ b/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1/service-operator.aws_client.go @@ -27,6 +27,7 @@ type ServiceoperatorV1alpha1Interface interface { CloudFormationTemplatesGetter DynamoDBsGetter ECRRepositoriesGetter + EKSNodeGroupsGetter ElastiCachesGetter S3BucketsGetter SNSSubscriptionsGetter @@ -51,6 +52,10 @@ func (c *ServiceoperatorV1alpha1Client) ECRRepositories(namespace string) ECRRep return newECRRepositories(c, namespace) } +func (c *ServiceoperatorV1alpha1Client) EKSNodeGroups(namespace string) EKSNodeGroupInterface { + return newEKSNodeGroups(c, namespace) +} + func (c *ServiceoperatorV1alpha1Client) ElastiCaches(namespace string) ElastiCacheInterface { return newElastiCaches(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 9f88b9b4a..a64f3c556 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -56,6 +56,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Serviceoperator().V1alpha1().DynamoDBs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("ecrrepositories"): return &genericInformer{resource: resource.GroupResource(), informer: f.Serviceoperator().V1alpha1().ECRRepositories().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("eksnodegroups"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Serviceoperator().V1alpha1().EKSNodeGroups().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("elasticaches"): return &genericInformer{resource: resource.GroupResource(), informer: f.Serviceoperator().V1alpha1().ElastiCaches().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("s3buckets"): diff --git a/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/eksnodegroup.go b/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/eksnodegroup.go new file mode 100644 index 000000000..ed4fec507 --- /dev/null +++ b/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/eksnodegroup.go @@ -0,0 +1,86 @@ +/* +Licensed 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. +*/ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + service_operator_aws_v1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" + versioned "github.com/awslabs/aws-service-operator/pkg/client/clientset/versioned" + internalinterfaces "github.com/awslabs/aws-service-operator/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/awslabs/aws-service-operator/pkg/client/listers/service-operator.aws/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// EKSNodeGroupInformer provides access to a shared informer and lister for +// EKSNodeGroups. +type EKSNodeGroupInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.EKSNodeGroupLister +} + +type eKSNodeGroupInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewEKSNodeGroupInformer constructs a new informer for EKSNodeGroup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewEKSNodeGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredEKSNodeGroupInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredEKSNodeGroupInformer constructs a new informer for EKSNodeGroup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredEKSNodeGroupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ServiceoperatorV1alpha1().EKSNodeGroups(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ServiceoperatorV1alpha1().EKSNodeGroups(namespace).Watch(options) + }, + }, + &service_operator_aws_v1alpha1.EKSNodeGroup{}, + resyncPeriod, + indexers, + ) +} + +func (f *eKSNodeGroupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredEKSNodeGroupInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *eKSNodeGroupInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&service_operator_aws_v1alpha1.EKSNodeGroup{}, f.defaultInformer) +} + +func (f *eKSNodeGroupInformer) Lister() v1alpha1.EKSNodeGroupLister { + return v1alpha1.NewEKSNodeGroupLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/interface.go b/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/interface.go index bca9063cb..27aabdc51 100644 --- a/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/service-operator.aws/v1alpha1/interface.go @@ -27,6 +27,8 @@ type Interface interface { DynamoDBs() DynamoDBInformer // ECRRepositories returns a ECRRepositoryInformer. ECRRepositories() ECRRepositoryInformer + // EKSNodeGroups returns a EKSNodeGroupInformer. + EKSNodeGroups() EKSNodeGroupInformer // ElastiCaches returns a ElastiCacheInformer. ElastiCaches() ElastiCacheInformer // S3Buckets returns a S3BucketInformer. @@ -65,6 +67,11 @@ func (v *version) ECRRepositories() ECRRepositoryInformer { return &eCRRepositoryInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// EKSNodeGroups returns a EKSNodeGroupInformer. +func (v *version) EKSNodeGroups() EKSNodeGroupInformer { + return &eKSNodeGroupInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // ElastiCaches returns a ElastiCacheInformer. func (v *version) ElastiCaches() ElastiCacheInformer { return &elastiCacheInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/listers/service-operator.aws/v1alpha1/eksnodegroup.go b/pkg/client/listers/service-operator.aws/v1alpha1/eksnodegroup.go new file mode 100644 index 000000000..b43f78af1 --- /dev/null +++ b/pkg/client/listers/service-operator.aws/v1alpha1/eksnodegroup.go @@ -0,0 +1,91 @@ +/* +Licensed 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. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// EKSNodeGroupLister helps list EKSNodeGroups. +type EKSNodeGroupLister interface { + // List lists all EKSNodeGroups in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.EKSNodeGroup, err error) + // EKSNodeGroups returns an object that can list and get EKSNodeGroups. + EKSNodeGroups(namespace string) EKSNodeGroupNamespaceLister + EKSNodeGroupListerExpansion +} + +// eKSNodeGroupLister implements the EKSNodeGroupLister interface. +type eKSNodeGroupLister struct { + indexer cache.Indexer +} + +// NewEKSNodeGroupLister returns a new EKSNodeGroupLister. +func NewEKSNodeGroupLister(indexer cache.Indexer) EKSNodeGroupLister { + return &eKSNodeGroupLister{indexer: indexer} +} + +// List lists all EKSNodeGroups in the indexer. +func (s *eKSNodeGroupLister) List(selector labels.Selector) (ret []*v1alpha1.EKSNodeGroup, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.EKSNodeGroup)) + }) + return ret, err +} + +// EKSNodeGroups returns an object that can list and get EKSNodeGroups. +func (s *eKSNodeGroupLister) EKSNodeGroups(namespace string) EKSNodeGroupNamespaceLister { + return eKSNodeGroupNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// EKSNodeGroupNamespaceLister helps list and get EKSNodeGroups. +type EKSNodeGroupNamespaceLister interface { + // List lists all EKSNodeGroups in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.EKSNodeGroup, err error) + // Get retrieves the EKSNodeGroup from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.EKSNodeGroup, error) + EKSNodeGroupNamespaceListerExpansion +} + +// eKSNodeGroupNamespaceLister implements the EKSNodeGroupNamespaceLister +// interface. +type eKSNodeGroupNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all EKSNodeGroups in the indexer for a given namespace. +func (s eKSNodeGroupNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.EKSNodeGroup, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.EKSNodeGroup)) + }) + return ret, err +} + +// Get retrieves the EKSNodeGroup from the indexer for a given namespace and name. +func (s eKSNodeGroupNamespaceLister) Get(name string) (*v1alpha1.EKSNodeGroup, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("eksnodegroup"), name) + } + return obj.(*v1alpha1.EKSNodeGroup), nil +} diff --git a/pkg/client/listers/service-operator.aws/v1alpha1/expansion_generated.go b/pkg/client/listers/service-operator.aws/v1alpha1/expansion_generated.go index 66fb3f996..5833c071c 100644 --- a/pkg/client/listers/service-operator.aws/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/service-operator.aws/v1alpha1/expansion_generated.go @@ -39,6 +39,14 @@ type ECRRepositoryListerExpansion interface{} // ECRRepositoryNamespaceLister. type ECRRepositoryNamespaceListerExpansion interface{} +// EKSNodeGroupListerExpansion allows custom methods to be added to +// EKSNodeGroupLister. +type EKSNodeGroupListerExpansion interface{} + +// EKSNodeGroupNamespaceListerExpansion allows custom methods to be added to +// EKSNodeGroupNamespaceLister. +type EKSNodeGroupNamespaceListerExpansion interface{} + // ElastiCacheListerExpansion allows custom methods to be added to // ElastiCacheLister. type ElastiCacheListerExpansion interface{} diff --git a/pkg/helpers/template_functions.go b/pkg/helpers/template_functions.go index 9e7014804..42d0e3c40 100644 --- a/pkg/helpers/template_functions.go +++ b/pkg/helpers/template_functions.go @@ -18,6 +18,7 @@ func New() Helpers { GetCloudFormationTemplateByName: GetCloudFormationTemplateByName, GetDynamoDBByName: GetDynamoDBByName, GetECRRepositoryByName: GetECRRepositoryByName, + GetEKSNodeGroupByName: GetEKSNodeGroupByName, GetElastiCacheByName: GetElastiCacheByName, GetS3BucketByName: GetS3BucketByName, GetSNSSubscriptionByName: GetSNSSubscriptionByName, @@ -32,6 +33,7 @@ type Helpers struct { GetCloudFormationTemplateByName func(config.Config, string, string) (interface{}, error) GetDynamoDBByName func(config.Config, string, string) (interface{}, error) GetECRRepositoryByName func(config.Config, string, string) (interface{}, error) + GetEKSNodeGroupByName func(config.Config, string, string) (interface{}, error) GetElastiCacheByName func(config.Config, string, string) (interface{}, error) GetS3BucketByName func(config.Config, string, string) (interface{}, error) GetSNSSubscriptionByName func(config.Config, string, string) (interface{}, error) @@ -78,6 +80,19 @@ func GetECRRepositoryByName(config config.Config, name string, namespace string) return resource, nil } +// GetEKSNodeGroupByName will find the resource by name +func GetEKSNodeGroupByName(config config.Config, name string, namespace string) (interface{}, error) { + logger := config.Logger + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resource, err := clientSet.EKSNodeGroups(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + logger.WithError(err).Error("error getting sns topic") + return "", err + } + + return resource, nil +} + // GetElastiCacheByName will find the resource by name func GetElastiCacheByName(config config.Config, name string, namespace string) (interface{}, error) { logger := config.Logger diff --git a/pkg/operators/base/base.go b/pkg/operators/base/base.go index 6e359e592..681655a22 100644 --- a/pkg/operators/base/base.go +++ b/pkg/operators/base/base.go @@ -6,6 +6,7 @@ import ( "github.com/awslabs/aws-service-operator/pkg/operators/cloudformationtemplate" "github.com/awslabs/aws-service-operator/pkg/operators/dynamodb" "github.com/awslabs/aws-service-operator/pkg/operators/ecrrepository" + "github.com/awslabs/aws-service-operator/pkg/operators/eksnodegroup" "github.com/awslabs/aws-service-operator/pkg/operators/elasticache" "github.com/awslabs/aws-service-operator/pkg/operators/s3bucket" "github.com/awslabs/aws-service-operator/pkg/operators/snssubscription" @@ -20,6 +21,7 @@ type base struct { cloudformationtemplate *cloudformationtemplate.Operator dynamodb *dynamodb.Operator ecrrepository *ecrrepository.Operator + eksnodegroup *eksnodegroup.Operator elasticache *elasticache.Operator s3bucket *s3bucket.Operator snssubscription *snssubscription.Operator @@ -37,6 +39,7 @@ func New( cloudformationtemplate: cloudformationtemplate.NewOperator(config, queueManager), dynamodb: dynamodb.NewOperator(config, queueManager), ecrrepository: ecrrepository.NewOperator(config, queueManager), + eksnodegroup: eksnodegroup.NewOperator(config, queueManager), elasticache: elasticache.NewOperator(config, queueManager), s3bucket: s3bucket.NewOperator(config, queueManager), snssubscription: snssubscription.NewOperator(config, queueManager), @@ -55,6 +58,9 @@ func (b *base) Watch(ctx context.Context, namespace string) { if b.config.Resources["ecrrepository"] { go b.ecrrepository.StartWatch(ctx, namespace) } + if b.config.Resources["eksnodegroup"] { + go b.eksnodegroup.StartWatch(ctx, namespace) + } if b.config.Resources["elasticache"] { go b.elasticache.StartWatch(ctx, namespace) } diff --git a/pkg/operators/dynamodb/cft.go b/pkg/operators/dynamodb/cft.go index d5a384457..21b2e8e1d 100644 --- a/pkg/operators/dynamodb/cft.go +++ b/pkg/operators/dynamodb/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.DynamoDB.Name) @@ -163,6 +166,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.DynamoDB) (output *clo NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.DynamoDB.Name) diff --git a/pkg/operators/ecrrepository/cft.go b/pkg/operators/ecrrepository/cft.go index 926914297..646af18e9 100644 --- a/pkg/operators/ecrrepository/cft.go +++ b/pkg/operators/ecrrepository/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.ECRRepository.Name) @@ -121,6 +124,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.ECRRepository) (output NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.ECRRepository.Name) diff --git a/pkg/operators/eksnodegroup/cft.go b/pkg/operators/eksnodegroup/cft.go new file mode 100644 index 000000000..48dd946d9 --- /dev/null +++ b/pkg/operators/eksnodegroup/cft.go @@ -0,0 +1,342 @@ +// >>>>>>> DO NOT EDIT THIS FILE <<<<<<<<<< +// This file is autogenerated via `aws-operator-codegen process` +// If you'd like the change anything about this file make edits to the .templ +// file in the pkg/codegen/assets directory. + +package eksnodegroup + +import ( + "errors" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudformation" + awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" + "github.com/awslabs/aws-service-operator/pkg/config" + "github.com/awslabs/aws-service-operator/pkg/helpers" +) + +// New generates a new object +func New(config config.Config, eksnodegroup *awsV1alpha1.EKSNodeGroup, topicARN string) *Cloudformation { + return &Cloudformation{ + EKSNodeGroup: eksnodegroup, + config: config, + topicARN: topicARN, + } +} + +// Cloudformation defines the eksnodegroup cfts +type Cloudformation struct { + config config.Config + EKSNodeGroup *awsV1alpha1.EKSNodeGroup + topicARN string +} + +// StackName returns the name of the stack based on the aws-operator-config +func (s *Cloudformation) StackName() string { + return helpers.StackName(s.config.ClusterName, "eksnodegroup", s.EKSNodeGroup.Name, s.EKSNodeGroup.Namespace) +} + +// GetOutputs return the stack outputs from the DescribeStacks call +func (s *Cloudformation) GetOutputs() (map[string]string, error) { + outputs := map[string]string{} + sess := s.config.AWSSession + svc := cloudformation.New(sess) + + stackInputs := cloudformation.DescribeStacksInput{ + StackName: aws.String(s.StackName()), + } + + output, err := svc.DescribeStacks(&stackInputs) + if err != nil { + return nil, err + } + // Not sure if this is even possible + if len(output.Stacks) != 1 { + return nil, errors.New("no stacks returned with that stack name") + } + + for _, out := range output.Stacks[0].Outputs { + outputs[*out.OutputKey] = *out.OutputValue + } + + return outputs, err +} + +// CreateStack will create the stack with the supplied params +func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput, err error) { + sess := s.config.AWSSession + svc := cloudformation.New(sess) + + cftemplate := helpers.GetCloudFormationTemplate(s.config, "eksnodegroup", s.EKSNodeGroup.Spec.CloudFormationTemplateName, s.EKSNodeGroup.Spec.CloudFormationTemplateNamespace) + + stackInputs := cloudformation.CreateStackInput{ + StackName: aws.String(s.StackName()), + TemplateURL: aws.String(cftemplate), + NotificationARNs: []*string{ + aws.String(s.topicARN), + }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, + } + + resourceName := helpers.CreateParam("ResourceName", s.EKSNodeGroup.Name) + resourceVersion := helpers.CreateParam("ResourceVersion", s.EKSNodeGroup.ResourceVersion) + namespace := helpers.CreateParam("Namespace", s.EKSNodeGroup.Namespace) + clusterName := helpers.CreateParam("ClusterName", s.config.ClusterName) + nodeGroupName := helpers.CreateParam("NodeGroupName", helpers.Stringify(s.EKSNodeGroup.Name)) + nodeimageIDTemp := "{{.Obj.Spec.Node.NodeImageId}}" + nodeimageIDValue, err := helpers.Templatize(nodeimageIDTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodeimageID := helpers.CreateParam("NodeImageId", helpers.Stringify(nodeimageIDValue)) + nodekeyNameTemp := "{{.Obj.Spec.Node.KeyName}}" + nodekeyNameValue, err := helpers.Templatize(nodekeyNameTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodekeyName := helpers.CreateParam("KeyName", helpers.Stringify(nodekeyNameValue)) + nodeinstanceTypeTemp := "{{.Obj.Spec.Node.NodeInstanceType}}" + nodeinstanceTypeValue, err := helpers.Templatize(nodeinstanceTypeTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodeinstanceType := helpers.CreateParam("NodeInstanceType", helpers.Stringify(nodeinstanceTypeValue)) + nodevolumeSizeTemp := "{{.Obj.Spec.Node.NodeVolumeSize}}" + nodevolumeSizeValue, err := helpers.Templatize(nodevolumeSizeTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodevolumeSize := helpers.CreateParam("NodeVolumeSize", helpers.Stringify(nodevolumeSizeValue)) + nodebootstrapArgumentsTemp := "{{.Obj.Spec.Node.BootstrapArguments}}" + nodebootstrapArgumentsValue, err := helpers.Templatize(nodebootstrapArgumentsTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodebootstrapArguments := helpers.CreateParam("BootstrapArguments", helpers.Stringify(nodebootstrapArgumentsValue)) + autoScalingGroupminSizeTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupMinSize}}" + autoScalingGroupminSizeValue, err := helpers.Templatize(autoScalingGroupminSizeTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupminSize := helpers.CreateParam("NodeAutoScalingGroupMinSize", helpers.Stringify(autoScalingGroupminSizeValue)) + autoScalingGroupmaxSizeTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupMaxSize}}" + autoScalingGroupmaxSizeValue, err := helpers.Templatize(autoScalingGroupmaxSizeTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupmaxSize := helpers.CreateParam("NodeAutoScalingGroupMaxSize", helpers.Stringify(autoScalingGroupmaxSizeValue)) + autoScalingGroupdesiredCapacityTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupDesiredCapacity}}" + autoScalingGroupdesiredCapacityValue, err := helpers.Templatize(autoScalingGroupdesiredCapacityTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupdesiredCapacity := helpers.CreateParam("NodeAutoScalingGroupDesiredCapacity", helpers.Stringify(autoScalingGroupdesiredCapacityValue)) + networkingcontrolPlaneSecurityGroupTemp := "{{.Obj.Spec.Networking.ClusterControlPlaneSecurityGroup}}" + networkingcontrolPlaneSecurityGroupValue, err := helpers.Templatize(networkingcontrolPlaneSecurityGroupTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingcontrolPlaneSecurityGroup := helpers.CreateParam("ClusterControlPlaneSecurityGroup", helpers.Stringify(networkingcontrolPlaneSecurityGroupValue)) + networkingvpcIDTemp := "{{.Obj.Spec.Networking.VpcId}}" + networkingvpcIDValue, err := helpers.Templatize(networkingvpcIDTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingvpcID := helpers.CreateParam("VpcId", helpers.Stringify(networkingvpcIDValue)) + networkingsubnetsTemp := "{{.Obj.Spec.Networking.Subnets}}" + networkingsubnetsValue, err := helpers.Templatize(networkingsubnetsTemp, helpers.Data{Obj: s.EKSNodeGroup, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingsubnets := helpers.CreateParam("Subnets", helpers.Stringify(networkingsubnetsValue)) + + parameters := []*cloudformation.Parameter{} + parameters = append(parameters, resourceName) + parameters = append(parameters, resourceVersion) + parameters = append(parameters, namespace) + parameters = append(parameters, clusterName) + parameters = append(parameters, nodeGroupName) + parameters = append(parameters, nodeimageID) + parameters = append(parameters, nodekeyName) + parameters = append(parameters, nodeinstanceType) + parameters = append(parameters, nodevolumeSize) + parameters = append(parameters, nodebootstrapArguments) + parameters = append(parameters, autoScalingGroupminSize) + parameters = append(parameters, autoScalingGroupmaxSize) + parameters = append(parameters, autoScalingGroupdesiredCapacity) + parameters = append(parameters, networkingcontrolPlaneSecurityGroup) + parameters = append(parameters, networkingvpcID) + parameters = append(parameters, networkingsubnets) + + stackInputs.SetParameters(parameters) + + resourceNameTag := helpers.CreateTag("ResourceName", s.EKSNodeGroup.Name) + resourceVersionTag := helpers.CreateTag("ResourceVersion", s.EKSNodeGroup.ResourceVersion) + namespaceTag := helpers.CreateTag("Namespace", s.EKSNodeGroup.Namespace) + clusterNameTag := helpers.CreateTag("ClusterName", s.config.ClusterName) + + tags := []*cloudformation.Tag{} + tags = append(tags, resourceNameTag) + tags = append(tags, resourceVersionTag) + tags = append(tags, namespaceTag) + tags = append(tags, clusterNameTag) + + stackInputs.SetTags(tags) + + output, err = svc.CreateStack(&stackInputs) + return +} + +// UpdateStack will update the existing stack +func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.EKSNodeGroup) (output *cloudformation.UpdateStackOutput, err error) { + sess := s.config.AWSSession + svc := cloudformation.New(sess) + + cftemplate := helpers.GetCloudFormationTemplate(s.config, "eksnodegroup", updated.Spec.CloudFormationTemplateName, updated.Spec.CloudFormationTemplateNamespace) + + stackInputs := cloudformation.UpdateStackInput{ + StackName: aws.String(s.StackName()), + TemplateURL: aws.String(cftemplate), + NotificationARNs: []*string{ + aws.String(s.topicARN), + }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, + } + + resourceName := helpers.CreateParam("ResourceName", s.EKSNodeGroup.Name) + resourceVersion := helpers.CreateParam("ResourceVersion", s.EKSNodeGroup.ResourceVersion) + namespace := helpers.CreateParam("Namespace", s.EKSNodeGroup.Namespace) + clusterName := helpers.CreateParam("ClusterName", s.config.ClusterName) + nodeGroupName := helpers.CreateParam("NodeGroupName", helpers.Stringify(s.EKSNodeGroup.Name)) + nodeimageIDTemp := "{{.Obj.Spec.Node.NodeImageId}}" + nodeimageIDValue, err := helpers.Templatize(nodeimageIDTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodeimageID := helpers.CreateParam("NodeImageId", helpers.Stringify(nodeimageIDValue)) + nodekeyNameTemp := "{{.Obj.Spec.Node.KeyName}}" + nodekeyNameValue, err := helpers.Templatize(nodekeyNameTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodekeyName := helpers.CreateParam("KeyName", helpers.Stringify(nodekeyNameValue)) + nodeinstanceTypeTemp := "{{.Obj.Spec.Node.NodeInstanceType}}" + nodeinstanceTypeValue, err := helpers.Templatize(nodeinstanceTypeTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodeinstanceType := helpers.CreateParam("NodeInstanceType", helpers.Stringify(nodeinstanceTypeValue)) + nodevolumeSizeTemp := "{{.Obj.Spec.Node.NodeVolumeSize}}" + nodevolumeSizeValue, err := helpers.Templatize(nodevolumeSizeTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodevolumeSize := helpers.CreateParam("NodeVolumeSize", helpers.Stringify(nodevolumeSizeValue)) + nodebootstrapArgumentsTemp := "{{.Obj.Spec.Node.BootstrapArguments}}" + nodebootstrapArgumentsValue, err := helpers.Templatize(nodebootstrapArgumentsTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + nodebootstrapArguments := helpers.CreateParam("BootstrapArguments", helpers.Stringify(nodebootstrapArgumentsValue)) + autoScalingGroupminSizeTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupMinSize}}" + autoScalingGroupminSizeValue, err := helpers.Templatize(autoScalingGroupminSizeTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupminSize := helpers.CreateParam("NodeAutoScalingGroupMinSize", helpers.Stringify(autoScalingGroupminSizeValue)) + autoScalingGroupmaxSizeTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupMaxSize}}" + autoScalingGroupmaxSizeValue, err := helpers.Templatize(autoScalingGroupmaxSizeTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupmaxSize := helpers.CreateParam("NodeAutoScalingGroupMaxSize", helpers.Stringify(autoScalingGroupmaxSizeValue)) + autoScalingGroupdesiredCapacityTemp := "{{.Obj.Spec.AutoScalingGroup.NodeAutoScalingGroupDesiredCapacity}}" + autoScalingGroupdesiredCapacityValue, err := helpers.Templatize(autoScalingGroupdesiredCapacityTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + autoScalingGroupdesiredCapacity := helpers.CreateParam("NodeAutoScalingGroupDesiredCapacity", helpers.Stringify(autoScalingGroupdesiredCapacityValue)) + networkingcontrolPlaneSecurityGroupTemp := "{{.Obj.Spec.Networking.ClusterControlPlaneSecurityGroup}}" + networkingcontrolPlaneSecurityGroupValue, err := helpers.Templatize(networkingcontrolPlaneSecurityGroupTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingcontrolPlaneSecurityGroup := helpers.CreateParam("ClusterControlPlaneSecurityGroup", helpers.Stringify(networkingcontrolPlaneSecurityGroupValue)) + networkingvpcIDTemp := "{{.Obj.Spec.Networking.VpcId}}" + networkingvpcIDValue, err := helpers.Templatize(networkingvpcIDTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingvpcID := helpers.CreateParam("VpcId", helpers.Stringify(networkingvpcIDValue)) + networkingsubnetsTemp := "{{.Obj.Spec.Networking.Subnets}}" + networkingsubnetsValue, err := helpers.Templatize(networkingsubnetsTemp, helpers.Data{Obj: updated, Config: s.config, Helpers: helpers.New()}) + if err != nil { + return output, err + } + networkingsubnets := helpers.CreateParam("Subnets", helpers.Stringify(networkingsubnetsValue)) + + parameters := []*cloudformation.Parameter{} + parameters = append(parameters, resourceName) + parameters = append(parameters, resourceVersion) + parameters = append(parameters, namespace) + parameters = append(parameters, clusterName) + parameters = append(parameters, nodeGroupName) + parameters = append(parameters, nodeimageID) + parameters = append(parameters, nodekeyName) + parameters = append(parameters, nodeinstanceType) + parameters = append(parameters, nodevolumeSize) + parameters = append(parameters, nodebootstrapArguments) + parameters = append(parameters, autoScalingGroupminSize) + parameters = append(parameters, autoScalingGroupmaxSize) + parameters = append(parameters, autoScalingGroupdesiredCapacity) + parameters = append(parameters, networkingcontrolPlaneSecurityGroup) + parameters = append(parameters, networkingvpcID) + parameters = append(parameters, networkingsubnets) + + stackInputs.SetParameters(parameters) + + resourceNameTag := helpers.CreateTag("ResourceName", s.EKSNodeGroup.Name) + resourceVersionTag := helpers.CreateTag("ResourceVersion", s.EKSNodeGroup.ResourceVersion) + namespaceTag := helpers.CreateTag("Namespace", s.EKSNodeGroup.Namespace) + clusterNameTag := helpers.CreateTag("ClusterName", s.config.ClusterName) + + tags := []*cloudformation.Tag{} + tags = append(tags, resourceNameTag) + tags = append(tags, resourceVersionTag) + tags = append(tags, namespaceTag) + tags = append(tags, clusterNameTag) + + stackInputs.SetTags(tags) + + output, err = svc.UpdateStack(&stackInputs) + return +} + +// DeleteStack will delete the stack +func (s *Cloudformation) DeleteStack() (err error) { + sess := s.config.AWSSession + svc := cloudformation.New(sess) + + stackInputs := cloudformation.DeleteStackInput{} + stackInputs.SetStackName(s.StackName()) + + _, err = svc.DeleteStack(&stackInputs) + return +} + +// WaitUntilStackDeleted will delete the stack +func (s *Cloudformation) WaitUntilStackDeleted() (err error) { + sess := s.config.AWSSession + svc := cloudformation.New(sess) + + stackInputs := cloudformation.DescribeStacksInput{ + StackName: aws.String(s.StackName()), + } + + err = svc.WaitUntilStackDeleteComplete(&stackInputs) + return +} diff --git a/pkg/operators/eksnodegroup/operator.go b/pkg/operators/eksnodegroup/operator.go new file mode 100644 index 000000000..0c32b080a --- /dev/null +++ b/pkg/operators/eksnodegroup/operator.go @@ -0,0 +1,270 @@ +// >>>>>>> DO NOT EDIT THIS FILE <<<<<<<<<< +// This file is autogenerated via `aws-operator generate` +// If you'd like the change anything about this file make edits to the .templ +// file in the pkg/codegen/assets directory. + +package eksnodegroup + +import ( + "context" + "github.com/awslabs/aws-service-operator/pkg/helpers" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "reflect" + + awsclient "github.com/awslabs/aws-service-operator/pkg/client/clientset/versioned/typed/service-operator.aws/v1alpha1" + "github.com/awslabs/aws-service-operator/pkg/config" + "github.com/awslabs/aws-service-operator/pkg/operator" + "github.com/awslabs/aws-service-operator/pkg/queue" + "github.com/awslabs/aws-service-operator/pkg/queuemanager" + "github.com/iancoleman/strcase" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/tools/cache" + "strings" + + awsV1alpha1 "github.com/awslabs/aws-service-operator/pkg/apis/service-operator.aws/v1alpha1" +) + +// Operator represents a controller object for object store custom resources +type Operator struct { + config config.Config + topicARN string + queueManager *queuemanager.QueueManager +} + +// NewOperator create controller for watching object store custom resources created +func NewOperator(config config.Config, queueManager *queuemanager.QueueManager) *Operator { + queuectrl := queue.New(config, config.AWSClientset, 10) + topicARN, _ := queuectrl.Register("eksnodegroup") + queueManager.Add(topicARN, queuemanager.HandlerFunc(QueueUpdater)) + + return &Operator{ + config: config, + topicARN: topicARN, + queueManager: queueManager, + } +} + +// StartWatch watches for instances of Object Store custom resources and acts on them +func (c *Operator) StartWatch(ctx context.Context, namespace string) { + resourceHandlers := cache.ResourceEventHandlerFuncs{ + AddFunc: c.onAdd, + UpdateFunc: c.onUpdate, + DeleteFunc: c.onDelete, + } + + oper := operator.New("eksnodegroups", namespace, resourceHandlers, c.config.AWSClientset.RESTClient()) + oper.Watch(&awsV1alpha1.EKSNodeGroup{}, ctx.Done()) +} + +// QueueUpdater will take the messages from the queue and process them +func QueueUpdater(config config.Config, msg *queuemanager.MessageBody) error { + logger := config.Logger + var name, namespace string + if msg.Updatable { + name = msg.ResourceName + namespace = msg.Namespace + } else { + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resources, err := clientSet.EKSNodeGroups("").List(metav1.ListOptions{}) + if err != nil { + logger.WithError(err).Error("error getting eksnodegroups") + return err + } + for _, resource := range resources.Items { + if resource.Status.StackID == msg.ParsedMessage["StackId"] { + name = resource.Name + namespace = resource.Namespace + } + } + } + + if name != "" && namespace != "" { + annotations := map[string]string{ + "StackID": msg.ParsedMessage["StackId"], + "StackName": msg.ParsedMessage["StackName"], + "ResourceType": msg.ParsedMessage["ResourceType"], + } + if msg.ParsedMessage["ResourceStatus"] == "ROLLBACK_COMPLETE" { + obj, err := deleteStack(config, name, namespace, msg.ParsedMessage["StackId"]) + if err != nil { + return err + } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) + } else if msg.ParsedMessage["ResourceStatus"] == "DELETE_COMPLETE" { + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + if err != nil { + return err + } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeWarning, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) + err = incrementRollbackCount(config, name, namespace) + if err != nil { + return err + } + } else { + obj, err := updateStatus(config, name, namespace, msg.ParsedMessage["StackId"], msg.ParsedMessage["ResourceStatus"], msg.ParsedMessage["ResourceStatusReason"]) + if err != nil { + return err + } + config.Recorder.AnnotatedEventf(obj, annotations, corev1.EventTypeNormal, strcase.ToCamel(strings.ToLower(msg.ParsedMessage["ResourceStatus"])), msg.ParsedMessage["ResourceStatusReason"]) + } + + } + + return nil +} + +func (c *Operator) onAdd(obj interface{}) { + s := obj.(*awsV1alpha1.EKSNodeGroup).DeepCopy() + if s.Status.ResourceStatus == "" || s.Status.ResourceStatus == "DELETE_COMPLETE" { + cft := New(c.config, s, c.topicARN) + output, err := cft.CreateStack() + if err != nil { + c.config.Logger.WithError(err).Errorf("error creating eksnodegroup '%s'", s.Name) + return + } + c.config.Logger.Infof("added eksnodegroup '%s' with stackID '%s'", s.Name, string(*output.StackId)) + c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) + + _, err = updateStatus(c.config, s.Name, s.Namespace, string(*output.StackId), "CREATE_IN_PROGRESS", "") + if err != nil { + c.config.Logger.WithError(err).Error("error updating status") + } + } +} + +func (c *Operator) onUpdate(oldObj, newObj interface{}) { + oo := oldObj.(*awsV1alpha1.EKSNodeGroup).DeepCopy() + no := newObj.(*awsV1alpha1.EKSNodeGroup).DeepCopy() + + if no.Status.ResourceStatus == "DELETE_COMPLETE" { + c.onAdd(no) + } + if helpers.IsStackComplete(oo.Status.ResourceStatus, false) && !reflect.DeepEqual(oo.Spec, no.Spec) { + cft := New(c.config, oo, c.topicARN) + output, err := cft.UpdateStack(no) + if err != nil { + c.config.Logger.WithError(err).Errorf("error updating eksnodegroup '%s' with new params %+v and old %+v", no.Name, no, oo) + return + } + c.config.Logger.Infof("updated eksnodegroup '%s' with params '%s'", no.Name, string(*output.StackId)) + c.config.Logger.Infof("view at https://console.aws.amazon.com/cloudformation/home?#/stack/detail?stackId=%s", string(*output.StackId)) + + _, err = updateStatus(c.config, oo.Name, oo.Namespace, string(*output.StackId), "UPDATE_IN_PROGRESS", "") + if err != nil { + c.config.Logger.WithError(err).Error("error updating status") + } + } +} + +func (c *Operator) onDelete(obj interface{}) { + s := obj.(*awsV1alpha1.EKSNodeGroup).DeepCopy() + cft := New(c.config, s, c.topicARN) + err := cft.DeleteStack() + if err != nil { + c.config.Logger.WithError(err).Errorf("error deleting eksnodegroup '%s'", s.Name) + return + } + + c.config.Logger.Infof("deleted eksnodegroup '%s'", s.Name) +} +func incrementRollbackCount(config config.Config, name string, namespace string) error { + logger := config.Logger + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resource, err := clientSet.EKSNodeGroups(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + logger.WithError(err).Error("error getting eksnodegroups") + return err + } + + resourceCopy := resource.DeepCopy() + resourceCopy.Spec.RollbackCount = resourceCopy.Spec.RollbackCount + 1 + + _, err = clientSet.EKSNodeGroups(namespace).Update(resourceCopy) + if err != nil { + logger.WithError(err).Error("error updating resource") + return err + } + return nil +} + +func updateStatus(config config.Config, name string, namespace string, stackID string, status string, reason string) (*awsV1alpha1.EKSNodeGroup, error) { + logger := config.Logger + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resource, err := clientSet.EKSNodeGroups(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + logger.WithError(err).Error("error getting eksnodegroups") + return nil, err + } + + resourceCopy := resource.DeepCopy() + resourceCopy.Status.ResourceStatus = status + resourceCopy.Status.ResourceStatusReason = reason + resourceCopy.Status.StackID = stackID + + if helpers.IsStackComplete(status, false) { + cft := New(config, resourceCopy, "") + outputs, err := cft.GetOutputs() + if err != nil { + logger.WithError(err).Error("error getting outputs") + } + resourceCopy.Output.NodeInstanceRole = outputs["NodeInstanceRole"] + resourceCopy.Output.NodeSecurityGroup = outputs["NodeSecurityGroup"] + } + + _, err = clientSet.EKSNodeGroups(namespace).Update(resourceCopy) + if err != nil { + logger.WithError(err).Error("error updating resource") + return nil, err + } + + if helpers.IsStackComplete(status, false) { + err = syncAdditionalResources(config, resourceCopy) + if err != nil { + logger.WithError(err).Info("error syncing resources") + } + } + return resourceCopy, nil +} + +func deleteStack(config config.Config, name string, namespace string, stackID string) (*awsV1alpha1.EKSNodeGroup, error) { + logger := config.Logger + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resource, err := clientSet.EKSNodeGroups(namespace).Get(name, metav1.GetOptions{}) + if err != nil { + logger.WithError(err).Error("error getting eksnodegroups") + return nil, err + } + + cft := New(config, resource, "") + err = cft.DeleteStack() + if err != nil { + return nil, err + } + + err = cft.WaitUntilStackDeleted() + return resource, err +} + +func syncAdditionalResources(config config.Config, s *awsV1alpha1.EKSNodeGroup) (err error) { + clientSet, _ := awsclient.NewForConfig(config.RESTConfig) + resource, err := clientSet.EKSNodeGroups(s.Namespace).Get(s.Name, metav1.GetOptions{}) + if err != nil { + return err + } + resource = resource.DeepCopy() + + configmaps := []string{} + eksNodeGroupCMData := map[string]string{ + "nodeInstanceRole": "{{.Obj.Output.NodeInstanceRole}}", + "nodeSecurityGroup": "{{.Obj.Output.NodeSecurityGroup}}", + } + eksNodeGroupCM := helpers.CreateConfigMap(config, s, s.Name, s.Namespace, eksNodeGroupCMData) + configmaps = append(configmaps, eksNodeGroupCM) + resource.AdditionalResources.ConfigMaps = configmaps + + _, err = clientSet.EKSNodeGroups(s.Namespace).Update(resource) + if err != nil { + return err + } + return nil +} diff --git a/pkg/operators/elasticache/cft.go b/pkg/operators/elasticache/cft.go index b36ce13d4..c29fd3ec4 100644 --- a/pkg/operators/elasticache/cft.go +++ b/pkg/operators/elasticache/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.ElastiCache.Name) @@ -226,6 +229,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.ElastiCache) (output * NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.ElastiCache.Name) diff --git a/pkg/operators/s3bucket/cft.go b/pkg/operators/s3bucket/cft.go index 0a14815f5..4c3336541 100644 --- a/pkg/operators/s3bucket/cft.go +++ b/pkg/operators/s3bucket/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.S3Bucket.Name) @@ -170,6 +173,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.S3Bucket) (output *clo NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.S3Bucket.Name) diff --git a/pkg/operators/snssubscription/cft.go b/pkg/operators/snssubscription/cft.go index 3c8ee0df7..edd63943a 100644 --- a/pkg/operators/snssubscription/cft.go +++ b/pkg/operators/snssubscription/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SNSSubscription.Name) @@ -147,6 +150,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.SNSSubscription) (outp NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SNSSubscription.Name) diff --git a/pkg/operators/snstopic/cft.go b/pkg/operators/snstopic/cft.go index 5e04c2395..79a815f1d 100644 --- a/pkg/operators/snstopic/cft.go +++ b/pkg/operators/snstopic/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SNSTopic.Name) @@ -119,6 +122,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.SNSTopic) (output *clo NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SNSTopic.Name) diff --git a/pkg/operators/sqsqueue/cft.go b/pkg/operators/sqsqueue/cft.go index fdd261a9a..26d0ed20e 100644 --- a/pkg/operators/sqsqueue/cft.go +++ b/pkg/operators/sqsqueue/cft.go @@ -74,6 +74,9 @@ func (s *Cloudformation) CreateStack() (output *cloudformation.CreateStackOutput NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SQSQueue.Name) @@ -175,6 +178,9 @@ func (s *Cloudformation) UpdateStack(updated *awsV1alpha1.SQSQueue) (output *clo NotificationARNs: []*string{ aws.String(s.topicARN), }, + Capabilities: []*string{ + aws.String("CAPABILITY_IAM"), + }, } resourceName := helpers.CreateParam("ResourceName", s.SQSQueue.Name)