├── test └── e2e │ ├── common │ ├── types.py │ ├── __init__.py │ └── waiter.py │ ├── .gitignore │ ├── requirements.txt │ ├── resources │ ├── pod_identity_association.yaml │ ├── capability_simple.yaml │ ├── cluster_adoption.yaml │ ├── addon_simple.yaml │ ├── access_entry_simple.yaml │ ├── fargateprofile_default.yaml │ ├── addon_pia.yaml │ ├── identity_provider_config.yaml │ ├── nodegroup_simple.yaml │ ├── cluster_simple.yaml │ └── cluster_automode.yaml │ ├── tests │ ├── __init__.py │ ├── test_capability.py │ └── test_pod_identity_association.py │ ├── service_cleanup.py │ ├── __init__.py │ ├── bootstrap_resources.py │ ├── replacement_values.py │ ├── conftest.py │ ├── fixtures.py │ └── service_bootstrap.py ├── NOTICE ├── OWNERS ├── templates └── hooks │ ├── capability │ ├── sdk_update_post_build_request.go.tpl │ └── sdk_update_pre_build_request.go.tpl │ ├── nodegroup │ ├── sdk_delete_pre_build_request.go.tpl │ ├── sdk_create_post_set_output.go.tpl │ ├── sdk_read_one_post_set_output.go.tpl │ └── sdk_file_end.go.tpl │ ├── fargate_profile │ └── sdk_delete_pre_build_request.go.tpl │ ├── access_entry │ ├── sdk_read_one_post_set_output.go.tpl │ └── sdk_update_pre_build_request.go.tpl │ ├── addons │ ├── sdk_update_post_set_output.go.tpl │ ├── sdk_update_post_build_request.go.tpl │ ├── sdk_create_post_set_output.go.tpl │ ├── sdk_read_one_post_set_output.go.tpl │ └── sdk_update_pre_build_request.go.tpl │ ├── pod_identity_association │ ├── sdk_create_post_set_output.go.tpl │ ├── sdk_read_one_post_set_output.go.tpl │ ├── sdk_update_post_build_request.go.tpl │ └── sdk_update_pre_build_request.go.tpl │ ├── cluster │ ├── sdk_delete_pre_build_request.go.tpl │ ├── sdk_read_one_post_set_output.go.tpl │ ├── sdk_file_end.go.tpl │ └── sdk_create_post_set_output.go.tpl │ └── identity_provider_config │ ├── sdk_read_one_post_build_request.go.tpl │ ├── sdk_delete_post_build_request.go.tpl │ ├── post_populate_resource_from_annotation.go.tpl │ ├── sdk_create_post_set_output.go.tpl │ ├── post_set_resource_identifiers.go.tpl │ └── sdk_read_one_post_set_output.go.tpl ├── .gitignore ├── config ├── rbac │ ├── service-account.yaml │ ├── kustomization.yaml │ ├── cluster-role-binding.yaml │ ├── leader-election-role-binding.yaml │ ├── leader-election-role.yaml │ ├── role-reader.yaml │ ├── role-writer.yaml │ └── cluster-role-controller.yaml ├── overlays │ └── namespaced │ │ ├── role.json │ │ ├── role-binding.json │ │ └── kustomization.yaml ├── crd │ ├── common │ │ ├── kustomization.yaml │ │ └── bases │ │ │ └── services.k8s.aws_iamroleselectors.yaml │ └── kustomization.yaml ├── controller │ ├── kustomization.yaml │ ├── service.yaml │ └── deployment.yaml ├── iam │ └── recommended-inline-policy └── default │ └── kustomization.yaml ├── apis └── v1alpha1 │ ├── doc.go │ ├── ack-generate-metadata.yaml │ ├── groupversion_info.go │ ├── annotation.go │ └── identity_provider_config.go ├── .github └── workflows │ ├── postsubmit.yaml │ └── create-release.yml ├── SECURITY.md ├── metadata.yaml ├── CODE_OF_CONDUCT.md ├── OWNERS_ALIASES ├── go.local.mod ├── helm ├── Chart.yaml ├── templates │ ├── service-account.yaml │ ├── NOTES.txt │ ├── role-reader.yaml │ ├── leader-election-role.yaml │ ├── leader-election-role-binding.yaml │ ├── metrics-service.yaml │ ├── role-writer.yaml │ ├── caches-role.yaml │ ├── cluster-role-controller.yaml │ ├── caches-role-binding.yaml │ ├── cluster-role-binding.yaml │ └── _helpers.tpl └── crds │ └── services.k8s.aws_iamroleselectors.yaml ├── pkg ├── resource │ ├── pod_identity_association │ │ ├── hooks.go │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ └── tags.go │ ├── addon │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ ├── tags.go │ │ └── resource.go │ ├── cluster │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ ├── tags.go │ │ └── resource.go │ ├── nodegroup │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ └── tags.go │ ├── capability │ │ ├── identifiers.go │ │ ├── references.go │ │ ├── manager_factory.go │ │ ├── hooks.go │ │ └── tags.go │ ├── access_entry │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ ├── delta.go │ │ └── tags.go │ ├── fargate_profile │ │ ├── identifiers.go │ │ ├── hook.go │ │ ├── manager_factory.go │ │ └── tags.go │ ├── identity_provider_config │ │ ├── identifiers.go │ │ ├── hooks.go │ │ ├── manager_factory.go │ │ └── tags.go │ └── registry.go └── version │ └── version.go ├── Makefile ├── olm └── olmconfig.yaml ├── GOVERNANCE.md ├── README.md └── CONTRIBUTING.md /test/e2e/common/types.py: -------------------------------------------------------------------------------- 1 | CLUSTER_RESOURCE_PLURAL = 'clusters' -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /test/e2e/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | **/bootstrap.yaml 4 | **/bootstrap.pkl -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - core-ack-team -------------------------------------------------------------------------------- /templates/hooks/capability/sdk_update_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | setConfiguration(input, desired, latest) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~ 4 | .idea 5 | .vscode 6 | /docs/site 7 | bin 8 | build 9 | .env 10 | vendor -------------------------------------------------------------------------------- /test/e2e/requirements.txt: -------------------------------------------------------------------------------- 1 | acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@459836d89145c81fbb9719419d76ea43ad0504d1 -------------------------------------------------------------------------------- /templates/hooks/nodegroup/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if nodegroupDeleting(r) { 2 | return r, requeueWaitWhileDeleting 3 | } 4 | -------------------------------------------------------------------------------- /templates/hooks/fargate_profile/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if profileDeleting(r) { 2 | return r, requeueWaitWhileDeleting 3 | } 4 | -------------------------------------------------------------------------------- /config/rbac/service-account.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: ack-eks-controller 6 | namespace: ack-system 7 | -------------------------------------------------------------------------------- /templates/hooks/access_entry/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if err := rm.setResourceAdditionalFields(ctx, ko); err != nil { 2 | return nil, err 3 | } -------------------------------------------------------------------------------- /config/overlays/namespaced/role.json: -------------------------------------------------------------------------------- 1 | [{"op": "replace", "path": "/kind", "value": "Role"}, 2 | {"op": "add", "path": "/metadata/namespace", "value": "ack-system"}] -------------------------------------------------------------------------------- /apis/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // +k8s:deepcopy-gen=package 2 | // Package v1alpha1 is the v1alpha1 version of the eks.services.k8s.aws API. 3 | // +groupName=eks.services.k8s.aws 4 | package v1alpha1 5 | -------------------------------------------------------------------------------- /templates/hooks/addons/sdk_update_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // Updating addons will very likely change the state of the addon 2 | // so we should requeue the resource to check the status again. 3 | returnAddonUpdating(&resource{ko}) -------------------------------------------------------------------------------- /templates/hooks/pod_identity_association/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if resp.Association.AssociationArn != nil { 2 | ko.Status.ACKResourceMetadata.ARN = (*ackv1alpha1.AWSResourceName)(resp.Association.AssociationArn) 3 | } -------------------------------------------------------------------------------- /templates/hooks/pod_identity_association/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if resp.Association.AssociationArn != nil { 2 | ko.Status.ACKResourceMetadata.ARN = (*ackv1alpha1.AWSResourceName)(resp.Association.AssociationArn) 3 | } -------------------------------------------------------------------------------- /config/overlays/namespaced/role-binding.json: -------------------------------------------------------------------------------- 1 | [{"op": "replace", "path": "/kind", "value": "RoleBinding"}, 2 | {"op": "add", "path": "/metadata/namespace", "value": "ack-system"}, 3 | {"op": "replace", "path": "/roleRef/kind", "value": "Role"}] -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - cluster-role-binding.yaml 3 | - cluster-role-controller.yaml 4 | - role-reader.yaml 5 | - role-writer.yaml 6 | - service-account.yaml 7 | - leader-election-role.yaml 8 | - leader-election-role-binding.yaml 9 | -------------------------------------------------------------------------------- /.github/workflows/postsubmit.yaml: -------------------------------------------------------------------------------- 1 | name: Hydrate Go Proxy 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | call-hydrate-go-proxy: 10 | uses: aws-controllers-k8s/.github/.github/workflows/reusable-postsubmit.yaml@main 11 | -------------------------------------------------------------------------------- /config/crd/common/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Code generated in runtime. DO NOT EDIT. 2 | 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | resources: 6 | - bases/services.k8s.aws_iamroleselectors.yaml 7 | - bases/services.k8s.aws_fieldexports.yaml 8 | -------------------------------------------------------------------------------- /templates/hooks/cluster/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if clusterDeleting(r) { 2 | return r, requeueWaitWhileDeleting 3 | } 4 | inUse, err := rm.clusterInUse(ctx, r); 5 | if err != nil { 6 | return nil, err 7 | } else if inUse { 8 | return r, requeueWaitWhileInUse 9 | } -------------------------------------------------------------------------------- /test/e2e/resources/pod_identity_association.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: PodIdentityAssociation 3 | metadata: 4 | name: $CR_NAME 5 | spec: 6 | clusterName: $CLUSTER_NAME 7 | namespace: $NAMESPACE 8 | roleARN: $ROLE_ARN 9 | serviceAccount: $SERVICE_ACCOUNT -------------------------------------------------------------------------------- /config/controller/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - deployment.yaml 3 | - service.yaml 4 | apiVersion: kustomize.config.k8s.io/v1beta1 5 | kind: Kustomization 6 | images: 7 | - name: controller 8 | newName: public.ecr.aws/aws-controllers-k8s/eks-controller 9 | newTag: 1.11.0 10 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security issue notifications 2 | 3 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 4 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | full_name: "Amazon Elastic Kubernetes Service" 3 | short_name: "EKS" 4 | link: "https://aws.amazon.com/eks/" 5 | documentation: "https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html" 6 | api_versions: 7 | - api_version: v1alpha1 8 | status: available 9 | -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/sdk_read_one_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | identityProviderConfigType := IdentityProviderConfigType 2 | input.IdentityProviderConfig = &svcsdktypes.IdentityProviderConfig{ 3 | Name: r.ko.Spec.OIDC.IdentityProviderConfigName, 4 | Type: &identityProviderConfigType, 5 | } -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/sdk_delete_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | identityProviderConfigType := IdentityProviderConfigType 2 | input.IdentityProviderConfig = &svcsdktypes.IdentityProviderConfig{ 3 | Name: r.ko.Spec.OIDC.IdentityProviderConfigName, 4 | Type: &identityProviderConfigType, 5 | } 6 | -------------------------------------------------------------------------------- /test/e2e/resources/capability_simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Capability 3 | metadata: 4 | name: $CAPABILITY_NAME 5 | spec: 6 | name: $CAPABILITY_NAME 7 | clusterName: $CLUSTER_NAME 8 | roleARN: $CAPABILITY_ROLE_ARN 9 | type: ACK 10 | deletePropagationPolicy: RETAIN 11 | -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/post_populate_resource_from_annotation.go.tpl: -------------------------------------------------------------------------------- 1 | 2 | if f0, f0ok := fields["identityProviderConfigName"]; f0ok { 3 | r.ko.Spec.OIDC = &svcapitypes.OIDCIdentityProviderConfigRequest{ 4 | IdentityProviderConfigName: &f0, 5 | } 6 | } else { 7 | return ackerrors.MissingNameIdentifier 8 | } -------------------------------------------------------------------------------- /.github/workflows/create-release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*.*.*" 7 | 8 | permissions: 9 | contents: write # For creating releases 10 | 11 | jobs: 12 | call-create-release: 13 | uses: aws-controllers-k8s/.github/.github/workflows/reusable-create-release.yaml@main 14 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /test/e2e/resources/cluster_adoption.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Cluster 3 | metadata: 4 | name: $CLUSTER_ADOPTION_NAME 5 | annotations: 6 | services.k8s.aws/adoption-policy: $ADOPTION_POLICY 7 | services.k8s.aws/adoption-fields: "$ADOPTION_FIELDS" 8 | services.k8s.aws/deletion-policy: retain 9 | -------------------------------------------------------------------------------- /test/e2e/resources/addon_simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Addon 3 | metadata: 4 | name: $CR_NAME 5 | spec: 6 | name: $ADDON_NAME 7 | addonVersion: $ADDON_VERSION 8 | clusterName: $CLUSTER_NAME 9 | configurationValues: | 10 | $CONFIGURATION_VALUES 11 | resolveConflicts: $RESOLVE_CONFLICTS 12 | -------------------------------------------------------------------------------- /templates/hooks/addons/sdk_update_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | // If a user deleted all the PodIdentityAssociations we should send an empty list to the API 2 | if delta.DifferentAt("Spec.PodIdentityAssociations") && len(desired.ko.Spec.PodIdentityAssociations) == 0 { 3 | input.PodIdentityAssociations = []svcsdktypes.AddonPodIdentityAssociations{} 4 | } -------------------------------------------------------------------------------- /templates/hooks/pod_identity_association/sdk_update_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | // UpdatePodIdentityAssociation does not unset TargetRoleARN if input set to nil. 2 | // Need to provide empty string instead for TargetRoleARN to be unset in update operation. 3 | if desired.ko.Spec.TargetRoleARN == nil { 4 | temp := "" 5 | input.TargetRoleArn = &temp 6 | } -------------------------------------------------------------------------------- /config/controller/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: ack-eks-metrics-service 5 | namespace: ack-system 6 | spec: 7 | selector: 8 | app.kubernetes.io/name: ack-eks-controller 9 | ports: 10 | - name: metricsport 11 | port: 8080 12 | targetPort: http 13 | protocol: TCP 14 | type: ClusterIP 15 | -------------------------------------------------------------------------------- /test/e2e/resources/access_entry_simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: AccessEntry 3 | metadata: 4 | name: $CR_NAME 5 | spec: 6 | clusterName: $CLUSTER_NAME 7 | principalARN: $PRINCIPAL_ARN 8 | accessPolicies: 9 | - policyARN: $ACCESS_POLICY_ARN 10 | accessScope: 11 | type: namespace 12 | namespaces: ["prod-1"] -------------------------------------------------------------------------------- /config/rbac/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: ack-eks-controller-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: ack-eks-controller 9 | subjects: 10 | - kind: ServiceAccount 11 | name: ack-eks-controller 12 | namespace: ack-system 13 | -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | identityProviderStatus := StatusCreating 2 | ko.Status.Status = &identityProviderStatus 3 | 4 | // Setting resource synced condition to false will trigger a requeue of 5 | // the resource. No need to return a requeue error here. 6 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 7 | 8 | -------------------------------------------------------------------------------- /test/e2e/resources/fargateprofile_default.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: FargateProfile 3 | metadata: 4 | name: $PROFILE_NAME 5 | spec: 6 | name: $PROFILE_NAME 7 | clusterName: $CLUSTER_NAME 8 | podExecutionRoleARN: $FARGATE_POD_ROLE 9 | subnets: 10 | - "$PRIVATE_SUBNET_1" 11 | - "$PRIVATE_SUBNET_2" 12 | selectors: 13 | - namespace: default -------------------------------------------------------------------------------- /test/e2e/resources/addon_pia.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Addon 3 | metadata: 4 | name: $CR_NAME 5 | spec: 6 | name: $ADDON_NAME 7 | addonVersion: $ADDON_VERSION 8 | clusterName: $CLUSTER_NAME 9 | podIdentityAssociations: 10 | - serviceAccount: adot-col-otlp-ingest 11 | roleARN: $ROLE_ARN 12 | - serviceAccount: adot-col-container-logs 13 | roleARN: $ROLE_ARN -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners#owners_aliases 2 | 3 | aliases: 4 | core-ack-team: 5 | - a-hilaly 6 | - jlbutler 7 | - michaelhtm 8 | - rushmash91 9 | - knottnt 10 | # emeritus-core-ack-team: 11 | # - TiberiuGC 12 | # - jaypipes 13 | # - jljaco 14 | # - mhausenblas 15 | # - RedbackThomson 16 | # - vijtrip2 17 | # - ivelichkovich -------------------------------------------------------------------------------- /config/rbac/leader-election-role-binding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | namespace: ack-system 6 | name: eks-leader-election-rolebinding 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: Role 10 | name: eks-leader-election-role 11 | subjects: 12 | - kind: ServiceAccount 13 | name: ack-eks-controller 14 | namespace: ack-system 15 | -------------------------------------------------------------------------------- /test/e2e/resources/identity_provider_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: IdentityProviderConfig 3 | metadata: 4 | name: $CR_NAME 5 | spec: 6 | clusterName: $CLUSTER_NAME 7 | oidc: 8 | clientID: client 9 | identityProviderConfigName: $IDP_NAME 10 | issuerURL: https://some-url.com/ 11 | usernameClaim: user 12 | groupsClaim: group 13 | tags: 14 | tkey: tval 15 | 16 | -------------------------------------------------------------------------------- /config/overlays/namespaced/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../default 3 | patches: 4 | - path: role.json 5 | target: 6 | group: rbac.authorization.k8s.io 7 | version: v1 8 | kind: ClusterRole 9 | name: ack-eks-controller 10 | - path: role-binding.json 11 | target: 12 | group: rbac.authorization.k8s.io 13 | version: v1 14 | kind: ClusterRoleBinding 15 | name: ack-eks-controller-rolebinding -------------------------------------------------------------------------------- /config/iam/recommended-inline-policy: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "eks:*", 8 | "iam:GetRole", 9 | "iam:PassRole", 10 | "iam:ListAttachedRolePolicies", 11 | "ec2:DescribeSubnets" 12 | ], 13 | "Resource": "*" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/post_set_resource_identifiers.go.tpl: -------------------------------------------------------------------------------- 1 | 2 | if identifier.AdditionalKeys == nil { 3 | return ackerrors.MissingNameIdentifier 4 | } 5 | f0, f0ok := identifier.AdditionalKeys["identityProviderConfigName"] 6 | if f0ok { 7 | r.ko.Spec.OIDC = &svcapitypes.OIDCIdentityProviderConfigRequest{ 8 | IdentityProviderConfigName: &f0, 9 | } 10 | } else { 11 | return ackerrors.MissingNameIdentifier 12 | } 13 | -------------------------------------------------------------------------------- /templates/hooks/capability/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if delta.DifferentAt("Spec.Tags") { 2 | err := syncTags( 3 | ctx, rm.sdkapi, rm.metrics, 4 | string(*latest.ko.Status.ACKResourceMetadata.ARN), 5 | aws.ToStringMap(desired.ko.Spec.Tags), aws.ToStringMap(latest.ko.Spec.Tags), 6 | ) 7 | if err != nil { 8 | return nil, err 9 | } 10 | } 11 | if !delta.DifferentExcept("Spec.Tags"){ 12 | return desired, nil 13 | } -------------------------------------------------------------------------------- /test/e2e/common/__init__.py: -------------------------------------------------------------------------------- 1 | # Ideally this should be a programatically resolved value, but it's not clear 2 | # how to do that. 3 | TESTS_DEFAULT_KUBERNETES_VERSION_1_32 = '1.32' 4 | TESTS_DEFAULT_KUBERNETES_VERSION_1_31 = '1.31' 5 | TESTS_DEFAULT_KUBERNETES_VERSION_1_30 = '1.30' 6 | # This is a release version that will be used with 1.32 Nodegroups. 7 | TESTS_DEFAULT_KUBERNETES_RELEASE_VERSION_1_32 = '1.32.1-20250317' 8 | TESTS_DEFAULT_KUBERNETES_RELEASE_VERSION_1_31 = '1.31.5-20250317' -------------------------------------------------------------------------------- /test/e2e/resources/nodegroup_simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Nodegroup 3 | metadata: 4 | name: $NODEGROUP_NAME 5 | spec: 6 | name: $NODEGROUP_NAME 7 | clusterName: $CLUSTER_NAME 8 | subnets: 9 | - "$PUBLIC_SUBNET_1" 10 | - "$PUBLIC_SUBNET_2" 11 | nodeRole: $NODEGROUP_ROLE 12 | scalingConfig: 13 | minSize: 1 14 | maxSize: 1 15 | desiredSize: 1 16 | version: "$K8S_VERSION" 17 | releaseVersion: "$RELEASE_VERSION" -------------------------------------------------------------------------------- /test/e2e/resources/cluster_simple.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Cluster 3 | metadata: 4 | name: $CLUSTER_NAME 5 | spec: 6 | name: $CLUSTER_NAME 7 | roleARN: $CLUSTER_ROLE 8 | accessConfig: 9 | authenticationMode: $AUTHENTICATION_MODE 10 | version: "$K8S_VERSION" 11 | resourcesVPCConfig: 12 | endpointPrivateAccess: true 13 | endpointPublicAccess: true 14 | subnetIDs: 15 | - "$PUBLIC_SUBNET_1" 16 | - "$PUBLIC_SUBNET_2" -------------------------------------------------------------------------------- /templates/hooks/addons/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // We expect the addon to be in 'CREATING' status since we just issued 2 | // the call to create it, but I suppose it doesn't hurt to check here. 3 | if addonCreating(&resource{ko}) { 4 | // Setting resource synced condition to false will trigger a requeue of 5 | // the resource. No need to return a requeue error here. 6 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 7 | return &resource{ko}, nil 8 | } 9 | -------------------------------------------------------------------------------- /config/rbac/leader-election-role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: eks-leader-election-role 6 | namespace: ack-system 7 | rules: 8 | - apiGroups: 9 | - coordination.k8s.io 10 | resources: 11 | - leases 12 | verbs: 13 | - get 14 | - list 15 | - watch 16 | - create 17 | - update 18 | - patch 19 | - delete 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - events 24 | verbs: 25 | - create 26 | - patch 27 | -------------------------------------------------------------------------------- /templates/hooks/nodegroup/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // We expect the nodegroup to be in 'CREATING' status since we just issued 2 | // the call to create it, but I suppose it doesn't hurt to check here. 3 | if nodegroupCreating(&resource{ko}) { 4 | // Setting resource synced condition to false will trigger a requeue of 5 | // the resource. No need to return a requeue error here. 6 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 7 | return &resource{ko}, nil 8 | } 9 | -------------------------------------------------------------------------------- /config/rbac/role-reader.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-eks-reader 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - eks.services.k8s.aws 11 | resources: 12 | - accessentries 13 | - addons 14 | - capabilities 15 | - clusters 16 | - fargateprofiles 17 | - identityproviderconfigs 18 | - nodegroups 19 | - podidentityassociations 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | -------------------------------------------------------------------------------- /apis/v1alpha1/ack-generate-metadata.yaml: -------------------------------------------------------------------------------- 1 | ack_generate_info: 2 | build_date: "2025-12-11T21:18:31Z" 3 | build_hash: 5c8b9050006ef6c7d3a97c279e7b1bc163f20a0a 4 | go_version: go1.25.4 5 | version: v0.56.0-3-g5c8b905 6 | api_directory_checksum: df9ec56e987fdc93ed2e7f55c55cf0bc3372b109 7 | api_version: v1alpha1 8 | aws_sdk_go_version: v1.40.1 9 | generator_config_info: 10 | file_checksum: 814a18c6541a85497ba4ed004d069ff15fa67a82 11 | original_file_name: generator.yaml 12 | last_modification: 13 | reason: API generation 14 | -------------------------------------------------------------------------------- /templates/hooks/addons/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if err := rm.setResourceAdditionalFields(ctx, ko, resp.Addon.PodIdentityAssociations); err != nil { 2 | return nil, err 3 | } 4 | if !addonActive(&resource{ko}) { 5 | // Setting resource synced condition to false will trigger a requeue of 6 | // the resource. No need to return a requeue error here. 7 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 8 | } else { 9 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionTrue, nil, nil) 10 | } -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - common 5 | - bases/eks.services.k8s.aws_accessentries.yaml 6 | - bases/eks.services.k8s.aws_addons.yaml 7 | - bases/eks.services.k8s.aws_capabilities.yaml 8 | - bases/eks.services.k8s.aws_clusters.yaml 9 | - bases/eks.services.k8s.aws_fargateprofiles.yaml 10 | - bases/eks.services.k8s.aws_identityproviderconfigs.yaml 11 | - bases/eks.services.k8s.aws_nodegroups.yaml 12 | - bases/eks.services.k8s.aws_podidentityassociations.yaml 13 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | # namespace: 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | # namePrefix: 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | resources: 16 | - ../crd 17 | - ../rbac 18 | - ../controller 19 | 20 | patchesStrategicMerge: 21 | -------------------------------------------------------------------------------- /templates/hooks/nodegroup/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if ko.Spec.ScalingConfig != nil && ko.Spec.ScalingConfig.DesiredSize != nil { 2 | ko.Status.DesiredSize = ko.Spec.ScalingConfig.DesiredSize 3 | } 4 | 5 | if !nodegroupActive(&resource{ko}) { 6 | // Setting resource synced condition to false will trigger a requeue of 7 | // the resource. No need to return a requeue error here. 8 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 9 | } else { 10 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionTrue, nil, nil) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /go.local.mod: -------------------------------------------------------------------------------- 1 | module github.com/aws-controllers-k8s/eks-controller 2 | 3 | go 1.14 4 | 5 | replace github.com/aws-controllers-k8s/runtime => ../runtime 6 | 7 | require ( 8 | github.com/aws-controllers-k8s/ec2-controller v0.0.10 9 | github.com/aws-controllers-k8s/iam-controller v0.0.8 10 | github.com/aws-controllers-k8s/runtime v0.17.2 11 | github.com/aws/aws-sdk-go v1.42.0 12 | github.com/go-logr/logr v1.2.0 13 | github.com/spf13/pflag v1.0.5 14 | k8s.io/api v0.23.0 15 | k8s.io/apimachinery v0.23.0 16 | k8s.io/client-go v0.23.0 17 | sigs.k8s.io/controller-runtime v0.11.0 18 | ) 19 | -------------------------------------------------------------------------------- /test/e2e/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /templates/hooks/access_entry/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if delta.DifferentAt("Spec.AccessPolicies") { 2 | err := rm.syncAccessPolicies(ctx, desired, latest) 3 | if err != nil { 4 | return nil, err 5 | } 6 | } 7 | if delta.DifferentAt("Spec.Tags") { 8 | err := syncTags( 9 | ctx, rm.sdkapi, rm.metrics, 10 | string(*latest.ko.Status.ACKResourceMetadata.ARN), 11 | aws.ToStringMap(desired.ko.Spec.Tags), aws.ToStringMap(latest.ko.Spec.Tags), 12 | ) 13 | if err != nil { 14 | return nil, err 15 | } 16 | } 17 | if !delta.DifferentExcept("Spec.AccessPolicies", "Spec.Tags"){ 18 | return desired, nil 19 | } -------------------------------------------------------------------------------- /templates/hooks/identity_provider_config/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if resp.IdentityProviderConfig.Oidc != nil { 2 | ko.Spec.Tags = aws.StringMap(resp.IdentityProviderConfig.Oidc.Tags) 3 | } 4 | temp := string(resp.IdentityProviderConfig.Oidc.Status) 5 | ko.Status.Status = &temp 6 | if !identityProviderActive(&resource{ko}) { 7 | // Setting resource synced condition to false will trigger a requeue of 8 | // the resource. No need to return a requeue error here. 9 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 10 | } else { 11 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionTrue, nil, nil) 12 | } 13 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | name: eks-chart 3 | description: A Helm chart for the ACK service controller for Amazon Elastic Kubernetes Service (EKS) 4 | version: 1.11.0 5 | appVersion: 1.11.0 6 | home: https://github.com/aws-controllers-k8s/eks-controller 7 | icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png 8 | sources: 9 | - https://github.com/aws-controllers-k8s/eks-controller 10 | maintainers: 11 | - name: ACK Admins 12 | url: https://github.com/orgs/aws-controllers-k8s/teams/ack-admin 13 | - name: EKS Admins 14 | url: https://github.com/orgs/aws-controllers-k8s/teams/eks-maintainer 15 | keywords: 16 | - aws 17 | - kubernetes 18 | - eks 19 | -------------------------------------------------------------------------------- /helm/templates/service-account.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 7 | app.kubernetes.io/instance: {{ .Release.Name }} 8 | app.kubernetes.io/managed-by: Helm 9 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 10 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 12 | name: {{ include "ack-eks-controller.service-account.name" . }} 13 | namespace: {{ .Release.Namespace }} 14 | annotations: 15 | {{- range $key, $value := .Values.serviceAccount.annotations }} 16 | {{ $key }}: {{ $value | quote }} 17 | {{- end }} 18 | {{- end }} 19 | -------------------------------------------------------------------------------- /pkg/resource/pod_identity_association/hooks.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package pod_identity_association 15 | 16 | import "github.com/aws-controllers-k8s/eks-controller/pkg/tags" 17 | 18 | var syncTags = tags.SyncTags 19 | -------------------------------------------------------------------------------- /pkg/version/version.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package version 17 | 18 | var ( 19 | GitVersion string 20 | GitCommit string 21 | BuildDate string 22 | ) 23 | -------------------------------------------------------------------------------- /templates/hooks/cluster/sdk_read_one_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if r.ko.Spec.ResourcesVPCConfig != nil && r.ko.Spec.ResourcesVPCConfig.SubnetRefs != nil { 2 | ko.Spec.ResourcesVPCConfig.SubnetRefs = r.ko.Spec.ResourcesVPCConfig.SubnetRefs 3 | } 4 | 5 | if r.ko.Spec.ResourcesVPCConfig != nil && r.ko.Spec.ResourcesVPCConfig.SecurityGroupRefs != nil { 6 | ko.Spec.ResourcesVPCConfig.SecurityGroupRefs = r.ko.Spec.ResourcesVPCConfig.SecurityGroupRefs 7 | } 8 | 9 | if !clusterActive(&resource{ko}) { 10 | // Setting resource synced condition to false will trigger a requeue of 11 | // the resource. No need to return a requeue error here. 12 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 13 | } else { 14 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionTrue, nil, nil) 15 | } -------------------------------------------------------------------------------- /templates/hooks/pod_identity_association/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if delta.DifferentAt("Spec.Tags") { 2 | // TODO(a-hilaly) we need to switch to "ONLY" using the ARN from the ackResourceMetadata 3 | // in the future. 4 | resourceARN := "" 5 | if desired.ko.Status.ACKResourceMetadata.ARN != nil { 6 | resourceARN = *latest.ko.Status.AssociationARN 7 | } else if desired.ko.Status.AssociationARN != nil{ 8 | resourceARN = string(*latest.ko.Status.ACKResourceMetadata.ARN) 9 | } 10 | err := syncTags( 11 | ctx, rm.sdkapi, rm.metrics, 12 | resourceARN, 13 | aws.ToStringMap(desired.ko.Spec.Tags), aws.ToStringMap(latest.ko.Spec.Tags), 14 | ) 15 | if err != nil { 16 | return nil, err 17 | } 18 | } 19 | if !delta.DifferentExcept("Spec.Tags"){ 20 | return desired, nil 21 | } -------------------------------------------------------------------------------- /templates/hooks/cluster/sdk_file_end.go.tpl: -------------------------------------------------------------------------------- 1 | {{ $CRD := .CRD }} 2 | {{ $SDKAPI := .SDKAPI }} 3 | 4 | {{/* Find the structure field within the operation */}} 5 | {{- range $fieldName, $field := $CRD.SpecFields -}} 6 | {{- if (or (eq $field.Path "Logging") (eq $field.Path "ResourcesVPCConfig")) }} 7 | 8 | {{- $shapeName := $field.ShapeRef.ShapeName }} 9 | 10 | // new{{ $shapeName }} returns a {{ $shapeName }} object 11 | // with each the field set by the resource's corresponding spec field. 12 | func (rm *resourceManager) new{{ $shapeName }}( 13 | r *resource, 14 | ) *svcsdktypes.{{ $shapeName }} { 15 | res := &svcsdktypes.{{ $shapeName }}{} 16 | 17 | {{ GoCodeSetSDKForStruct $CRD "" "res" $field.ShapeRef "" (printf "r.ko.Spec.%s" $field.Names.Camel) 1 }} 18 | 19 | return res 20 | } 21 | 22 | 23 | {{- end }} 24 | 25 | {{- end }} -------------------------------------------------------------------------------- /helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | {{ .Chart.Name }} has been installed. 2 | This chart deploys "public.ecr.aws/aws-controllers-k8s/eks-controller:1.11.0". 3 | 4 | Check its status by running: 5 | kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/instance={{ .Release.Name }}" 6 | 7 | You are now able to create Amazon Elastic Kubernetes Service (EKS) resources! 8 | 9 | The controller is running in "{{ .Values.installScope }}" mode. 10 | The controller is configured to manage AWS resources in region: "{{ .Values.aws.region }}" 11 | 12 | Visit https://aws-controllers-k8s.github.io/community/reference/ for an API 13 | reference of all the resources that can be created using this controller. 14 | 15 | For more information on the AWS Controllers for Kubernetes (ACK) project, visit: 16 | https://aws-controllers-k8s.github.io/community/ 17 | -------------------------------------------------------------------------------- /templates/hooks/nodegroup/sdk_file_end.go.tpl: -------------------------------------------------------------------------------- 1 | {{ $CRD := .CRD }} 2 | {{ $SDKAPI := .SDKAPI }} 3 | 4 | {{/* Find the structure field within the operation */}} 5 | {{- range $fieldName, $field := $CRD.SpecFields -}} 6 | {{- if (or (eq $field.Path "ScalingConfig") (eq $field.Path "UpdateConfig")) }} 7 | 8 | {{- $shapeName := $field.ShapeRef.ShapeName }} 9 | 10 | // new{{ $shapeName }} returns a {{ $shapeName }} object 11 | // with each the field set by the resource's corresponding spec field. 12 | func (rm *resourceManager) new{{ $shapeName }}( 13 | r *resource, 14 | ) (*svcsdktypes.{{ $shapeName }}, error) { 15 | res := &svcsdktypes.{{ $shapeName }}{} 16 | 17 | {{ GoCodeSetSDKForStruct $CRD "" "res" $field.ShapeRef "" (printf "r.ko.Spec.%s" $field.Names.Camel) 1 }} 18 | 19 | return res, nil 20 | } 21 | 22 | 23 | {{- end }} 24 | 25 | {{- end }} -------------------------------------------------------------------------------- /test/e2e/resources/cluster_automode.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: eks.services.k8s.aws/v1alpha1 2 | kind: Cluster 3 | metadata: 4 | name: $CLUSTER_NAME 5 | spec: 6 | name: $CLUSTER_NAME 7 | version: "$CLUSTER_VERSION" 8 | roleARN: $AUTO_CLUSTER_ROLE 9 | resourcesVPCConfig: 10 | subnetIDs: 11 | - $PUBLIC_SUBNET_1 12 | - $PUBLIC_SUBNET_2 13 | endpointPublicAccess: true 14 | endpointPrivateAccess: true 15 | computeConfig: 16 | enabled: true 17 | nodeRoleARN: $NODEPOOL_ROLE 18 | nodePools: 19 | - system 20 | - general-purpose 21 | kubernetesNetworkConfig: 22 | ipFamily: ipv4 23 | elasticLoadBalancing: 24 | enabled: true 25 | storageConfig: 26 | blockStorage: 27 | enabled: true 28 | accessConfig: 29 | authenticationMode: "API" 30 | bootstrapClusterCreatorAdminPermissions: true 31 | -------------------------------------------------------------------------------- /templates/hooks/cluster/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if desired.ko.Spec.ResourcesVPCConfig.SubnetRefs != nil { 2 | ko.Spec.ResourcesVPCConfig.SubnetRefs = desired.ko.Spec.ResourcesVPCConfig.SubnetRefs 3 | } 4 | 5 | if desired.ko.Spec.ResourcesVPCConfig.SecurityGroupRefs != nil { 6 | ko.Spec.ResourcesVPCConfig.SecurityGroupRefs = desired.ko.Spec.ResourcesVPCConfig.SecurityGroupRefs 7 | } 8 | 9 | // We expect the cluster to be in 'CREATING' status since we just issued 10 | // the call to create it, but I suppose it doesn't hurt to check here. 11 | if clusterCreating(&resource{ko}) { 12 | // Setting resource synced condition to false will trigger a requeue of 13 | // the resource. No need to return a requeue error here. 14 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 15 | return &resource{ko}, nil 16 | } 17 | 18 | -------------------------------------------------------------------------------- /config/rbac/role-writer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-eks-writer 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - eks.services.k8s.aws 11 | resources: 12 | - accessentries 13 | - addons 14 | - capabilities 15 | - clusters 16 | - fargateprofiles 17 | - identityproviderconfigs 18 | - nodegroups 19 | - podidentityassociations 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - eks.services.k8s.aws 30 | resources: 31 | - accessentries 32 | - addons 33 | - capabilities 34 | - clusters 35 | - fargateprofiles 36 | - identityproviderconfigs 37 | - nodegroups 38 | - podidentityassociations 39 | verbs: 40 | - get 41 | - patch 42 | - update 43 | -------------------------------------------------------------------------------- /helm/templates/role-reader.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: {{ include "ack-eks-controller.app.fullname" . }}-reader 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: Helm 12 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 13 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 14 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 15 | rules: 16 | - apiGroups: 17 | - eks.services.k8s.aws 18 | resources: 19 | - accessentries 20 | - addons 21 | - capabilities 22 | - clusters 23 | - fargateprofiles 24 | - identityproviderconfigs 25 | - nodegroups 26 | - podidentityassociations 27 | verbs: 28 | - get 29 | - list 30 | - watch 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash # Use bash syntax 2 | 3 | # Set up variables 4 | GO111MODULE=on 5 | 6 | # Build ldflags 7 | VERSION ?= "v0.0.0" 8 | GITCOMMIT=$(shell git rev-parse HEAD) 9 | BUILDDATE=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') 10 | GO_LDFLAGS=-ldflags "-X main.version=$(VERSION) \ 11 | -X main.buildHash=$(GITCOMMIT) \ 12 | -X main.buildDate=$(BUILDDATE)" 13 | 14 | .PHONY: all test local-test 15 | 16 | all: test 17 | 18 | local-run-controller: ## Run a controller image locally for SERVICE 19 | @go run ./cmd/controller/main.go \ 20 | --aws-region=us-west-2 \ 21 | --enable-development-logging \ 22 | --log-level=debug 23 | 24 | test: ## Run code tests 25 | go test -v ./... 26 | 27 | local-test: ## Run code tests using go.local.mod file 28 | go test -modfile=go.local.mod -v ./... 29 | 30 | help: ## Show this help. 31 | @grep -F -h "##" $(MAKEFILE_LIST) | grep -F -v grep | sed -e 's/\\$$//' \ 32 | | awk -F'[:#]' '{print $$1 = sprintf("%-30s", $$1), $$4}' -------------------------------------------------------------------------------- /templates/hooks/addons/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if addonDeleting(latest) { 2 | msg := "Addon is currently being deleted" 3 | ackcondition.SetSynced(latest, corev1.ConditionFalse, &msg, nil) 4 | return latest, requeueWaitWhileDeleting 5 | } 6 | if !addonActive(latest) { 7 | msg := "Addon is in '" + *latest.ko.Status.Status + "' status" 8 | ackcondition.SetSynced(latest, corev1.ConditionFalse, &msg, nil) 9 | if addonHasTerminalStatus(latest) { 10 | ackcondition.SetTerminal(latest, corev1.ConditionTrue, &msg, nil) 11 | return latest, nil 12 | } 13 | return latest, requeueWaitUntilCanModify(latest) 14 | } 15 | 16 | if delta.DifferentAt("Spec.Tags") { 17 | err := syncTags( 18 | ctx, rm.sdkapi, rm.metrics, 19 | string(*latest.ko.Status.ACKResourceMetadata.ARN), 20 | aws.ToStringMap(desired.ko.Spec.Tags), aws.ToStringMap(latest.ko.Spec.Tags), 21 | ) 22 | if err != nil { 23 | return nil, err 24 | } 25 | } 26 | if !delta.DifferentExcept("Spec.Tags"){ 27 | return desired, nil 28 | } -------------------------------------------------------------------------------- /test/e2e/service_cleanup.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | """Cleans up the resources created by the bootstrapping process. 15 | """ 16 | 17 | import logging 18 | 19 | from acktest.bootstrapping import Resources 20 | 21 | from e2e import bootstrap_directory 22 | 23 | def service_cleanup(): 24 | logging.getLogger().setLevel(logging.INFO) 25 | 26 | resources = Resources.deserialize(bootstrap_directory) 27 | resources.cleanup() 28 | 29 | if __name__ == "__main__": 30 | service_cleanup() -------------------------------------------------------------------------------- /helm/templates/leader-election-role.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.leaderElection.enabled }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: {{ include "ack-eks-controller.app.fullname" . }}-leaderelection 6 | {{ if .Values.leaderElection.namespace }} 7 | namespace: {{ .Values.leaderElection.namespace }} 8 | {{ else }} 9 | namespace: {{ .Release.Namespace }} 10 | {{ end }} 11 | labels: 12 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 13 | app.kubernetes.io/instance: {{ .Release.Name }} 14 | app.kubernetes.io/managed-by: Helm 15 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 16 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 18 | rules: 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch{{- end }} 38 | -------------------------------------------------------------------------------- /helm/templates/leader-election-role-binding.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.leaderElection.enabled }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: {{ include "ack-eks-controller.app.fullname" . }}-leaderelection 6 | {{ if .Values.leaderElection.namespace }} 7 | namespace: {{ .Values.leaderElection.namespace }} 8 | {{ else }} 9 | namespace: {{ .Release.Namespace }} 10 | {{ end }} 11 | labels: 12 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 13 | app.kubernetes.io/instance: {{ .Release.Name }} 14 | app.kubernetes.io/managed-by: Helm 15 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 16 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 18 | roleRef: 19 | apiGroup: rbac.authorization.k8s.io 20 | kind: Role 21 | name: {{ include "ack-eks-controller.app.fullname" . }}-leaderelection 22 | subjects: 23 | - kind: ServiceAccount 24 | name: {{ include "ack-eks-controller.service-account.name" . }} 25 | namespace: {{ .Release.Namespace }}{{- end }} 26 | -------------------------------------------------------------------------------- /helm/templates/metrics-service.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.metrics.service.create }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ .Chart.Name | trimSuffix "-chart" | trunc 44 }}-controller-metrics 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: Helm 11 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 12 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 13 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 14 | spec: 15 | selector: 16 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 17 | app.kubernetes.io/instance: {{ .Release.Name }} 18 | app.kubernetes.io/managed-by: Helm 19 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 20 | {{- range $key, $value := .Values.deployment.labels }} 21 | {{ $key }}: {{ $value | quote }} 22 | {{- end }} 23 | type: {{ .Values.metrics.service.type }} 24 | ports: 25 | - name: metricsport 26 | port: 8080 27 | targetPort: http 28 | protocol: TCP 29 | {{- end }} 30 | -------------------------------------------------------------------------------- /apis/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package v1alpha1 17 | 18 | import ( 19 | "k8s.io/apimachinery/pkg/runtime/schema" 20 | "sigs.k8s.io/controller-runtime/pkg/scheme" 21 | ) 22 | 23 | var ( 24 | // GroupVersion is the API Group Version used to register the objects 25 | GroupVersion = schema.GroupVersion{Group: "eks.services.k8s.aws", Version: "v1alpha1"} 26 | 27 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 28 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 29 | 30 | // AddToScheme adds the types in this group-version to the given scheme. 31 | AddToScheme = SchemeBuilder.AddToScheme 32 | ) 33 | -------------------------------------------------------------------------------- /helm/templates/role-writer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: {{ include "ack-eks-controller.app.fullname" . }}-writer 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: Helm 12 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 13 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 14 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 15 | rules: 16 | - apiGroups: 17 | - eks.services.k8s.aws 18 | resources: 19 | - accessentries 20 | - addons 21 | - capabilities 22 | - clusters 23 | - fargateprofiles 24 | - identityproviderconfigs 25 | - nodegroups 26 | - podidentityassociations 27 | verbs: 28 | - create 29 | - delete 30 | - get 31 | - list 32 | - patch 33 | - update 34 | - watch 35 | - apiGroups: 36 | - eks.services.k8s.aws 37 | resources: 38 | - accessentries 39 | - addons 40 | - capabilities 41 | - clusters 42 | - fargateprofiles 43 | - identityproviderconfigs 44 | - nodegroups 45 | - podidentityassociations 46 | verbs: 47 | - get 48 | - patch 49 | - update 50 | -------------------------------------------------------------------------------- /test/e2e/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | import pytest 15 | from typing import Dict, Any 16 | from pathlib import Path 17 | 18 | from acktest.resources import load_resource_file 19 | 20 | SERVICE_NAME = "eks" 21 | CRD_GROUP = "eks.services.k8s.aws" 22 | CRD_VERSION = "v1alpha1" 23 | 24 | # PyTest marker for the current service 25 | service_marker = pytest.mark.service(arg=SERVICE_NAME) 26 | 27 | bootstrap_directory = Path(__file__).parent 28 | resource_directory = Path(__file__).parent / "resources" 29 | def load_eks_resource(resource_name: str, additional_replacements: Dict[str, Any] = {}): 30 | """ Overrides the default `load_resource_file` to access the specific resources 31 | directory for the current service. 32 | """ 33 | return load_resource_file(resource_directory, resource_name, additional_replacements=additional_replacements) -------------------------------------------------------------------------------- /helm/templates/caches-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "ack-eks-controller.app.fullname" . }}-namespaces-cache 5 | labels: 6 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 7 | app.kubernetes.io/instance: {{ .Release.Name }} 8 | app.kubernetes.io/managed-by: Helm 9 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 10 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 12 | rules: 13 | - apiGroups: 14 | - "" 15 | resources: 16 | - namespaces 17 | verbs: 18 | - get 19 | - list 20 | - watch 21 | --- 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | kind: Role 24 | metadata: 25 | name: {{ include "ack-eks-controller.app.fullname" . }}-configmaps-cache 26 | namespace: {{ .Release.Namespace }} 27 | labels: 28 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 29 | app.kubernetes.io/instance: {{ .Release.Name }} 30 | app.kubernetes.io/managed-by: Helm 31 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 32 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 33 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 34 | rules: 35 | - apiGroups: 36 | - "" 37 | resources: 38 | - configmaps 39 | verbs: 40 | - get 41 | - list 42 | - watch -------------------------------------------------------------------------------- /olm/olmconfig.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | annotations: 3 | capabilityLevel: Basic Install 4 | shortDescription: AWS EKS controller is a service controller for managing EKS resources 5 | in Kubernetes 6 | displayName: AWS Controllers for Kubernetes - Amazon EKS 7 | description: |- 8 | Manage Elastic Kubernetes Service (EKS) resources in AWS from within your Kubernetes cluster. 9 | 10 | 11 | **About Amazon EKS** 12 | 13 | 14 | Amazon Elastic Kubernetes Service (Amazon EKS) is a managed service that you can use to run Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane or nodes. Kubernetes is an open-source system for automating the deployment, scaling, and management of containerized applications. 15 | 16 | 17 | **About the AWS Controllers for Kubernetes** 18 | 19 | 20 | This controller is a component of the [AWS Controller for Kubernetes](https://github.com/aws/aws-controllers-k8s) 21 | project. 22 | 23 | 24 | **Pre-Installation Steps** 25 | 26 | 27 | Please follow the following link: [Red Hat OpenShift](https://aws-controllers-k8s.github.io/community/docs/user-docs/openshift/) 28 | samples: 29 | - kind: Addon 30 | spec: '{}' 31 | - kind: Cluster 32 | spec: '{}' 33 | - kind: FargateProfile 34 | spec: '{}' 35 | - kind: Nodegroup 36 | spec: '{}' 37 | maintainers: 38 | - name: "eks maintainer team" 39 | email: "ack-maintainers@amazon.com" 40 | links: 41 | - name: Amazon EKS Developer Resources 42 | url: https://aws.amazon.com/eks/getting-started/ 43 | -------------------------------------------------------------------------------- /test/e2e/bootstrap_resources.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | """Declares the structure of the bootstrapped resources and provides a loader 15 | for them. 16 | """ 17 | 18 | from dataclasses import dataclass 19 | from acktest.bootstrapping import Resources 20 | from acktest.bootstrapping.iam import Role 21 | from acktest.bootstrapping.vpc import VPC 22 | from acktest.bootstrapping.eks import Cluster 23 | from e2e import bootstrap_directory 24 | 25 | @dataclass 26 | class BootstrapResources(Resources): 27 | AdoptionCluster: Cluster 28 | ClusterVPC: VPC 29 | ClusterRole: Role 30 | AutoClusterRole: Role 31 | FargatePodRole: Role 32 | NodegroupRole: Role 33 | NodepoolRole: Role 34 | CapabilityRole: Role 35 | 36 | PodIdentityAssociationRole: Role 37 | AccessEntryPrincipalRole: Role 38 | 39 | _bootstrap_resources = None 40 | 41 | def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.pkl") -> BootstrapResources: 42 | global _bootstrap_resources 43 | if _bootstrap_resources is None: 44 | _bootstrap_resources = BootstrapResources.deserialize(bootstrap_directory, bootstrap_file_name=bootstrap_file_name) 45 | return _bootstrap_resources 46 | -------------------------------------------------------------------------------- /helm/templates/cluster-role-controller.yaml: -------------------------------------------------------------------------------- 1 | {{ $labels := .Values.role.labels }} 2 | {{ $appVersion := .Chart.AppVersion | quote }} 3 | {{ $rbacRules := include "ack-eks-controller.rbac-rules" . }} 4 | {{ $fullname := include "ack-eks-controller.app.fullname" . }} 5 | {{ $chartVersion := include "ack-eks-controller.chart.name-version" . }} 6 | {{ if eq .Values.installScope "cluster" }} 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | kind: ClusterRole 9 | metadata: 10 | name: {{ include "ack-eks-controller.app.fullname" . }} 11 | labels: 12 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 13 | app.kubernetes.io/instance: {{ .Release.Name }} 14 | app.kubernetes.io/managed-by: Helm 15 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 16 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 18 | {{- range $key, $value := $labels }} 19 | {{ $key }}: {{ $value | quote }} 20 | {{- end }} 21 | {{$rbacRules }} 22 | {{ else if eq .Values.installScope "namespace" }} 23 | {{ $wn := include "ack-eks-controller.watch-namespace" . }} 24 | {{ $namespaces := split "," $wn }} 25 | {{ range $namespaces }} 26 | --- 27 | apiVersion: rbac.authorization.k8s.io/v1 28 | kind: Role 29 | metadata: 30 | name: {{ $fullname }}-{{ . }} 31 | namespace: {{ . }} 32 | labels: 33 | app.kubernetes.io/name: {{ $fullname }} 34 | app.kubernetes.io/instance: {{ $.Release.Name }} 35 | app.kubernetes.io/managed-by: Helm 36 | app.kubernetes.io/version: {{ $appVersion }} 37 | k8s-app: {{ $fullname }} 38 | helm.sh/chart: {{ $chartVersion }} 39 | {{- range $key, $value := $labels }} 40 | {{ $key }}: {{ $value | quote }} 41 | {{- end }} 42 | {{ $rbacRules }} 43 | {{ end }} 44 | {{ end }} -------------------------------------------------------------------------------- /helm/templates/caches-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: {{ include "ack-eks-controller.app.fullname" . }}-namespaces-cache 5 | labels: 6 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 7 | app.kubernetes.io/instance: {{ .Release.Name }} 8 | app.kubernetes.io/managed-by: Helm 9 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 10 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 12 | roleRef: 13 | kind: ClusterRole 14 | apiGroup: rbac.authorization.k8s.io 15 | name: {{ include "ack-eks-controller.app.fullname" . }}-namespaces-cache 16 | subjects: 17 | - kind: ServiceAccount 18 | name: {{ include "ack-eks-controller.service-account.name" . }} 19 | namespace: {{ .Release.Namespace }} 20 | --- 21 | apiVersion: rbac.authorization.k8s.io/v1 22 | kind: RoleBinding 23 | metadata: 24 | name: {{ include "ack-eks-controller.app.fullname" . }}-configmaps-cache 25 | namespace: {{ .Release.Namespace }} 26 | labels: 27 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 28 | app.kubernetes.io/instance: {{ .Release.Name }} 29 | app.kubernetes.io/managed-by: Helm 30 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 31 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 32 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 33 | roleRef: 34 | kind: Role 35 | apiGroup: rbac.authorization.k8s.io 36 | name: {{ include "ack-eks-controller.app.fullname" . }}-configmaps-cache 37 | subjects: 38 | - kind: ServiceAccount 39 | name: {{ include "ack-eks-controller.service-account.name" . }} 40 | namespace: {{ .Release.Namespace }} 41 | -------------------------------------------------------------------------------- /test/e2e/replacement_values.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | """Stores the values used by each of the integration tests for replacing the 14 | EKS-specific test variables. 15 | """ 16 | 17 | from e2e.bootstrap_resources import get_bootstrap_resources 18 | 19 | 20 | REPLACEMENT_VALUES = { 21 | "CLUSTER_ROLE": get_bootstrap_resources().ClusterRole.arn, 22 | "AUTO_CLUSTER_ROLE": get_bootstrap_resources().AutoClusterRole.arn, 23 | "FARGATE_POD_ROLE": get_bootstrap_resources().FargatePodRole.arn, 24 | "NODEGROUP_ROLE": get_bootstrap_resources().NodegroupRole.arn, 25 | "POD_IDENTITY_ASSOCIATION_ROLE": get_bootstrap_resources().PodIdentityAssociationRole.arn, 26 | "NODEPOOL_ROLE": get_bootstrap_resources().NodepoolRole.arn, 27 | "CAPABILITY_ROLE_ARN": get_bootstrap_resources().CapabilityRole.arn, 28 | 29 | "PUBLIC_SUBNET_1": get_bootstrap_resources().ClusterVPC.public_subnets.subnet_ids[0], 30 | "PUBLIC_SUBNET_2": get_bootstrap_resources().ClusterVPC.public_subnets.subnet_ids[1], 31 | "PRIVATE_SUBNET_1": get_bootstrap_resources().ClusterVPC.private_subnets.subnet_ids[0], 32 | "PRIVATE_SUBNET_2": get_bootstrap_resources().ClusterVPC.private_subnets.subnet_ids[1], 33 | 34 | "AUTHENTICATION_MODE": "API_AND_CONFIG_MAP" 35 | } -------------------------------------------------------------------------------- /test/e2e/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | import os 15 | import boto3 16 | import pytest 17 | 18 | from acktest import k8s 19 | 20 | 21 | def pytest_addoption(parser): 22 | parser.addoption("--runslow", action="store_true", default=False, help="run slow tests") 23 | 24 | 25 | def pytest_configure(config): 26 | config.addinivalue_line( 27 | "markers", "canary: mark test to also run in canary tests" 28 | ) 29 | config.addinivalue_line( 30 | "markers", "service(arg): mark test associated with a given service" 31 | ) 32 | config.addinivalue_line( 33 | "markers", "slow: mark test as slow to run" 34 | ) 35 | config.addinivalue_line( 36 | "markers", "resource_data: mark test with data to use when creating fixture" 37 | ) 38 | 39 | def pytest_collection_modifyitems(config, items): 40 | if config.getoption("--runslow"): 41 | return 42 | skip_slow = pytest.mark.skip(reason="need --runslow option to run") 43 | for item in items: 44 | if "slow" in item.keywords: 45 | item.add_marker(skip_slow) 46 | 47 | # Provide a k8s client to interact with the integration test cluster 48 | @pytest.fixture(scope='class') 49 | def k8s_client(): 50 | return k8s._get_k8s_api_client() 51 | 52 | @pytest.fixture(scope='module') 53 | def eks_client(): 54 | return boto3.client('eks') -------------------------------------------------------------------------------- /pkg/resource/addon/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package addon 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/cluster/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package cluster 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/nodegroup/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package nodegroup 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/capability/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package capability 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/access_entry/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package access_entry 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/fargate_profile/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package fargate_profile 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/identity_provider_config/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package identity_provider_config 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /pkg/resource/pod_identity_association/identifiers.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package pod_identity_association 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | ) 21 | 22 | // resourceIdentifiers implements the 23 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 24 | type resourceIdentifiers struct { 25 | meta *ackv1alpha1.ResourceMetadata 26 | } 27 | 28 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 29 | // this means the resource has not yet been created in the backend AWS 30 | // service. 31 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 32 | if ri.meta != nil { 33 | return ri.meta.ARN 34 | } 35 | return nil 36 | } 37 | 38 | // OwnerAccountID returns the AWS account identifier in which the 39 | // backend AWS resource resides, or nil if this information is not known 40 | // for the resource 41 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 42 | if ri.meta != nil { 43 | return ri.meta.OwnerAccountID 44 | } 45 | return nil 46 | } 47 | 48 | // Region returns the AWS region in which the resource exists, or 49 | // nil if this information is not known. 50 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 51 | if ri.meta != nil { 52 | return ri.meta.Region 53 | } 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /GOVERNANCE.md: -------------------------------------------------------------------------------- 1 | # Project governance 2 | 3 | This document lays out the guidelines under which the AWS Controllers for Kubernetes (ACK) project will be governed. 4 | The goal is to make sure that the roles and responsibilities are well defined and clarify on how decisions are made. 5 | 6 | ## Roles 7 | 8 | In the context of ACK, we consider the following roles: 9 | 10 | * __Users__ ... everyone using ACK, typically willing to provide feedback on ACK by proposing features and/or filing issues. 11 | * __Contributors__ ... everyone contributing code, documentation, examples, testing infra, and participating in feature proposals as well as design discussions. Code contributions will require a Developer Certificate of Origin (DCO). 12 | * __Maintainers__ ... are responsible for engaging with and assisting contributors to iterate on the contributions until it reaches acceptable quality. Maintainers can decide whether the contributions can be accepted into the project or rejected. Any active contributor meeting the project quality can be made a Maintainer by the Advisory Board. 13 | * __Advisory Board__ ... is responsible for defining the guidelines and processes that the project operates under. 14 | 15 | The initial members of the Advisory Board are `@jaypipes` and `@mhausenblas`. 16 | 17 | 18 | ## Communication 19 | 20 | The primary mechanism for communication will be via the `#provider-aws` channel on the Kubernetes Slack community. 21 | All features and bug fixes will be tracked as issues in GitHub. All decisions will be documented in GitHub issues. 22 | 23 | In the future, we may consider using a public mailing list, which can be better archived. 24 | 25 | ## Roadmap Planning 26 | 27 | Maintainers will share roadmap and release versions as milestones in GitHub. 28 | 29 | ## Release Management 30 | 31 | The Advisory Board will propose a release management proposal via a GitHub issue and resolve it there. 32 | 33 | ## Other relevant governance resources 34 | 35 | * The ACK [Contributing Guidelines](CONTRIBUTING.md) 36 | * Our [Code of Conduct](CODE_OF_CONDUCT.md) 37 | -------------------------------------------------------------------------------- /pkg/resource/registry.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package resource 17 | 18 | import ( 19 | ackrt "github.com/aws-controllers-k8s/runtime/pkg/runtime" 20 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 21 | ) 22 | 23 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=iamroleselectors,verbs=get;list;watch;create;update;patch;delete 24 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=iamroleselectors/status,verbs=get;update;patch 25 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=fieldexports,verbs=get;list;watch;create;update;patch;delete 26 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=fieldexports/status,verbs=get;update;patch 27 | // +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch 28 | // +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;patch 29 | // +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;patch 30 | 31 | var ( 32 | reg = ackrt.NewRegistry() 33 | ) 34 | 35 | // GetManagerFactories returns a slice of resource manager factories that are 36 | // registered with this package 37 | func GetManagerFactories() []acktypes.AWSResourceManagerFactory { 38 | return reg.GetResourceManagerFactories() 39 | } 40 | 41 | // RegisterManagerFactory registers a resource manager factory with the 42 | // package's registry 43 | func RegisterManagerFactory(f acktypes.AWSResourceManagerFactory) { 44 | reg.RegisterResourceManagerFactory(f) 45 | } 46 | -------------------------------------------------------------------------------- /helm/templates/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | {{ if eq .Values.installScope "cluster" }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: {{ include "ack-eks-controller.app.fullname" . }}-rolebinding 6 | labels: 7 | app.kubernetes.io/name: {{ include "ack-eks-controller.app.name" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: Helm 10 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 11 | k8s-app: {{ include "ack-eks-controller.app.name" . }} 12 | helm.sh/chart: {{ include "ack-eks-controller.chart.name-version" . }} 13 | roleRef: 14 | kind: ClusterRole 15 | apiGroup: rbac.authorization.k8s.io 16 | name: {{ include "ack-eks-controller.app.fullname" . }} 17 | subjects: 18 | - kind: ServiceAccount 19 | name: {{ include "ack-eks-controller.service-account.name" . }} 20 | namespace: {{ .Release.Namespace }} 21 | {{ else if eq .Values.installScope "namespace" }} 22 | {{ $wn := include "ack-eks-controller.watch-namespace" . }} 23 | {{ $namespaces := split "," $wn }} 24 | {{ $fullname := include "ack-eks-controller.app.fullname" . }} 25 | {{ $releaseNamespace := .Release.Namespace }} 26 | {{ $serviceAccountName := include "ack-eks-controller.service-account.name" . }} 27 | {{ $chartVersion := include "ack-eks-controller.chart.name-version" . }} 28 | {{ $appVersion := .Chart.AppVersion | quote }} 29 | {{ range $namespaces }} 30 | --- 31 | apiVersion: rbac.authorization.k8s.io/v1 32 | kind: RoleBinding 33 | metadata: 34 | name: {{ $fullname }}-{{ . }} 35 | namespace: {{ . }} 36 | labels: 37 | app.kubernetes.io/name: {{ $fullname }} 38 | app.kubernetes.io/instance: {{ $.Release.Name }} 39 | app.kubernetes.io/managed-by: Helm 40 | app.kubernetes.io/version: {{ $appVersion }} 41 | k8s-app: {{ $fullname }} 42 | helm.sh/chart: {{ $chartVersion }} 43 | roleRef: 44 | kind: Role 45 | apiGroup: rbac.authorization.k8s.io 46 | name: {{ $fullname }}-{{ . }} 47 | subjects: 48 | - kind: ServiceAccount 49 | name: {{ $serviceAccountName }} 50 | namespace: {{ $releaseNamespace }} 51 | {{ end }} 52 | {{ end }} -------------------------------------------------------------------------------- /config/rbac/cluster-role-controller.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: ack-eks-controller 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | - secrets 12 | verbs: 13 | - get 14 | - list 15 | - patch 16 | - watch 17 | - apiGroups: 18 | - "" 19 | resources: 20 | - namespaces 21 | verbs: 22 | - get 23 | - list 24 | - watch 25 | - apiGroups: 26 | - ec2.services.k8s.aws 27 | resources: 28 | - securitygroups 29 | - securitygroups/status 30 | - subnets 31 | - subnets/status 32 | verbs: 33 | - get 34 | - list 35 | - apiGroups: 36 | - eks.services.k8s.aws 37 | resources: 38 | - accessentries 39 | - addons 40 | - capabilities 41 | - clusters 42 | - fargateprofiles 43 | - identityproviderconfigs 44 | - nodegroups 45 | - podidentityassociations 46 | verbs: 47 | - create 48 | - delete 49 | - get 50 | - list 51 | - patch 52 | - update 53 | - watch 54 | - apiGroups: 55 | - eks.services.k8s.aws 56 | resources: 57 | - accessentries/status 58 | - addons/status 59 | - capabilities/status 60 | - clusters/status 61 | - fargateprofiles/status 62 | - identityproviderconfigs/status 63 | - nodegroups/status 64 | - podidentityassociations/status 65 | verbs: 66 | - get 67 | - patch 68 | - update 69 | - apiGroups: 70 | - iam.services.k8s.aws 71 | resources: 72 | - roles 73 | - roles/status 74 | verbs: 75 | - get 76 | - list 77 | - apiGroups: 78 | - kms.services.k8s.aws 79 | resources: 80 | - keys 81 | - keys/status 82 | verbs: 83 | - get 84 | - list 85 | - apiGroups: 86 | - services.k8s.aws 87 | resources: 88 | - fieldexports 89 | - iamroleselectors 90 | verbs: 91 | - create 92 | - delete 93 | - get 94 | - list 95 | - patch 96 | - update 97 | - watch 98 | - apiGroups: 99 | - services.k8s.aws 100 | resources: 101 | - fieldexports/status 102 | - iamroleselectors/status 103 | verbs: 104 | - get 105 | - patch 106 | - update 107 | -------------------------------------------------------------------------------- /pkg/resource/capability/references.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package capability 17 | 18 | import ( 19 | "context" 20 | 21 | "sigs.k8s.io/controller-runtime/pkg/client" 22 | 23 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 24 | 25 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 26 | ) 27 | 28 | // ClearResolvedReferences removes any reference values that were made 29 | // concrete in the spec. It returns a copy of the input AWSResource which 30 | // contains the original *Ref values, but none of their respective concrete 31 | // values. 32 | func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) acktypes.AWSResource { 33 | ko := rm.concreteResource(res).ko.DeepCopy() 34 | 35 | return &resource{ko} 36 | } 37 | 38 | // ResolveReferences finds if there are any Reference field(s) present 39 | // inside AWSResource passed in the parameter and attempts to resolve those 40 | // reference field(s) into their respective target field(s). It returns a 41 | // copy of the input AWSResource with resolved reference(s), a boolean which 42 | // is set to true if the resource contains any references (regardless of if 43 | // they are resolved successfully) and an error if the passed AWSResource's 44 | // reference field(s) could not be resolved. 45 | func (rm *resourceManager) ResolveReferences( 46 | ctx context.Context, 47 | apiReader client.Reader, 48 | res acktypes.AWSResource, 49 | ) (acktypes.AWSResource, bool, error) { 50 | return res, false, nil 51 | } 52 | 53 | // validateReferenceFields validates the reference field and corresponding 54 | // identifier field. 55 | func validateReferenceFields(ko *svcapitypes.Capability) error { 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACK service controller for Amazon Elastic Kubernetes Service (EKS) 2 | 3 | This repository contains source code for the AWS Controllers for Kubernetes 4 | (ACK) service controller for Amazon EKS. 5 | 6 | Please [log issues][ack-issues] and feedback on the main AWS Controllers for 7 | Kubernetes Github project. 8 | 9 | [ack-issues]: https://github.com/aws-controllers-k8s/community/issues 10 | 11 | ## Getting started 12 | 13 | To install the `eks-controller` on your cluster, follow the the 14 | [installation][ack-install] instructions. 15 | 16 | Currently, the `eks-controller` is GA and supports the following resources: 17 | - `Cluster` 18 | - `Nodegroup` 19 | - `FargateProfile` 20 | - `Addon` 21 | - `PodIdentityAssociation` 22 | - `AccessEntry` 23 | 24 | A detailed list of the resources supported specifications can be found in the 25 | [references][ack-references] section. 26 | 27 | ## Annotations 28 | 29 | For some resources, the `eks-controller` supports annotations to customize the 30 | behavior of the controller. The following annotations are supported: 31 | 32 | - **Nodegroup** 33 | - `eks.services.k8s.aws/desired-size-managed-by`: used to control whether the 34 | controller should manage the desiredSize of the Nodegroup `spec.ScalingConfig.DesiredSize`. 35 | It supports the following values: 36 | - `ack-eks-controller`: If set, the controller will be responsible for 37 | managing the desired size of the nodegroup. 38 | - `external-autoscaler`: If set, will ignore any changes to the 39 | `spec.ScalingConfig.DesiredSize` and will not manage the desired size 40 | of the nodegroup. 41 | 42 | If not set, the controller will default to `ack-eks-controller`. 43 | 44 | - `eks.services.k8s.aws/force-update-version`: used to force the version 45 | update of the nodegroup. If set to `true`, and the controller detects a 46 | a change in the nodegroup, it will set the `force` attribute to `true` 47 | in the `UpdateNodeGroupConfig` API call. 48 | 49 | ## Contributing 50 | 51 | We welcome community contributions and pull requests. 52 | 53 | See our [contribution guide](/CONTRIBUTING.md) for more information on how to 54 | report issues, set up a development environment, and submit code. 55 | 56 | We adhere to the [Amazon Open Source Code of Conduct][coc]. 57 | 58 | You can also learn more about our [Governance](/GOVERNANCE.md) structure. 59 | 60 | [coc]: https://aws.github.io/code-of-conduct 61 | 62 | ## License 63 | 64 | This project is [licensed](/LICENSE) under the Apache-2.0 License. 65 | 66 | [ack-references]:https://aws-controllers-k8s.github.io/community/reference 67 | [ack-install]:https://aws-controllers-k8s.github.io/community/docs/user-docs/install/ -------------------------------------------------------------------------------- /pkg/resource/identity_provider_config/hooks.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package identity_provider_config 15 | 16 | import ( 17 | "context" 18 | 19 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 20 | ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log" 21 | ) 22 | 23 | // Taken from the list of nodegroup statuses on the boto3 documentation 24 | // https://https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/eks/client/describe_identity_provider_config.html#describe-identity-provider-config 25 | const ( 26 | StatusCreating = "CREATING" 27 | StatusActive = "ACTIVE" 28 | StatusDeleting = "DELETING" 29 | 30 | IdentityProviderConfigType = "oidc" 31 | ) 32 | 33 | // customCheckRequiredFieldsMissing returns true if there are any fields 34 | // for the ReadOne Input shape that are required but not present in the 35 | // resource's Spec or Status 36 | func (rm *resourceManager) customCheckRequiredFieldsMissing( 37 | r *resource, 38 | ) bool { 39 | if r.ko.Spec.ClusterName == nil || r.ko.Spec.OIDC.IdentityProviderConfigName == nil { 40 | return true 41 | } 42 | return false 43 | } 44 | 45 | // identityProviderActive returns true if the supplied cluster is in an active status 46 | func identityProviderActive(r *resource) bool { 47 | if r.ko.Status.Status == nil { 48 | return false 49 | } 50 | cs := *r.ko.Status.Status 51 | return cs == StatusActive 52 | } 53 | 54 | // identityProviderCreating returns true if the supplied cluster is in the process of 55 | // being created 56 | func identityProviderCreating(r *resource) bool { 57 | if r.ko.Status.Status == nil { 58 | return false 59 | } 60 | cs := *r.ko.Status.Status 61 | return cs == StatusCreating 62 | } 63 | 64 | // identityProviderDeleting returns true if the supplied cluster is in the process of 65 | // being deleted 66 | func identityProviderDeleting(r *resource) bool { 67 | if r.ko.Status.Status == nil { 68 | return false 69 | } 70 | cs := *r.ko.Status.Status 71 | return cs == StatusDeleting 72 | } 73 | 74 | func (rm *resourceManager) customUpdate( 75 | ctx context.Context, 76 | desired *resource, 77 | latest *resource, 78 | delta *ackcompare.Delta, 79 | ) (updated *resource, err error) { 80 | rlog := ackrtlog.FromContext(ctx) 81 | exit := rlog.Trace("rm.customUpdate") 82 | defer exit(err) 83 | 84 | return nil, nil 85 | } 86 | -------------------------------------------------------------------------------- /pkg/resource/fargate_profile/hook.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package fargate_profile 15 | 16 | import ( 17 | "context" 18 | "fmt" 19 | 20 | corev1 "k8s.io/api/core/v1" 21 | 22 | "github.com/aws-controllers-k8s/eks-controller/pkg/tags" 23 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 24 | ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition" 25 | ackrequeue "github.com/aws-controllers-k8s/runtime/pkg/requeue" 26 | ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log" 27 | "github.com/aws/aws-sdk-go-v2/aws" 28 | svcsdk "github.com/aws/aws-sdk-go/service/eks" 29 | ) 30 | 31 | var ( 32 | UnableToUpdateError = "Changes to FargateProfile resources are not" + 33 | " currently possible. To update the resource, delete and re-create it" 34 | ) 35 | 36 | var ( 37 | requeueWaitWhileDeleting = ackrequeue.NeededAfter( 38 | fmt.Errorf("profile is in '%s' state, cannot be modified or deleted", svcsdk.FargateProfileStatusDeleting), 39 | ackrequeue.DefaultRequeueAfterDuration, 40 | ) 41 | ) 42 | 43 | // profileDeleting returns true if the supplied EKS FargateProfile is in the 44 | // `Deleting` status 45 | func profileDeleting(r *resource) bool { 46 | if r.ko.Status.Status == nil { 47 | return false 48 | } 49 | ps := *r.ko.Status.Status 50 | return ps == svcsdk.FargateProfileStatusDeleting 51 | } 52 | 53 | // customPreCompare ensures that default values of nil-able types are 54 | // appropriately replaced with empty maps or structs depending on the default 55 | // output of the SDK. 56 | func customPreCompare( 57 | a *resource, 58 | b *resource, 59 | ) { 60 | if a.ko.Spec.Tags == nil && b.ko.Spec.Tags != nil { 61 | a.ko.Spec.Tags = map[string]*string{} 62 | } else if a.ko.Spec.Tags != nil && b.ko.Spec.Tags == nil { 63 | b.ko.Spec.Tags = map[string]*string{} 64 | } 65 | } 66 | 67 | func (rm *resourceManager) customUpdate( 68 | ctx context.Context, 69 | desired *resource, 70 | latest *resource, 71 | delta *ackcompare.Delta, 72 | ) (updated *resource, err error) { 73 | rlog := ackrtlog.FromContext(ctx) 74 | exit := rlog.Trace("rm.customUpdate") 75 | defer exit(err) 76 | 77 | if delta.DifferentAt("Spec.Tags") { 78 | 79 | if err := tags.SyncTags( 80 | ctx, rm.sdkapi, rm.metrics, 81 | string(*latest.ko.Status.ACKResourceMetadata.ARN), 82 | aws.ToStringMap(desired.ko.Spec.Tags), aws.ToStringMap(latest.ko.Spec.Tags), 83 | ); err != nil { 84 | return nil, err 85 | } 86 | return desired, nil 87 | } 88 | 89 | // Never allow any changes 90 | updated = &resource{ko: desired.ko.DeepCopy()} 91 | ackcondition.SetSynced(updated, corev1.ConditionFalse, &UnableToUpdateError, nil) 92 | return updated, nil 93 | } 94 | -------------------------------------------------------------------------------- /helm/crds/services.k8s.aws_iamroleselectors.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.19.0 7 | name: iamroleselectors.services.k8s.aws 8 | spec: 9 | group: services.k8s.aws 10 | names: 11 | kind: IAMRoleSelector 12 | listKind: IAMRoleSelectorList 13 | plural: iamroleselectors 14 | singular: iamroleselector 15 | scope: Cluster 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: IAMRoleSelector is the schema for the IAMRoleSelector API. 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | properties: 41 | arn: 42 | type: string 43 | x-kubernetes-validations: 44 | - message: Value is immutable once set 45 | rule: self == oldSelf 46 | namespaceSelector: 47 | description: IAMRoleSelectorSpec defines the desired state of IAMRoleSelector 48 | properties: 49 | labelSelector: 50 | description: LabelSelector is a label query over a set of resources. 51 | properties: 52 | matchLabels: 53 | additionalProperties: 54 | type: string 55 | type: object 56 | required: 57 | - matchLabels 58 | type: object 59 | names: 60 | items: 61 | type: string 62 | type: array 63 | required: 64 | - names 65 | type: object 66 | resourceTypeSelector: 67 | items: 68 | properties: 69 | group: 70 | type: string 71 | kind: 72 | type: string 73 | version: 74 | type: string 75 | required: 76 | - group 77 | - kind 78 | - version 79 | type: object 80 | type: array 81 | required: 82 | - arn 83 | type: object 84 | status: 85 | type: object 86 | type: object 87 | served: true 88 | storage: true 89 | subresources: 90 | status: {} 91 | -------------------------------------------------------------------------------- /config/crd/common/bases/services.k8s.aws_iamroleselectors.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.19.0 7 | name: iamroleselectors.services.k8s.aws 8 | spec: 9 | group: services.k8s.aws 10 | names: 11 | kind: IAMRoleSelector 12 | listKind: IAMRoleSelectorList 13 | plural: iamroleselectors 14 | singular: iamroleselector 15 | scope: Cluster 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: IAMRoleSelector is the schema for the IAMRoleSelector API. 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | properties: 41 | arn: 42 | type: string 43 | x-kubernetes-validations: 44 | - message: Value is immutable once set 45 | rule: self == oldSelf 46 | namespaceSelector: 47 | description: IAMRoleSelectorSpec defines the desired state of IAMRoleSelector 48 | properties: 49 | labelSelector: 50 | description: LabelSelector is a label query over a set of resources. 51 | properties: 52 | matchLabels: 53 | additionalProperties: 54 | type: string 55 | type: object 56 | required: 57 | - matchLabels 58 | type: object 59 | names: 60 | items: 61 | type: string 62 | type: array 63 | required: 64 | - names 65 | type: object 66 | resourceTypeSelector: 67 | items: 68 | properties: 69 | group: 70 | type: string 71 | kind: 72 | type: string 73 | version: 74 | type: string 75 | required: 76 | - group 77 | - kind 78 | - version 79 | type: object 80 | type: array 81 | required: 82 | - arn 83 | type: object 84 | status: 85 | type: object 86 | type: object 87 | served: true 88 | storage: true 89 | subresources: 90 | status: {} 91 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug 4 | report, new feature, correction, or additional documentation, we greatly value 5 | feedback and contributions from our community. 6 | 7 | Please read through this document before submitting any issues or pull requests 8 | to ensure we have all the necessary information to effectively respond to your 9 | bug report or contribution. 10 | 11 | ## Reporting Bugs/Feature Requests 12 | 13 | We welcome you to use the GitHub issue tracker to report bugs or suggest 14 | features. 15 | 16 | When filing an issue, please check existing open, or recently closed, issues to 17 | make sure somebody else hasn't already reported the issue. Please try to 18 | include as much information as you can. Details like these are incredibly 19 | useful: 20 | 21 | * A reproducible test case or series of steps 22 | * The version of our code being used 23 | * Any modifications you've made relevant to the bug 24 | * Anything unusual about your environment or deployment 25 | 26 | ## Contributing via Pull Requests 27 | 28 | Contributions via pull requests are much appreciated. Before sending us a pull 29 | request, please ensure that: 30 | 31 | 1. You are working against the latest source on the *main* branch. 32 | 2. You check existing open, and recently merged, pull requests to make sure 33 | someone else hasn't addressed the problem already. 34 | 3. You open an issue to discuss any significant work - we would hate for your 35 | time to be wasted. 36 | 37 | To send us a pull request, please: 38 | 39 | 1. Fork the repository. 40 | 2. Modify the source; please focus on the specific change you are contributing. 41 | If you also reformat all the code, it will be hard for us to focus on your 42 | change. 43 | 3. Ensure local tests pass. 44 | 4. Commit to your fork using clear commit messages. 45 | 5. Send us a pull request, answering any default questions in the pull request 46 | interface. 47 | 6. Pay attention to any automated CI failures reported in the pull request, and 48 | stay involved in the conversation. 49 | 50 | GitHub provides additional document on [forking a repository][fork] and 51 | [creating a pull request][pr]. 52 | 53 | [fork]: https://help.github.com/articles/fork-a-repo/ 54 | [pr]: https://help.github.com/articles/creating-a-pull-request/ 55 | 56 | ## Finding contributions to work on 57 | 58 | Looking at the existing issues is a great way to find something to contribute 59 | on. As our projects, by default, use the default GitHub issue labels 60 | (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at 61 | any 'help wanted' issues is a great place to start. 62 | 63 | ## Developer documentation 64 | 65 | [See the documentation][dev-docs] for detailed development information. 66 | 67 | [dev-docs]: https://aws-controllers-k8s.github.io/community/docs/contributor-docs/overview/ 68 | 69 | ## Code of Conduct 70 | 71 | We adhere to the [Amazon Open Source Code of Conduct][coc]. 72 | 73 | [coc]: https://aws.github.io/code-of-conduct 74 | 75 | ## Security issue notifications 76 | 77 | If you discover a potential security issue in this project we ask that you 78 | notify AWS/Amazon Security via our [vulnerability reporting page][vuln]. Please 79 | do **not** create a public Github issue. 80 | 81 | [vuln]: http://aws.amazon.com/security/vulnerability-reporting/ 82 | 83 | ## License 84 | 85 | This project is [licensed][./LICENSE] under the Apache-2.0 License. 86 | -------------------------------------------------------------------------------- /apis/v1alpha1/annotation.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package v1alpha1 15 | 16 | import "fmt" 17 | 18 | var ( 19 | // DesiredSizeManagedByAnnotation is the annotation key used to set the management style for the 20 | // desired size of a nodegroup scaling configuration. This annotation can only be set on a 21 | // nodegroup custom resource. 22 | // 23 | // The value of this annotation must be one of the following: 24 | // 25 | // - 'external-autoscaler': The desired size is managed by an external entity. Causing the 26 | // controller to completly ignore the `scalingConfig.desiredSize` field 27 | // and not reconcile the desired size of a nodegroup. 28 | // 29 | // - 'ack-eks-controller': The desired size is managed by the ACK controller. Causing the 30 | // controller to reconcile the desired size of the nodegroup with the 31 | // value of the `spec.scalingConfig.desiredSize` field. 32 | // 33 | // By default the desired size is managed by the controller. If the annotation is not set, or 34 | // the value is not one of the above, the controller will default to managing the desired size 35 | // as if the annotation was set to "controller". 36 | DesiredSizeManagedByAnnotation = fmt.Sprintf("%s/desired-size-managed-by", GroupVersion.Group) 37 | // ForceNodeGroupUpdateVersionAnnotation is the annotation key used to force an update of the 38 | // nodegroup version. This annotation can only be set on a nodegroup custom resource. 39 | // The value of this annotation must be a boolean value. If the value is "true", the controller 40 | // will force an update of the nodegroup version to the value specified in the `version` field 41 | // of the `spec` object. If the value is "false", the controller will not force an update of the 42 | // nodegroup version. 43 | ForceNodeGroupUpdateVersionAnnotation = fmt.Sprintf("%s/force-update-version", GroupVersion.Group) 44 | // ForceClusterUpgradeAnnotation is an annotation whose value indicates whether 45 | // the cluster version upgrade should be forced even if there are cluster insight findings. 46 | // The value of this annotation must be a boolean value. 47 | ForceClusterUpgradeAnnotation = fmt.Sprintf("%s/force-upgrade", GroupVersion.Group) 48 | ) 49 | 50 | const ( 51 | // DesiredSizeManagedByExternalAutoscaler is the value of the DesiredSizeManagedByAnnotation 52 | // annotation that indicates that the desired size of a nodegroup is managed by an external 53 | // autoscaler. 54 | DesiredSizeManagedByExternalAutoscaler = "external-autoscaler" 55 | // DesiredSizeManagedByACKController is the value of the DesiredSizeManagedByAnnotation 56 | // annotation that indicates that the desired size of a nodegroup is managed by the ACK 57 | // controller. 58 | DesiredSizeManagedByACKController = "ack-eks-controller" 59 | // DefaultForceClusterUpgrade is the default value for ForceClusterUpgradeAnnotation if the annotation 60 | // is not set or has an invalid value. 61 | DefaultForceClusterUpgrade = false 62 | ) 63 | -------------------------------------------------------------------------------- /pkg/resource/addon/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package addon 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/cluster/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package cluster 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/capability/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package capability 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/nodegroup/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package nodegroup 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/access_entry/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package access_entry 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/fargate_profile/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package fargate_profile 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/identity_provider_config/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package identity_provider_config 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /pkg/resource/pod_identity_association/manager_factory.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package pod_identity_association 17 | 18 | import ( 19 | "fmt" 20 | "sync" 21 | 22 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 23 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 24 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 25 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 26 | "github.com/aws/aws-sdk-go-v2/aws" 27 | "github.com/go-logr/logr" 28 | 29 | svcresource "github.com/aws-controllers-k8s/eks-controller/pkg/resource" 30 | ) 31 | 32 | // resourceManagerFactory produces resourceManager objects. It implements the 33 | // `types.AWSResourceManagerFactory` interface. 34 | type resourceManagerFactory struct { 35 | sync.RWMutex 36 | // rmCache contains resource managers for a particular AWS account ID 37 | rmCache map[string]*resourceManager 38 | } 39 | 40 | // ResourcePrototype returns an AWSResource that resource managers produced by 41 | // this factory will handle 42 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 43 | return &resourceDescriptor{} 44 | } 45 | 46 | // ManagerFor returns a resource manager object that can manage resources for a 47 | // supplied AWS account 48 | func (f *resourceManagerFactory) ManagerFor( 49 | cfg ackcfg.Config, 50 | clientcfg aws.Config, 51 | log logr.Logger, 52 | metrics *ackmetrics.Metrics, 53 | rr acktypes.Reconciler, 54 | id ackv1alpha1.AWSAccountID, 55 | region ackv1alpha1.AWSRegion, 56 | roleARN ackv1alpha1.AWSResourceName, 57 | ) (acktypes.AWSResourceManager, error) { 58 | // We use the account ID, region, and role ARN to uniquely identify a 59 | // resource manager. This helps us to avoid creating multiple resource 60 | // managers for the same account/region/roleARN combination. 61 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 62 | f.RLock() 63 | rm, found := f.rmCache[rmId] 64 | f.RUnlock() 65 | 66 | if found { 67 | return rm, nil 68 | } 69 | 70 | f.Lock() 71 | defer f.Unlock() 72 | 73 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 74 | if err != nil { 75 | return nil, err 76 | } 77 | f.rmCache[rmId] = rm 78 | return rm, nil 79 | } 80 | 81 | // IsAdoptable returns true if the resource is able to be adopted 82 | func (f *resourceManagerFactory) IsAdoptable() bool { 83 | return true 84 | } 85 | 86 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 87 | // Default is false which means resource will not be requeued after success. 88 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 89 | return 0 90 | } 91 | 92 | func newResourceManagerFactory() *resourceManagerFactory { 93 | return &resourceManagerFactory{ 94 | rmCache: map[string]*resourceManager{}, 95 | } 96 | } 97 | 98 | func init() { 99 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 100 | } 101 | -------------------------------------------------------------------------------- /config/controller/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: ack-system 5 | --- 6 | apiVersion: apps/v1 7 | kind: Deployment 8 | metadata: 9 | name: ack-eks-controller 10 | namespace: ack-system 11 | labels: 12 | app.kubernetes.io/name: ack-eks-controller 13 | app.kubernetes.io/part-of: ack-system 14 | spec: 15 | selector: 16 | matchLabels: 17 | app.kubernetes.io/name: ack-eks-controller 18 | replicas: 1 19 | template: 20 | metadata: 21 | labels: 22 | app.kubernetes.io/name: ack-eks-controller 23 | spec: 24 | containers: 25 | - command: 26 | - ./bin/controller 27 | args: 28 | - --aws-region 29 | - "$(AWS_REGION)" 30 | - --aws-endpoint-url 31 | - "$(AWS_ENDPOINT_URL)" 32 | - --enable-development-logging=$(ACK_ENABLE_DEVELOPMENT_LOGGING) 33 | - --log-level 34 | - "$(ACK_LOG_LEVEL)" 35 | - --resource-tags 36 | - "$(ACK_RESOURCE_TAGS)" 37 | - --watch-namespace 38 | - "$(ACK_WATCH_NAMESPACE)" 39 | - --enable-leader-election=$(ENABLE_LEADER_ELECTION) 40 | - --leader-election-namespace 41 | - "$(LEADER_ELECTION_NAMESPACE)" 42 | - --reconcile-default-max-concurrent-syncs 43 | - "$(RECONCILE_DEFAULT_MAX_CONCURRENT_SYNCS)" 44 | - --feature-gates 45 | - "$(FEATURE_GATES)" 46 | - --enable-carm=$(ENABLE_CARM) 47 | image: controller:latest 48 | name: controller 49 | ports: 50 | - name: http 51 | containerPort: 8080 52 | resources: 53 | limits: 54 | cpu: 100m 55 | memory: 300Mi 56 | requests: 57 | cpu: 100m 58 | memory: 200Mi 59 | env: 60 | - name: ACK_SYSTEM_NAMESPACE 61 | valueFrom: 62 | fieldRef: 63 | fieldPath: metadata.namespace 64 | - name: AWS_REGION 65 | value: "" 66 | - name: AWS_ENDPOINT_URL 67 | value: "" 68 | - name: ACK_WATCH_NAMESPACE 69 | value: "" 70 | - name: ACK_ENABLE_DEVELOPMENT_LOGGING 71 | value: "false" 72 | - name: ACK_LOG_LEVEL 73 | value: "info" 74 | - name: ACK_RESOURCE_TAGS 75 | value: "services.k8s.aws/controller-version=%CONTROLLER_SERVICE%-%CONTROLLER_VERSION%,services.k8s.aws/namespace=%K8S_NAMESPACE%" 76 | - name: ENABLE_LEADER_ELECTION 77 | value: "false" 78 | - name: LEADER_ELECTION_NAMESPACE 79 | value: "ack-system" 80 | - name: "RECONCILE_DEFAULT_MAX_CONCURRENT_SYNCS" 81 | value: "1" 82 | - name: "FEATURE_GATES" 83 | value: "" 84 | - name: "ENABLE_CARM" 85 | value: "true" 86 | securityContext: 87 | allowPrivilegeEscalation: false 88 | privileged: false 89 | runAsNonRoot: true 90 | capabilities: 91 | drop: 92 | - ALL 93 | livenessProbe: 94 | httpGet: 95 | path: /healthz 96 | port: 8081 97 | initialDelaySeconds: 15 98 | periodSeconds: 20 99 | readinessProbe: 100 | httpGet: 101 | path: /readyz 102 | port: 8081 103 | initialDelaySeconds: 5 104 | periodSeconds: 10 105 | securityContext: 106 | seccompProfile: 107 | type: RuntimeDefault 108 | terminationGracePeriodSeconds: 10 109 | serviceAccountName: ack-eks-controller 110 | hostIPC: false 111 | hostPID: false 112 | hostNetwork: false 113 | dnsPolicy: ClusterFirst 114 | -------------------------------------------------------------------------------- /pkg/resource/access_entry/delta.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package access_entry 17 | 18 | import ( 19 | "bytes" 20 | "reflect" 21 | 22 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 23 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 24 | ) 25 | 26 | // Hack to avoid import errors during build... 27 | var ( 28 | _ = &bytes.Buffer{} 29 | _ = &reflect.Method{} 30 | _ = &acktags.Tags{} 31 | ) 32 | 33 | // newResourceDelta returns a new `ackcompare.Delta` used to compare two 34 | // resources 35 | func newResourceDelta( 36 | a *resource, 37 | b *resource, 38 | ) *ackcompare.Delta { 39 | delta := ackcompare.NewDelta() 40 | if (a == nil && b != nil) || 41 | (a != nil && b == nil) { 42 | delta.Add("", a, b) 43 | return delta 44 | } 45 | customPreCompare(delta, a, b) 46 | 47 | if ackcompare.HasNilDifference(a.ko.Spec.ClusterName, b.ko.Spec.ClusterName) { 48 | delta.Add("Spec.ClusterName", a.ko.Spec.ClusterName, b.ko.Spec.ClusterName) 49 | } else if a.ko.Spec.ClusterName != nil && b.ko.Spec.ClusterName != nil { 50 | if *a.ko.Spec.ClusterName != *b.ko.Spec.ClusterName { 51 | delta.Add("Spec.ClusterName", a.ko.Spec.ClusterName, b.ko.Spec.ClusterName) 52 | } 53 | } 54 | if !reflect.DeepEqual(a.ko.Spec.ClusterRef, b.ko.Spec.ClusterRef) { 55 | delta.Add("Spec.ClusterRef", a.ko.Spec.ClusterRef, b.ko.Spec.ClusterRef) 56 | } 57 | if len(a.ko.Spec.KubernetesGroups) != len(b.ko.Spec.KubernetesGroups) { 58 | delta.Add("Spec.KubernetesGroups", a.ko.Spec.KubernetesGroups, b.ko.Spec.KubernetesGroups) 59 | } else if len(a.ko.Spec.KubernetesGroups) > 0 { 60 | if !ackcompare.SliceStringPEqual(a.ko.Spec.KubernetesGroups, b.ko.Spec.KubernetesGroups) { 61 | delta.Add("Spec.KubernetesGroups", a.ko.Spec.KubernetesGroups, b.ko.Spec.KubernetesGroups) 62 | } 63 | } 64 | if ackcompare.HasNilDifference(a.ko.Spec.PrincipalARN, b.ko.Spec.PrincipalARN) { 65 | delta.Add("Spec.PrincipalARN", a.ko.Spec.PrincipalARN, b.ko.Spec.PrincipalARN) 66 | } else if a.ko.Spec.PrincipalARN != nil && b.ko.Spec.PrincipalARN != nil { 67 | if *a.ko.Spec.PrincipalARN != *b.ko.Spec.PrincipalARN { 68 | delta.Add("Spec.PrincipalARN", a.ko.Spec.PrincipalARN, b.ko.Spec.PrincipalARN) 69 | } 70 | } 71 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 72 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 73 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 74 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 75 | } 76 | if ackcompare.HasNilDifference(a.ko.Spec.Type, b.ko.Spec.Type) { 77 | delta.Add("Spec.Type", a.ko.Spec.Type, b.ko.Spec.Type) 78 | } else if a.ko.Spec.Type != nil && b.ko.Spec.Type != nil { 79 | if *a.ko.Spec.Type != *b.ko.Spec.Type { 80 | delta.Add("Spec.Type", a.ko.Spec.Type, b.ko.Spec.Type) 81 | } 82 | } 83 | if ackcompare.HasNilDifference(a.ko.Spec.Username, b.ko.Spec.Username) { 84 | delta.Add("Spec.Username", a.ko.Spec.Username, b.ko.Spec.Username) 85 | } else if a.ko.Spec.Username != nil && b.ko.Spec.Username != nil { 86 | if *a.ko.Spec.Username != *b.ko.Spec.Username { 87 | delta.Add("Spec.Username", a.ko.Spec.Username, b.ko.Spec.Username) 88 | } 89 | } 90 | 91 | return delta 92 | } 93 | -------------------------------------------------------------------------------- /pkg/resource/capability/hooks.go: -------------------------------------------------------------------------------- 1 | package capability 2 | 3 | import ( 4 | "reflect" 5 | 6 | "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 7 | "github.com/aws-controllers-k8s/eks-controller/pkg/tags" 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | svcsdk "github.com/aws/aws-sdk-go-v2/service/eks" 10 | svcsdktypes "github.com/aws/aws-sdk-go-v2/service/eks/types" 11 | ) 12 | 13 | var syncTags = tags.SyncTags 14 | 15 | // setConfiguration sets the configuration field of UpdateCapabilityInput. 16 | // It especially compares which rbacRoleMappings need to be added and updated 17 | // vs the ones that need to be removed 18 | func setConfiguration( 19 | input *svcsdk.UpdateCapabilityInput, 20 | desired *resource, 21 | latest *resource, 22 | ) { 23 | if desired.ko.Spec.Configuration == nil || desired.ko.Spec.Configuration.ArgoCD == nil { 24 | input.Configuration = nil 25 | return 26 | } 27 | 28 | if input.Configuration == nil || input.Configuration.ArgoCd == nil { 29 | input.Configuration = &svcsdktypes.UpdateCapabilityConfiguration{ 30 | ArgoCd: &svcsdktypes.UpdateArgoCdConfig{}, 31 | } 32 | } 33 | 34 | if desired.ko.Spec.Configuration.ArgoCD.NetworkAccess != nil { 35 | input.Configuration.ArgoCd.NetworkAccess = &svcsdktypes.ArgoCdNetworkAccessConfigRequest{ 36 | VpceIds: aws.ToStringSlice(desired.ko.Spec.Configuration.ArgoCD.NetworkAccess.VPCEIDs), 37 | } 38 | } 39 | if desired.ko.Spec.Configuration.ArgoCD.RbacRoleMappings != nil { 40 | input.Configuration.ArgoCd.RbacRoleMappings = &svcsdktypes.UpdateRoleMappings{} 41 | toAddOrUpdate, toRemove := compareRbacRoleMappings(desired.ko.Spec.Configuration.ArgoCD.RbacRoleMappings, latest.ko.Spec.Configuration.ArgoCD.RbacRoleMappings) 42 | if len(toAddOrUpdate) > 0 { 43 | input.Configuration.ArgoCd.RbacRoleMappings.AddOrUpdateRoleMappings = toAddOrUpdate 44 | } 45 | if len(toRemove) > 0 { 46 | input.Configuration.ArgoCd.RbacRoleMappings.RemoveRoleMappings = toRemove 47 | } 48 | } 49 | } 50 | 51 | func compareRbacRoleMappings(desired []*v1alpha1.ArgoCDRoleMapping, latest []*v1alpha1.ArgoCDRoleMapping) ([]svcsdktypes.ArgoCdRoleMapping, []svcsdktypes.ArgoCdRoleMapping) { 52 | var toAddOrUpdate []svcsdktypes.ArgoCdRoleMapping 53 | var toRemove []svcsdktypes.ArgoCdRoleMapping 54 | 55 | for _, desiredMapping := range desired { 56 | found := false 57 | for _, latestMapping := range latest { 58 | if isRoleMappingEqual(desiredMapping, latestMapping) { 59 | found = true 60 | break 61 | } 62 | } 63 | if !found { 64 | toAddOrUpdate = append(toAddOrUpdate, roleMappingToServiceSDK(desiredMapping)) 65 | } 66 | } 67 | 68 | for _, latestMapping := range latest { 69 | found := false 70 | for _, desiredMapping := range desired { 71 | if isRoleMappingEqual(desiredMapping, latestMapping) { 72 | found = true 73 | break 74 | } 75 | } 76 | if !found { 77 | toRemove = append(toRemove, roleMappingToServiceSDK(latestMapping)) 78 | } 79 | } 80 | 81 | return toAddOrUpdate, toRemove 82 | } 83 | 84 | func isRoleMappingEqual(desired *v1alpha1.ArgoCDRoleMapping, latest *v1alpha1.ArgoCDRoleMapping) bool { 85 | return aws.ToString(desired.Role) == aws.ToString(latest.Role) && 86 | reflect.DeepEqual(desired.Identities, latest.Identities) 87 | } 88 | 89 | func roleMappingToServiceSDK(roleMapping *v1alpha1.ArgoCDRoleMapping) svcsdktypes.ArgoCdRoleMapping { 90 | rm := svcsdktypes.ArgoCdRoleMapping{ 91 | Role: svcsdktypes.ArgoCdRole(aws.ToString(roleMapping.Role)), 92 | } 93 | identities := make([]svcsdktypes.SsoIdentity, len(roleMapping.Identities)) 94 | for i, identity := range roleMapping.Identities { 95 | identities[i] = svcsdktypes.SsoIdentity{ 96 | Id: identity.ID, 97 | Type: svcsdktypes.SsoIdentityType(aws.ToString(identity.Type)), 98 | } 99 | } 100 | return rm 101 | } 102 | -------------------------------------------------------------------------------- /apis/v1alpha1/identity_provider_config.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package v1alpha1 17 | 18 | import ( 19 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // IdentityProviderConfigSpec defines the desired state of IdentityProviderConfig. 24 | // 25 | // An object representing an identity provider configuration. 26 | type IdentityProviderConfigSpec struct { 27 | 28 | // The name of your cluster. 29 | // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable once set" 30 | ClusterName *string `json:"clusterName,omitempty"` 31 | ClusterRef *ackv1alpha1.AWSResourceReferenceWrapper `json:"clusterRef,omitempty"` 32 | // An object representing an OpenID Connect (OIDC) identity provider configuration. 33 | // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable once set" 34 | // +kubebuilder:validation:Required 35 | OIDC *OIDCIdentityProviderConfigRequest `json:"oidc"` 36 | // Metadata that assists with categorization and organization. Each tag consists 37 | // of a key and an optional value. You define both. Tags don't propagate to 38 | // any other cluster or Amazon Web Services resources. 39 | // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable once set" 40 | Tags map[string]*string `json:"tags,omitempty"` 41 | } 42 | 43 | // IdentityProviderConfigStatus defines the observed state of IdentityProviderConfig 44 | type IdentityProviderConfigStatus struct { 45 | // All CRs managed by ACK have a common `Status.ACKResourceMetadata` member 46 | // that is used to contain resource sync state, account ownership, 47 | // constructed ARN for the resource 48 | // +kubebuilder:validation:Optional 49 | ACKResourceMetadata *ackv1alpha1.ResourceMetadata `json:"ackResourceMetadata"` 50 | // All CRs managed by ACK have a common `Status.Conditions` member that 51 | // contains a collection of `ackv1alpha1.Condition` objects that describe 52 | // the various terminal states of the CR and its backend AWS service API 53 | // resource 54 | // +kubebuilder:validation:Optional 55 | Conditions []*ackv1alpha1.Condition `json:"conditions"` 56 | // The status of the OIDC identity provider. 57 | // +kubebuilder:validation:Optional 58 | Status *string `json:"status,omitempty"` 59 | } 60 | 61 | // IdentityProviderConfig is the Schema for the IdentityProviderConfigs API 62 | // +kubebuilder:object:root=true 63 | // +kubebuilder:subresource:status 64 | type IdentityProviderConfig struct { 65 | metav1.TypeMeta `json:",inline"` 66 | metav1.ObjectMeta `json:"metadata,omitempty"` 67 | Spec IdentityProviderConfigSpec `json:"spec,omitempty"` 68 | Status IdentityProviderConfigStatus `json:"status,omitempty"` 69 | } 70 | 71 | // IdentityProviderConfigList contains a list of IdentityProviderConfig 72 | // +kubebuilder:object:root=true 73 | type IdentityProviderConfigList struct { 74 | metav1.TypeMeta `json:",inline"` 75 | metav1.ListMeta `json:"metadata,omitempty"` 76 | Items []IdentityProviderConfig `json:"items"` 77 | } 78 | 79 | func init() { 80 | SchemeBuilder.Register(&IdentityProviderConfig{}, &IdentityProviderConfigList{}) 81 | } 82 | -------------------------------------------------------------------------------- /pkg/resource/addon/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package addon 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.Addon{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/cluster/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package cluster 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.Cluster{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/capability/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package capability 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.Capability{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/nodegroup/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package nodegroup 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.Nodegroup{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/access_entry/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package access_entry 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.AccessEntry{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/fargate_profile/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package fargate_profile 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.FargateProfile{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /test/e2e/tests/test_capability.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | """Integration tests for the EKS Capability resource 15 | """ 16 | 17 | import logging 18 | import time 19 | from typing import Dict, Tuple 20 | 21 | import pytest 22 | 23 | from acktest.k8s import resource as k8s, condition 24 | from acktest.resources import random_suffix_name 25 | from e2e import CRD_VERSION, service_marker, CRD_GROUP, load_eks_resource 26 | from e2e.replacement_values import REPLACEMENT_VALUES 27 | from e2e.fixtures import assert_tagging_functionality 28 | 29 | from .test_cluster import simple_cluster, wait_for_cluster_active, get_and_assert_status 30 | 31 | RESOURCE_PLURAL = 'capabilities' 32 | 33 | # Time to wait after creating the CR for the status to be populated 34 | CREATE_WAIT_AFTER_SECONDS = 10 35 | 36 | # Time to wait after modifying the CR for the status to change 37 | MODIFY_WAIT_AFTER_SECONDS = 10 38 | 39 | # Time to wait after the capability has changed status, for the CR to update 40 | CHECK_STATUS_WAIT_SECONDS = 10 41 | 42 | @pytest.fixture 43 | def simple_capability(eks_client, simple_cluster) -> Tuple[k8s.CustomResourceReference, Dict]: 44 | (ref, cr) = simple_cluster 45 | cluster_name = cr["spec"]["name"] 46 | 47 | wait_for_cluster_active(eks_client, cluster_name) 48 | 49 | capability_name = random_suffix_name("capability", 32) 50 | 51 | replacements = REPLACEMENT_VALUES.copy() 52 | replacements["CLUSTER_NAME"] = cluster_name 53 | replacements["CAPABILITY_NAME"] = capability_name 54 | replacements["ROLE_ARN"] = capability_name 55 | 56 | resource_data = load_eks_resource( 57 | "capability_simple", 58 | additional_replacements=replacements, 59 | ) 60 | logging.debug(resource_data) 61 | 62 | # Create the k8s resource 63 | ref = k8s.CustomResourceReference( 64 | CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, 65 | capability_name, namespace="default", 66 | ) 67 | k8s.create_custom_resource(ref, resource_data) 68 | cr = k8s.wait_resource_consumed_by_controller(ref) 69 | 70 | assert cr is not None 71 | assert k8s.get_resource_exists(ref) 72 | 73 | time.sleep(CREATE_WAIT_AFTER_SECONDS) 74 | 75 | yield (ref, cr) 76 | 77 | _, deleted = k8s.delete_custom_resource(ref, 3, 10) 78 | assert deleted 79 | 80 | @service_marker 81 | class TestCapability: 82 | def test_create_update_delete_capability(self, simple_capability, eks_client): 83 | (ref, cr) = simple_capability 84 | 85 | cluster_name = cr["spec"]["clusterName"] 86 | cr_name = ref.name 87 | 88 | capability_name = cr["spec"]["name"] 89 | 90 | try: 91 | aws_res = eks_client.describe_capability( 92 | clusterName=cluster_name, 93 | capabilityName=capability_name 94 | ) 95 | assert aws_res is not None 96 | 97 | assert aws_res["capability"]["capabilityName"] == capability_name 98 | assert aws_res["capability"]["roleArn"] is not None 99 | except eks_client.exceptions.ResourceNotFoundException: 100 | pytest.fail(f"Could not find Capability '{cr_name}' in EKS") 101 | 102 | k8s.wait_on_condition(ref, condition.CONDITION_TYPE_RESOURCE_SYNCED, "True", wait_periods=5, period_length=CHECK_STATUS_WAIT_SECONDS) 103 | 104 | assert_tagging_functionality(ref, cr["status"]["ackResourceMetadata"]["arn"]) 105 | -------------------------------------------------------------------------------- /test/e2e/fixtures.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | """Fixtures common to all EKS controller tests""" 15 | 16 | import dataclasses 17 | import logging 18 | 19 | from acktest.k8s.resource import _get_k8s_api_client 20 | from kubernetes import client 21 | from acktest.k8s import resource as k8s 22 | from acktest import tags as tagutil 23 | 24 | import time 25 | import pytest 26 | import boto3 27 | 28 | @dataclasses.dataclass 29 | class SeviceAccountRef: 30 | ns: str 31 | name: str 32 | 33 | def create_service_account(namespace: str, name: str): 34 | pass 35 | """ 36 | Creates a new ServiceAccount. 37 | 38 | :param namespace: Namespace of the ServiceAccount. 39 | :param name: Name of the ServiceAccount 40 | :return: None 41 | """ 42 | _api_client = _get_k8s_api_client() 43 | service_account = client.V1ServiceAccount( 44 | api_version='v1', 45 | kind='ServiceAccount', 46 | metadata={ 47 | 'name': name, 48 | 'namespace': namespace, 49 | }, 50 | ) 51 | service_account = _api_client.sanitize_for_serialization(service_account) 52 | client.CoreV1Api(_api_client).create_namespaced_service_account(namespace.lower(), service_account) 53 | 54 | def delete_service_account(namespace: str, name: str): 55 | """ 56 | Delete an existing k8s ServiceAccount. 57 | 58 | :param namespace: Namespace of the ServiceAccount. 59 | :param name: Name of the ServiceAccount 60 | :return: None 61 | """ 62 | _api_client = _get_k8s_api_client() 63 | client.CoreV1Api(_api_client).delete_namespaced_service_account(name.lower(), namespace.lower()) 64 | 65 | @pytest.fixture(scope="module") 66 | def k8s_service_account(): 67 | created = [] 68 | def _k8s_service_account(ns, name): 69 | create_service_account(ns, name) 70 | sa_ref = SeviceAccountRef(ns, name) 71 | created.append(sa_ref) 72 | return sa_ref 73 | 74 | yield _k8s_service_account 75 | 76 | for sa_ref in created: 77 | delete_service_account(sa_ref.ns, sa_ref.name) 78 | 79 | TAGS_PATCH_WAIT_TIME = 5 80 | 81 | def assert_tagging_functionality(ref, arn): 82 | eks_client = boto3.client('eks') 83 | # Add tags 84 | k8s.patch_custom_resource(ref, { 85 | "spec": { 86 | "tags": { 87 | "key1": "value1", 88 | "key2": "value2" 89 | } 90 | } 91 | }) 92 | time.sleep(TAGS_PATCH_WAIT_TIME) 93 | 94 | 95 | pia_tags = eks_client.list_tags_for_resource( 96 | resourceArn=arn 97 | ) 98 | pia_tags = tagutil.clean(pia_tags['tags']) 99 | assert len(pia_tags) == 2 100 | assert pia_tags["key1"] == "value1" 101 | assert pia_tags["key2"] == "value2" 102 | 103 | # Update tags 104 | k8s.patch_custom_resource(ref, { 105 | "spec": { 106 | "tags": { 107 | "key2": "value2-updated", 108 | "key3": "value3" 109 | } 110 | } 111 | }) 112 | time.sleep(TAGS_PATCH_WAIT_TIME) 113 | 114 | pia_tags = eks_client.list_tags_for_resource( 115 | resourceArn=arn 116 | ) 117 | pia_tags = tagutil.clean(pia_tags['tags']) 118 | logging.info(pia_tags) 119 | assert len(pia_tags) == 3 120 | assert pia_tags["key1"] == "value1" 121 | assert pia_tags["key2"] == "value2-updated" 122 | assert pia_tags["key3"] == "value3" -------------------------------------------------------------------------------- /pkg/resource/identity_provider_config/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package identity_provider_config 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.IdentityProviderConfig{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/pod_identity_association/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package pod_identity_association 17 | 18 | import ( 19 | "slices" 20 | "strings" 21 | 22 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 23 | 24 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 25 | ) 26 | 27 | var ( 28 | _ = svcapitypes.PodIdentityAssociation{} 29 | _ = acktags.NewTags() 30 | ) 31 | 32 | // convertToOrderedACKTags converts the tags parameter into 'acktags.Tags' shape. 33 | // This method helps in creating the hub(acktags.Tags) for merging 34 | // default controller tags with existing resource tags. It also returns a slice 35 | // of keys maintaining the original key Order when the tags are a list 36 | func convertToOrderedACKTags(tags map[string]*string) (acktags.Tags, []string) { 37 | result := acktags.NewTags() 38 | keyOrder := []string{} 39 | 40 | if len(tags) == 0 { 41 | return result, keyOrder 42 | } 43 | for k, v := range tags { 44 | if v == nil { 45 | result[k] = "" 46 | } else { 47 | result[k] = *v 48 | } 49 | } 50 | 51 | return result, keyOrder 52 | } 53 | 54 | // fromACKTags converts the tags parameter into map[string]*string shape. 55 | // This method helps in setting the tags back inside AWSResource after merging 56 | // default controller tags with existing resource tags. When a list, 57 | // it maintains the order from original 58 | func fromACKTags(tags acktags.Tags, keyOrder []string) map[string]*string { 59 | result := map[string]*string{} 60 | 61 | _ = keyOrder 62 | for k, v := range tags { 63 | result[k] = &v 64 | } 65 | 66 | return result 67 | } 68 | 69 | // ignoreSystemTags ignores tags that have keys that start with "aws:" 70 | // and systemTags defined on startup via the --resource-tags flag, 71 | // to avoid patching them to the resourceSpec. 72 | // Eg. resources created with cloudformation have tags that cannot be 73 | // removed by an ACK controller 74 | func ignoreSystemTags(tags acktags.Tags, systemTags []string) { 75 | for k := range tags { 76 | if strings.HasPrefix(k, "aws:") || 77 | slices.Contains(systemTags, k) { 78 | delete(tags, k) 79 | } 80 | } 81 | } 82 | 83 | // syncAWSTags ensures AWS-managed tags (prefixed with "aws:") from the latest resource state 84 | // are preserved in the desired state. This prevents the controller from attempting to 85 | // modify AWS-managed tags, which would result in an error. 86 | // 87 | // AWS-managed tags are automatically added by AWS services (e.g., CloudFormation, Service Catalog) 88 | // and cannot be modified or deleted through normal tag operations. Common examples include: 89 | // - aws:cloudformation:stack-name 90 | // - aws:servicecatalog:productArn 91 | // 92 | // Parameters: 93 | // - a: The target Tags map to be updated (typically desired state) 94 | // - b: The source Tags map containing AWS-managed tags (typically latest state) 95 | // 96 | // Example: 97 | // 98 | // latest := Tags{"aws:cloudformation:stack-name": "my-stack", "environment": "prod"} 99 | // desired := Tags{"environment": "dev"} 100 | // SyncAWSTags(desired, latest) 101 | // desired now contains {"aws:cloudformation:stack-name": "my-stack", "environment": "dev"} 102 | func syncAWSTags(a acktags.Tags, b acktags.Tags) { 103 | for k := range b { 104 | if strings.HasPrefix(k, "aws:") { 105 | a[k] = b[k] 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /pkg/resource/cluster/resource.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package cluster 17 | 18 | import ( 19 | "fmt" 20 | 21 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 22 | ackerrors "github.com/aws-controllers-k8s/runtime/pkg/errors" 23 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | rtclient "sigs.k8s.io/controller-runtime/pkg/client" 26 | 27 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 28 | ) 29 | 30 | // Hack to avoid import errors during build... 31 | var ( 32 | _ = &ackerrors.MissingNameIdentifier 33 | ) 34 | 35 | // resource implements the `aws-controller-k8s/runtime/pkg/types.AWSResource` 36 | // interface 37 | type resource struct { 38 | // The Kubernetes-native CR representing the resource 39 | ko *svcapitypes.Cluster 40 | } 41 | 42 | // Identifiers returns an AWSResourceIdentifiers object containing various 43 | // identifying information, including the AWS account ID that owns the 44 | // resource, the resource's AWS Resource Name (ARN) 45 | func (r *resource) Identifiers() acktypes.AWSResourceIdentifiers { 46 | return &resourceIdentifiers{r.ko.Status.ACKResourceMetadata} 47 | } 48 | 49 | // IsBeingDeleted returns true if the Kubernetes resource has a non-zero 50 | // deletion timestamp 51 | func (r *resource) IsBeingDeleted() bool { 52 | return !r.ko.DeletionTimestamp.IsZero() 53 | } 54 | 55 | // RuntimeObject returns the Kubernetes apimachinery/runtime representation of 56 | // the AWSResource 57 | func (r *resource) RuntimeObject() rtclient.Object { 58 | return r.ko 59 | } 60 | 61 | // MetaObject returns the Kubernetes apimachinery/apis/meta/v1.Object 62 | // representation of the AWSResource 63 | func (r *resource) MetaObject() metav1.Object { 64 | return r.ko.GetObjectMeta() 65 | } 66 | 67 | // Conditions returns the ACK Conditions collection for the AWSResource 68 | func (r *resource) Conditions() []*ackv1alpha1.Condition { 69 | return r.ko.Status.Conditions 70 | } 71 | 72 | // ReplaceConditions sets the Conditions status field for the resource 73 | func (r *resource) ReplaceConditions(conditions []*ackv1alpha1.Condition) { 74 | r.ko.Status.Conditions = conditions 75 | } 76 | 77 | // SetObjectMeta sets the ObjectMeta field for the resource 78 | func (r *resource) SetObjectMeta(meta metav1.ObjectMeta) { 79 | r.ko.ObjectMeta = meta 80 | } 81 | 82 | // SetStatus will set the Status field for the resource 83 | func (r *resource) SetStatus(desired acktypes.AWSResource) { 84 | r.ko.Status = desired.(*resource).ko.Status 85 | } 86 | 87 | // SetIdentifiers sets the Spec or Status field that is referenced as the unique 88 | // resource identifier 89 | func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error { 90 | if identifier.NameOrID == "" { 91 | return ackerrors.MissingNameIdentifier 92 | } 93 | r.ko.Spec.Name = &identifier.NameOrID 94 | 95 | return nil 96 | } 97 | 98 | // PopulateResourceFromAnnotation populates the fields passed from adoption annotation 99 | func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { 100 | f0, ok := fields["name"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: name")) 103 | } 104 | r.ko.Spec.Name = &f0 105 | 106 | return nil 107 | } 108 | 109 | // DeepCopy will return a copy of the resource 110 | func (r *resource) DeepCopy() acktypes.AWSResource { 111 | koCopy := r.ko.DeepCopy() 112 | return &resource{koCopy} 113 | } 114 | -------------------------------------------------------------------------------- /test/e2e/common/waiter.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | import datetime 15 | import time 16 | import typing 17 | 18 | import boto3 19 | import pytest 20 | 21 | DEFAULT_WAIT_UNTIL_TIMEOUT_SECONDS = 60*10 22 | DEFAULT_WAIT_UNTIL_INTERVAL_SECONDS = 15 23 | DEFAULT_WAIT_UNTIL_DELETED_TIMEOUT_SECONDS = 60*20 24 | DEFAULT_WAIT_UNTIL_DELETED_INTERVAL_SECONDS = 30 25 | 26 | ClusterMatchFunc = typing.NewType( 27 | 'ClusterMatchFunc', 28 | typing.Callable[[dict], bool], 29 | ) 30 | 31 | class StatusMatcher: 32 | def __init__(self, status): 33 | self.match_on = status 34 | 35 | def __call__(self, record: dict) -> bool: 36 | return (record is not None and 'status' in record 37 | and record['status'] == self.match_on) 38 | 39 | 40 | def status_matches(status: str) -> ClusterMatchFunc: 41 | return StatusMatcher(status) 42 | 43 | 44 | def wait_until( 45 | eks_cluster_name: str, 46 | match_fn: ClusterMatchFunc, 47 | timeout_seconds: int = DEFAULT_WAIT_UNTIL_TIMEOUT_SECONDS, 48 | interval_seconds: int = DEFAULT_WAIT_UNTIL_INTERVAL_SECONDS, 49 | ) -> None: 50 | """Waits until an EKS cluster with the supplied name is returned from the EKS API 51 | and the matching functor returns True. 52 | 53 | Usage: 54 | from e2e.common.waiter import wait_until, status_matches 55 | 56 | wait_until( 57 | cluster_name, 58 | status_matches("ACTIVE"), 59 | ) 60 | 61 | Raises: 62 | pytest.fail upon timeout 63 | """ 64 | now = datetime.datetime.now() 65 | timeout = now + datetime.timedelta(seconds=timeout_seconds) 66 | 67 | while not match_fn(get(eks_cluster_name)): 68 | if datetime.datetime.now() >= timeout: 69 | pytest.fail("failed to match Cluster before timeout") 70 | time.sleep(interval_seconds) 71 | 72 | 73 | def wait_until_deleted( 74 | eks_cluster_name: str, 75 | timeout_seconds: int = DEFAULT_WAIT_UNTIL_DELETED_TIMEOUT_SECONDS, 76 | interval_seconds: int = DEFAULT_WAIT_UNTIL_DELETED_INTERVAL_SECONDS, 77 | ) -> None: 78 | """Waits until an EKS cluster with the supplied name is no longer returned from 79 | the EKS API. 80 | 81 | Usage: 82 | from e2e.common.waiter import wait_until_deleted 83 | 84 | wait_until_deleted(cluster_name) 85 | 86 | Raises: 87 | pytest.fail upon timeout or if the EKS cluster goes to any other status 88 | other than 'DELETING' 89 | """ 90 | now = datetime.datetime.now() 91 | timeout = now + datetime.timedelta(seconds=timeout_seconds) 92 | 93 | while True: 94 | if datetime.datetime.now() >= timeout: 95 | pytest.fail("Timed out waiting for cluster to be deleted in EKS API") 96 | time.sleep(interval_seconds) 97 | 98 | latest = get(eks_cluster_name) 99 | if latest is None: 100 | break 101 | 102 | if latest['status'] != "DELETING": 103 | pytest.fail( 104 | "Status is not 'DELETING' for EKS cluster that was " 105 | "deleted. Status is " + latest['status'] 106 | ) 107 | 108 | def get(eks_cluster_name): 109 | """Returns a dict containing the EKS cluster record from the EKS API. 110 | 111 | If no such cluster exists, returns None. 112 | """ 113 | c = boto3.client('eks') 114 | try: 115 | resp = c.describe_cluster(name=eks_cluster_name) 116 | assert 'cluster' in resp 117 | return resp['cluster'] 118 | except c.exceptions.ResourceNotFoundException: 119 | return None 120 | -------------------------------------------------------------------------------- /test/e2e/tests/test_pod_identity_association.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | 14 | """Integration tests for the EKS PodIdentityAssociation resource 15 | """ 16 | 17 | import json 18 | import logging 19 | import time 20 | from typing import Dict, Tuple 21 | 22 | import pytest 23 | from acktest.k8s import resource as k8s 24 | from acktest.resources import random_suffix_name 25 | from e2e import CRD_VERSION, service_marker, CRD_GROUP, load_eks_resource 26 | from e2e.replacement_values import REPLACEMENT_VALUES 27 | from e2e.fixtures import k8s_service_account, assert_tagging_functionality 28 | 29 | from .test_cluster import simple_cluster, wait_for_cluster_active 30 | 31 | RESOURCE_PLURAL = 'podidentityassociations' 32 | 33 | #TODO(a-hilaly): Dynamically create this role... 34 | PIA_ROLE = "arn:aws:iam::632556926448:role/ack-eks-controller-pia-role" 35 | 36 | CREATE_WAIT_AFTER_SECONDS = 10 37 | 38 | @pytest.fixture 39 | def pod_identity_association(k8s_service_account, eks_client, simple_cluster) -> Tuple[k8s.CustomResourceReference, Dict]: 40 | cr_name = random_suffix_name("s3-readonly-pia", 24) 41 | namespace = "default" 42 | service_account_name = "s3-readonly-service-account" 43 | _ = k8s_service_account(namespace, service_account_name) 44 | 45 | (ref, cr) = simple_cluster 46 | cluster_name = cr["spec"]["name"] 47 | 48 | wait_for_cluster_active(eks_client, cluster_name) 49 | 50 | replacements = REPLACEMENT_VALUES.copy() 51 | replacements["CR_NAME"] = cr_name 52 | replacements["CLUSTER_NAME"] = cluster_name 53 | replacements["NAMESPACE"] = namespace 54 | replacements["ROLE_ARN"] = "arn:aws:iam::632556926448:role/ack-eks-controller-pia-role" 55 | replacements["SERVICE_ACCOUNT"] = service_account_name 56 | 57 | resource_data = load_eks_resource( 58 | "pod_identity_association", 59 | additional_replacements=replacements, 60 | ) 61 | logging.debug(resource_data) 62 | 63 | # Create the k8s resource 64 | ref = k8s.CustomResourceReference( 65 | CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, 66 | cr_name, namespace="default", 67 | ) 68 | k8s.create_custom_resource(ref, resource_data) 69 | cr = k8s.wait_resource_consumed_by_controller(ref) 70 | 71 | assert cr is not None 72 | assert k8s.get_resource_exists(ref) 73 | 74 | time.sleep(CREATE_WAIT_AFTER_SECONDS) 75 | 76 | yield (ref, cr) 77 | 78 | _, deleted = k8s.delete_custom_resource(ref, 3, 10) 79 | assert deleted 80 | 81 | 82 | @service_marker 83 | class TestPodIdentityAssociation: 84 | def test_create_delete_pod_identity_association(self, pod_identity_association, eks_client): 85 | (ref, cr) = pod_identity_association 86 | 87 | cluster_name = cr["spec"]["clusterName"] 88 | association_id = cr["status"]["associationID"] 89 | namespace = cr["spec"]["namespace"] 90 | role_arn = cr["spec"]["roleARN"] 91 | 92 | try: 93 | aws_res = eks_client.describe_pod_identity_association( 94 | clusterName=cluster_name, 95 | associationId=association_id 96 | ) 97 | assert aws_res is not None 98 | 99 | assert aws_res["association"]["namespace"] == namespace 100 | assert aws_res["association"]["roleArn"] == role_arn 101 | assert aws_res["association"]["associationId"] == association_id 102 | except eks_client.exceptions.ResourceNotFoundException: 103 | pytest.fail(f"Could not find PodIdentityAssociation '{ref.name}' in EKS") 104 | 105 | assert_tagging_functionality(ref, cr["status"]["ackResourceMetadata"]["arn"]) -------------------------------------------------------------------------------- /test/e2e/service_bootstrap.py: -------------------------------------------------------------------------------- 1 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | # not use this file except in compliance with the License. A copy of the 5 | # License is located at 6 | # 7 | # http://aws.amazon.com/apache2.0/ 8 | # 9 | # or in the "license" file accompanying this file. This file is distributed 10 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | # express or implied. See the License for the specific language governing 12 | # permissions and limitations under the License. 13 | """Bootstraps the resources required to run the EKS integration tests. 14 | """ 15 | import logging 16 | 17 | import boto3 18 | from acktest.aws.identity import get_region 19 | from acktest.bootstrapping import Resources, BootstrapFailureException 20 | from acktest.bootstrapping.iam import Role 21 | from acktest.bootstrapping.vpc import VPC 22 | from acktest.bootstrapping.eks import Cluster 23 | from e2e import bootstrap_directory 24 | from e2e.bootstrap_resources import BootstrapResources 25 | 26 | def get_availability_zone_names(): 27 | ec2_client = boto3.client("ec2", region_name=get_region()) 28 | zones = ec2_client.describe_availability_zones() 29 | return list(map(lambda x: x['ZoneName'], zones['AvailabilityZones'])) 30 | 31 | def service_bootstrap() -> Resources: 32 | logging.getLogger().setLevel(logging.INFO) 33 | 34 | zones = get_availability_zone_names() 35 | # We create one subnet more than the number of AZs in order to have the last subnet in the same AZ as the first one 36 | num_public_subnet=len(zones) + 1 37 | 38 | resources = BootstrapResources( 39 | ClusterRole=Role("cluster-role", "eks.amazonaws.com", managed_policies=["arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"]), 40 | FargatePodRole=Role("fargate-pod-role", "eks-fargate-pods.amazonaws.com", managed_policies=["arn:aws:iam::aws:policy/AmazonEKSFargatePodExecutionRolePolicy"]), 41 | NodegroupRole=Role("nodegroup-role", "ec2.amazonaws.com", managed_policies=[ 42 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", 43 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", 44 | "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy" 45 | ]), 46 | AutoClusterRole=Role("cluster-role", "eks.amazonaws.com", managed_policies=["arn:aws:iam::aws:policy/AmazonEKSBlockStoragePolicy", 47 | "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy", 48 | "arn:aws:iam::aws:policy/AmazonEKSComputePolicy", 49 | "arn:aws:iam::aws:policy/AmazonEKSLoadBalancingPolicy", 50 | "arn:aws:iam::aws:policy/AmazonEKSNetworkingPolicy",]), 51 | NodepoolRole=Role("nodepool-role", "ec2.amazonaws.com", managed_policies=[ 52 | "arn:aws:iam::aws:policy/AmazonEKSWorkerNodeMinimalPolicy", 53 | "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", 54 | "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" 55 | ]), 56 | CapabilityRole=Role("capability-role", "capabilities.eks.amazonaws.com", managed_policies=[]), 57 | PodIdentityAssociationRole=Role( 58 | "ack-pod-identity-association-role", 59 | "pods.eks.amazonaws.com", 60 | managed_policies=[ 61 | "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess", 62 | ] 63 | ), 64 | AccessEntryPrincipalRole=Role( 65 | "ack-access-entry-principal-role", 66 | "eks.amazonaws.com", 67 | ), 68 | ClusterVPC=VPC(name_prefix="cluster-vpc", num_public_subnet=num_public_subnet, num_private_subnet=2), 69 | AdoptionCluster=Cluster(name_prefix="adoption-cluster", num_managed_nodes=1) 70 | ) 71 | 72 | try: 73 | resources.bootstrap() 74 | except BootstrapFailureException as ex: 75 | exit(254) 76 | 77 | return resources 78 | 79 | if __name__ == "__main__": 80 | config = service_bootstrap() 81 | # Write config to current directory by default 82 | config.serialize(bootstrap_directory) 83 | -------------------------------------------------------------------------------- /pkg/resource/addon/resource.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | // Code generated by ack-generate. DO NOT EDIT. 15 | 16 | package addon 17 | 18 | import ( 19 | "fmt" 20 | 21 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 22 | ackerrors "github.com/aws-controllers-k8s/runtime/pkg/errors" 23 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 24 | "github.com/aws/aws-sdk-go-v2/aws" 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | rtclient "sigs.k8s.io/controller-runtime/pkg/client" 27 | 28 | svcapitypes "github.com/aws-controllers-k8s/eks-controller/apis/v1alpha1" 29 | ) 30 | 31 | // Hack to avoid import errors during build... 32 | var ( 33 | _ = &ackerrors.MissingNameIdentifier 34 | ) 35 | 36 | // resource implements the `aws-controller-k8s/runtime/pkg/types.AWSResource` 37 | // interface 38 | type resource struct { 39 | // The Kubernetes-native CR representing the resource 40 | ko *svcapitypes.Addon 41 | } 42 | 43 | // Identifiers returns an AWSResourceIdentifiers object containing various 44 | // identifying information, including the AWS account ID that owns the 45 | // resource, the resource's AWS Resource Name (ARN) 46 | func (r *resource) Identifiers() acktypes.AWSResourceIdentifiers { 47 | return &resourceIdentifiers{r.ko.Status.ACKResourceMetadata} 48 | } 49 | 50 | // IsBeingDeleted returns true if the Kubernetes resource has a non-zero 51 | // deletion timestamp 52 | func (r *resource) IsBeingDeleted() bool { 53 | return !r.ko.DeletionTimestamp.IsZero() 54 | } 55 | 56 | // RuntimeObject returns the Kubernetes apimachinery/runtime representation of 57 | // the AWSResource 58 | func (r *resource) RuntimeObject() rtclient.Object { 59 | return r.ko 60 | } 61 | 62 | // MetaObject returns the Kubernetes apimachinery/apis/meta/v1.Object 63 | // representation of the AWSResource 64 | func (r *resource) MetaObject() metav1.Object { 65 | return r.ko.GetObjectMeta() 66 | } 67 | 68 | // Conditions returns the ACK Conditions collection for the AWSResource 69 | func (r *resource) Conditions() []*ackv1alpha1.Condition { 70 | return r.ko.Status.Conditions 71 | } 72 | 73 | // ReplaceConditions sets the Conditions status field for the resource 74 | func (r *resource) ReplaceConditions(conditions []*ackv1alpha1.Condition) { 75 | r.ko.Status.Conditions = conditions 76 | } 77 | 78 | // SetObjectMeta sets the ObjectMeta field for the resource 79 | func (r *resource) SetObjectMeta(meta metav1.ObjectMeta) { 80 | r.ko.ObjectMeta = meta 81 | } 82 | 83 | // SetStatus will set the Status field for the resource 84 | func (r *resource) SetStatus(desired acktypes.AWSResource) { 85 | r.ko.Status = desired.(*resource).ko.Status 86 | } 87 | 88 | // SetIdentifiers sets the Spec or Status field that is referenced as the unique 89 | // resource identifier 90 | func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error { 91 | if identifier.NameOrID == "" { 92 | return ackerrors.MissingNameIdentifier 93 | } 94 | r.ko.Spec.Name = &identifier.NameOrID 95 | 96 | f1, f1ok := identifier.AdditionalKeys["clusterName"] 97 | if f1ok { 98 | r.ko.Spec.ClusterName = aws.String(f1) 99 | } 100 | 101 | return nil 102 | } 103 | 104 | // PopulateResourceFromAnnotation populates the fields passed from adoption annotation 105 | func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { 106 | f0, ok := fields["name"] 107 | if !ok { 108 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: name")) 109 | } 110 | r.ko.Spec.Name = &f0 111 | f1, ok := fields["clusterName"] 112 | if !ok { 113 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: clusterName")) 114 | } 115 | r.ko.Spec.ClusterName = &f1 116 | 117 | return nil 118 | } 119 | 120 | // DeepCopy will return a copy of the resource 121 | func (r *resource) DeepCopy() acktypes.AWSResource { 122 | koCopy := r.ko.DeepCopy() 123 | return &resource{koCopy} 124 | } 125 | -------------------------------------------------------------------------------- /helm/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* The name of the application this chart installs */}} 2 | {{- define "ack-eks-controller.app.name" -}} 3 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 4 | {{- end -}} 5 | 6 | {{/* 7 | Create a default fully qualified app name. 8 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 9 | If release name contains chart name it will be used as a full name. 10 | */}} 11 | {{- define "ack-eks-controller.app.fullname" -}} 12 | {{- if .Values.fullnameOverride -}} 13 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 14 | {{- else -}} 15 | {{- $name := default .Chart.Name .Values.nameOverride -}} 16 | {{- if contains $name .Release.Name -}} 17 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 18 | {{- else -}} 19 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 20 | {{- end -}} 21 | {{- end -}} 22 | {{- end -}} 23 | 24 | {{/* The name and version as used by the chart label */}} 25 | {{- define "ack-eks-controller.chart.name-version" -}} 26 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 27 | {{- end -}} 28 | 29 | {{/* The name of the service account to use */}} 30 | {{- define "ack-eks-controller.service-account.name" -}} 31 | {{ default "default" .Values.serviceAccount.name }} 32 | {{- end -}} 33 | 34 | {{- define "ack-eks-controller.watch-namespace" -}} 35 | {{- if eq .Values.installScope "namespace" -}} 36 | {{ .Values.watchNamespace | default .Release.Namespace }} 37 | {{- end -}} 38 | {{- end -}} 39 | 40 | {{/* The mount path for the shared credentials file */}} 41 | {{- define "ack-eks-controller.aws.credentials.secret_mount_path" -}} 42 | {{- "/var/run/secrets/aws" -}} 43 | {{- end -}} 44 | 45 | {{/* The path the shared credentials file is mounted */}} 46 | {{- define "ack-eks-controller.aws.credentials.path" -}} 47 | {{ $secret_mount_path := include "ack-eks-controller.aws.credentials.secret_mount_path" . }} 48 | {{- printf "%s/%s" $secret_mount_path .Values.aws.credentials.secretKey -}} 49 | {{- end -}} 50 | 51 | {{/* The rules a of ClusterRole or Role */}} 52 | {{- define "ack-eks-controller.rbac-rules" -}} 53 | rules: 54 | - apiGroups: 55 | - "" 56 | resources: 57 | - configmaps 58 | - secrets 59 | verbs: 60 | - get 61 | - list 62 | - patch 63 | - watch 64 | - apiGroups: 65 | - "" 66 | resources: 67 | - namespaces 68 | verbs: 69 | - get 70 | - list 71 | - watch 72 | - apiGroups: 73 | - ec2.services.k8s.aws 74 | resources: 75 | - securitygroups 76 | - securitygroups/status 77 | - subnets 78 | - subnets/status 79 | verbs: 80 | - get 81 | - list 82 | - apiGroups: 83 | - eks.services.k8s.aws 84 | resources: 85 | - accessentries 86 | - addons 87 | - capabilities 88 | - clusters 89 | - fargateprofiles 90 | - identityproviderconfigs 91 | - nodegroups 92 | - podidentityassociations 93 | verbs: 94 | - create 95 | - delete 96 | - get 97 | - list 98 | - patch 99 | - update 100 | - watch 101 | - apiGroups: 102 | - eks.services.k8s.aws 103 | resources: 104 | - accessentries/status 105 | - addons/status 106 | - capabilities/status 107 | - clusters/status 108 | - fargateprofiles/status 109 | - identityproviderconfigs/status 110 | - nodegroups/status 111 | - podidentityassociations/status 112 | verbs: 113 | - get 114 | - patch 115 | - update 116 | - apiGroups: 117 | - iam.services.k8s.aws 118 | resources: 119 | - roles 120 | - roles/status 121 | verbs: 122 | - get 123 | - list 124 | - apiGroups: 125 | - kms.services.k8s.aws 126 | resources: 127 | - keys 128 | - keys/status 129 | verbs: 130 | - get 131 | - list 132 | - apiGroups: 133 | - services.k8s.aws 134 | resources: 135 | - fieldexports 136 | - iamroleselectors 137 | verbs: 138 | - create 139 | - delete 140 | - get 141 | - list 142 | - patch 143 | - update 144 | - watch 145 | - apiGroups: 146 | - services.k8s.aws 147 | resources: 148 | - fieldexports/status 149 | - iamroleselectors/status 150 | verbs: 151 | - get 152 | - patch 153 | - update 154 | {{- end }} 155 | 156 | {{/* Convert k/v map to string like: "key1=value1,key2=value2,..." */}} 157 | {{- define "ack-eks-controller.feature-gates" -}} 158 | {{- $list := list -}} 159 | {{- range $k, $v := .Values.featureGates -}} 160 | {{- $list = append $list (printf "%s=%s" $k ( $v | toString)) -}} 161 | {{- end -}} 162 | {{ join "," $list }} 163 | {{- end -}} 164 | --------------------------------------------------------------------------------