diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index 79a6a45..36ddc2b 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,8 +1,8 @@ ack_generate_info: - build_date: "2024-10-10T04:09:12Z" - build_hash: 36c2d234498c2bc4f60773ab8df632af4067f43b + build_date: "2024-12-04T21:05:49Z" + build_hash: 5b95c1667a03835266df2d3f598718dd164184af go_version: go1.23.2 - version: v0.39.1 + version: v0.39.1-8-g5b95c16 api_directory_checksum: 761a2c708651b0273bf39d98dddaf029de23d337 api_version: v1alpha1 aws_sdk_go_version: v1.49.0 diff --git a/config/controller/deployment.yaml b/config/controller/deployment.yaml index e518f04..f571c49 100644 --- a/config/controller/deployment.yaml +++ b/config/controller/deployment.yaml @@ -41,6 +41,8 @@ spec: - "$(LEADER_ELECTION_NAMESPACE)" - --reconcile-default-max-concurrent-syncs - "$(RECONCILE_DEFAULT_MAX_CONCURRENT_SYNCS)" + - --feature-gates + - "$(FEATURE_GATES)" image: controller:latest name: controller ports: @@ -76,6 +78,8 @@ spec: value: "ack-system" - name: "RECONCILE_DEFAULT_MAX_CONCURRENT_SYNCS" value: "1" + - name: "FEATURE_GATES" + value: "" securityContext: allowPrivilegeEscalation: false privileged: false diff --git a/config/controller/kustomization.yaml b/config/controller/kustomization.yaml index b22900c..5c71796 100644 --- a/config/controller/kustomization.yaml +++ b/config/controller/kustomization.yaml @@ -6,4 +6,4 @@ kind: Kustomization images: - name: controller newName: public.ecr.aws/aws-controllers-k8s/iam-controller - newTag: 1.3.13 + newTag: 1.3.9 diff --git a/go.mod b/go.mod index 84a1ec0..fdfe6fd 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22.0 toolchain go1.22.5 require ( - github.com/aws-controllers-k8s/runtime v0.39.0 + github.com/aws-controllers-k8s/runtime v0.39.1-0.20241202082353-a6b0014a8130 github.com/aws/aws-sdk-go v1.49.0 github.com/go-logr/logr v1.4.2 github.com/micahhausler/aws-iam-policy v0.4.2 diff --git a/go.sum b/go.sum index f05ec07..d5280d2 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/a-hilaly/aws-iam-policy v0.0.0-20231121054900-2c56e839ca53 h1:2uNM0nR github.com/a-hilaly/aws-iam-policy v0.0.0-20231121054900-2c56e839ca53/go.mod h1:Ojgst9ZFn+VEEJpqtuw/LxVGqEf2+hwWBlkYWvF/XWM= github.com/aws-controllers-k8s/runtime v0.39.0 h1:IgOXluSzvb4UcDr9eU7SPw5MJnL7kt5R6DuF5Qu9zVQ= github.com/aws-controllers-k8s/runtime v0.39.0/go.mod h1:G07g26y1cxyZO6Ngp+LwXf03CqFyLNL7os4Py4IdyGY= +github.com/aws-controllers-k8s/runtime v0.39.1-0.20241202082353-a6b0014a8130 h1:EoXYRrpBX2hi5B1IawKr2LJTsVsreHsJdxULLlMNO9U= +github.com/aws-controllers-k8s/runtime v0.39.1-0.20241202082353-a6b0014a8130/go.mod h1:G07g26y1cxyZO6Ngp+LwXf03CqFyLNL7os4Py4IdyGY= github.com/aws/aws-sdk-go v1.49.0 h1:g9BkW1fo9GqKfwg2+zCD+TW/D36Ux+vtfJ8guF4AYmY= github.com/aws/aws-sdk-go v1.49.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 041245c..b0638d7 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 name: iam-chart description: A Helm chart for the ACK service controller for AWS Identity & Access Management (IAM) -version: 1.3.13 -appVersion: 1.3.13 +version: 1.3.9 +appVersion: 1.3.9 home: https://github.com/aws-controllers-k8s/iam-controller icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png sources: diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt index c8444c5..9f11763 100644 --- a/helm/templates/NOTES.txt +++ b/helm/templates/NOTES.txt @@ -1,5 +1,5 @@ {{ .Chart.Name }} has been installed. -This chart deploys "public.ecr.aws/aws-controllers-k8s/iam-controller:1.3.13". +This chart deploys "public.ecr.aws/aws-controllers-k8s/iam-controller:1.3.9". Check its status by running: kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/instance={{ .Release.Name }}" diff --git a/helm/templates/caches-role-binding.yaml b/helm/templates/caches-role-binding.yaml index fdff62f..a047f3f 100644 --- a/helm/templates/caches-role-binding.yaml +++ b/helm/templates/caches-role-binding.yaml @@ -8,7 +8,7 @@ roleRef: name: ack-namespaces-cache-iam-controller subjects: - kind: ServiceAccount - name: ack-iam-controller + name: {{ include "ack-iam-controller.service-account.name" . }} namespace: {{ .Release.Namespace }} --- apiVersion: rbac.authorization.k8s.io/v1 @@ -22,5 +22,5 @@ roleRef: name: ack-configmaps-cache-iam-controller subjects: - kind: ServiceAccount - name: ack-iam-controller - namespace: {{ .Release.Namespace }} \ No newline at end of file + name: {{ include "ack-iam-controller.service-account.name" . }} + namespace: {{ .Release.Namespace }} diff --git a/helm/values.yaml b/helm/values.yaml index 7bfacbb..50a0551 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -4,7 +4,7 @@ image: repository: public.ecr.aws/aws-controllers-k8s/iam-controller - tag: 1.3.13 + tag: 1.3.9 pullPolicy: IfNotPresent pullSecrets: [] @@ -163,4 +163,6 @@ featureGates: # Enables the Team level granularity for CARM. See https://github.com/aws-controllers-k8s/community/issues/2031 TeamLevelCARM: false # Enable ReadOnlyResources feature/annotation. - ReadOnlyResources: false \ No newline at end of file + ReadOnlyResources: false + # Enable ResourceAdoption feature/annotation. + ResourceAdoption: false \ No newline at end of file diff --git a/pkg/resource/group/descriptor.go b/pkg/resource/group/descriptor.go index 9688bd3..3a00742 100644 --- a/pkg/resource/group/descriptor.go +++ b/pkg/resource/group/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/Group" + FinalizerString = "finalizers.iam.services.k8s.aws/Group" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/group/resource.go b/pkg/resource/group/resource.go index 7c88620..927bdeb 100644 --- a/pkg/resource/group/resource.go +++ b/pkg/resource/group/resource.go @@ -93,6 +93,17 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["name"] + if !ok { + return ackerrors.MissingNameIdentifier + } + r.ko.Spec.Name = &tmp + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/pkg/resource/instance_profile/descriptor.go b/pkg/resource/instance_profile/descriptor.go index 96586cd..d139981 100644 --- a/pkg/resource/instance_profile/descriptor.go +++ b/pkg/resource/instance_profile/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/InstanceProfile" + FinalizerString = "finalizers.iam.services.k8s.aws/InstanceProfile" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/instance_profile/resource.go b/pkg/resource/instance_profile/resource.go index 3754bb8..f53a9e4 100644 --- a/pkg/resource/instance_profile/resource.go +++ b/pkg/resource/instance_profile/resource.go @@ -93,6 +93,17 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["name"] + if !ok { + return ackerrors.MissingNameIdentifier + } + r.ko.Spec.Name = &tmp + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/pkg/resource/open_id_connect_provider/descriptor.go b/pkg/resource/open_id_connect_provider/descriptor.go index 809d1e5..3c4171c 100644 --- a/pkg/resource/open_id_connect_provider/descriptor.go +++ b/pkg/resource/open_id_connect_provider/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/OpenIDConnectProvider" + FinalizerString = "finalizers.iam.services.k8s.aws/OpenIDConnectProvider" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/open_id_connect_provider/resource.go b/pkg/resource/open_id_connect_provider/resource.go index 77d00f6..8d9e1c5 100644 --- a/pkg/resource/open_id_connect_provider/resource.go +++ b/pkg/resource/open_id_connect_provider/resource.go @@ -93,6 +93,22 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["arn"] + if !ok { + return ackerrors.MissingNameIdentifier + } + + if r.ko.Status.ACKResourceMetadata == nil { + r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{} + } + arn := ackv1alpha1.AWSResourceName(tmp) + r.ko.Status.ACKResourceMetadata.ARN = &arn + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/pkg/resource/policy/descriptor.go b/pkg/resource/policy/descriptor.go index 58788a0..dde2c5c 100644 --- a/pkg/resource/policy/descriptor.go +++ b/pkg/resource/policy/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/Policy" + FinalizerString = "finalizers.iam.services.k8s.aws/Policy" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/policy/resource.go b/pkg/resource/policy/resource.go index 9d673f7..ea92706 100644 --- a/pkg/resource/policy/resource.go +++ b/pkg/resource/policy/resource.go @@ -93,6 +93,22 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["arn"] + if !ok { + return ackerrors.MissingNameIdentifier + } + + if r.ko.Status.ACKResourceMetadata == nil { + r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{} + } + arn := ackv1alpha1.AWSResourceName(tmp) + r.ko.Status.ACKResourceMetadata.ARN = &arn + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/pkg/resource/role/descriptor.go b/pkg/resource/role/descriptor.go index 4c56959..8af22ea 100644 --- a/pkg/resource/role/descriptor.go +++ b/pkg/resource/role/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/Role" + FinalizerString = "finalizers.iam.services.k8s.aws/Role" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/role/resource.go b/pkg/resource/role/resource.go index 3775b5c..2c02e95 100644 --- a/pkg/resource/role/resource.go +++ b/pkg/resource/role/resource.go @@ -93,6 +93,17 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["name"] + if !ok { + return ackerrors.MissingNameIdentifier + } + r.ko.Spec.Name = &tmp + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/pkg/resource/user/descriptor.go b/pkg/resource/user/descriptor.go index 19c1579..c0910b4 100644 --- a/pkg/resource/user/descriptor.go +++ b/pkg/resource/user/descriptor.go @@ -28,7 +28,7 @@ import ( ) const ( - finalizerString = "finalizers.iam.services.k8s.aws/User" + FinalizerString = "finalizers.iam.services.k8s.aws/User" ) var ( @@ -88,8 +88,8 @@ func (d *resourceDescriptor) IsManaged( // https://github.com/kubernetes-sigs/controller-runtime/issues/994 is // fixed. This should be able to be: // - // return k8sctrlutil.ContainsFinalizer(obj, finalizerString) - return containsFinalizer(obj, finalizerString) + // return k8sctrlutil.ContainsFinalizer(obj, FinalizerString) + return containsFinalizer(obj, FinalizerString) } // Remove once https://github.com/kubernetes-sigs/controller-runtime/issues/994 @@ -118,7 +118,7 @@ func (d *resourceDescriptor) MarkManaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.AddFinalizer(obj, finalizerString) + k8sctrlutil.AddFinalizer(obj, FinalizerString) } // MarkUnmanaged removes the supplied resource from management by ACK. What @@ -133,7 +133,7 @@ func (d *resourceDescriptor) MarkUnmanaged( // Should not happen. If it does, there is a bug in the code panic("nil RuntimeMetaObject in AWSResource") } - k8sctrlutil.RemoveFinalizer(obj, finalizerString) + k8sctrlutil.RemoveFinalizer(obj, FinalizerString) } // MarkAdopted places descriptors on the custom resource that indicate the diff --git a/pkg/resource/user/resource.go b/pkg/resource/user/resource.go index ee6bc4e..9874d54 100644 --- a/pkg/resource/user/resource.go +++ b/pkg/resource/user/resource.go @@ -93,6 +93,17 @@ func (r *resource) SetIdentifiers(identifier *ackv1alpha1.AWSIdentifiers) error return nil } +// PopulateResourceFromAnnotation populates the fields passed from adoption annotation +func (r *resource) PopulateResourceFromAnnotation(fields map[string]string) error { + tmp, ok := fields["name"] + if !ok { + return ackerrors.MissingNameIdentifier + } + r.ko.Spec.Name = &tmp + + return nil +} + // DeepCopy will return a copy of the resource func (r *resource) DeepCopy() acktypes.AWSResource { koCopy := r.ko.DeepCopy() diff --git a/test/e2e/bootstrap_resources.py b/test/e2e/bootstrap_resources.py index 450a769..f7263ab 100644 --- a/test/e2e/bootstrap_resources.py +++ b/test/e2e/bootstrap_resources.py @@ -17,12 +17,13 @@ from dataclasses import dataclass from acktest.bootstrapping import Resources +from acktest.bootstrapping.iam import UserPolicies, Role from e2e import bootstrap_directory @dataclass class BootstrapResources(Resources): - pass - + AdoptedPolicy: UserPolicies + AdoptedRole: Role _bootstrap_resources = None def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.pkl") -> BootstrapResources: diff --git a/test/e2e/resources/policy_adoption.yaml b/test/e2e/resources/policy_adoption.yaml new file mode 100644 index 0000000..6ec376f --- /dev/null +++ b/test/e2e/resources/policy_adoption.yaml @@ -0,0 +1,8 @@ +apiVersion: iam.services.k8s.aws/v1alpha1 +kind: Policy +metadata: + name: $POLICY_ADOPTION_NAME + annotations: + services.k8s.aws/adoption-policy: $ADOPTION_POLICY + services.k8s.aws/adoption-fields: "$ADOPTION_FIELDS" + services.k8s.aws/deletion-policy: retain diff --git a/test/e2e/resources/role_adoption.yaml b/test/e2e/resources/role_adoption.yaml new file mode 100644 index 0000000..c5d2ce8 --- /dev/null +++ b/test/e2e/resources/role_adoption.yaml @@ -0,0 +1,8 @@ +apiVersion: iam.services.k8s.aws/v1alpha1 +kind: Role +metadata: + name: $ROLE_ADOPTION_NAME + annotations: + services.k8s.aws/adoption-policy: $ADOPTION_POLICY + services.k8s.aws/adoption-fields: "$ADOPTION_FIELDS" + services.k8s.aws/deletion-policy: retain diff --git a/test/e2e/service_bootstrap.py b/test/e2e/service_bootstrap.py index 015d98c..6886726 100644 --- a/test/e2e/service_bootstrap.py +++ b/test/e2e/service_bootstrap.py @@ -15,16 +15,31 @@ """ import logging +import json from acktest.bootstrapping import Resources, BootstrapFailureException -from acktest.bootstrapping.iam import Role -from acktest.bootstrapping.vpc import VPC +from acktest.bootstrapping.iam import UserPolicies, Role from e2e import bootstrap_directory from e2e.bootstrap_resources import BootstrapResources def service_bootstrap() -> Resources: logging.getLogger().setLevel(logging.INFO) - resources = BootstrapResources() + sample_policy = json.dumps({ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:ListBucket", + ], + "Resource": "*" + } + ] + }) + resources = BootstrapResources( + AdoptedPolicy=UserPolicies("adopted-policies", policy_documents=[sample_policy]), + AdoptedRole=Role("adopted-role", "eks.amazonaws.com", managed_policies=["arn:aws:iam::aws:policy/AmazonSQSFullAccess", "arn:aws:iam::aws:policy/AmazonEC2FullAccess"]) + ) try: resources.bootstrap() diff --git a/test/e2e/tests/test_policy.py b/test/e2e/tests/test_policy.py index ed8637a..4607989 100644 --- a/test/e2e/tests/test_policy.py +++ b/test/e2e/tests/test_policy.py @@ -22,6 +22,7 @@ from acktest.k8s import resource as k8s from acktest.resources import random_suffix_name from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_resource +from e2e.bootstrap_resources import get_bootstrap_resources from e2e.common.types import POLICY_RESOURCE_PLURAL from e2e.replacement_values import REPLACEMENT_VALUES from e2e import policy @@ -32,6 +33,7 @@ # NOTE(jaypipes): I've seen Tagris take nearly 20 seconds to return updated tag # information on a resource. MODIFY_WAIT_AFTER_SECONDS = 20 +CREATE_WAIT_AFTER_SECONDS = 10 @pytest.fixture(scope="module") @@ -77,6 +79,33 @@ def simple_policy(): policy.wait_until_deleted(policy_arn) +@pytest.fixture(scope="module") +def adopt_policy(): + resource_arn = get_bootstrap_resources().AdoptedPolicy.arns[0] + resource_name = random_suffix_name("adopted-policy", 24) + replacements = REPLACEMENT_VALUES.copy() + replacements["POLICY_ADOPTION_NAME"] = resource_name + replacements["ADOPTION_POLICY"] = "adopt" + replacements["ADOPTION_FIELDS"] = f"{{\\\"arn\\\": \\\"{resource_arn}\\\"}}" + + resource_data = load_resource( + "policy_adoption", + additional_replacements=replacements, + ) + + ref = k8s.CustomResourceReference( + CRD_GROUP, CRD_VERSION, POLICY_RESOURCE_PLURAL, + resource_name, namespace="default", + ) + k8s.create_custom_resource(ref, resource_data) + + time.sleep(CREATE_WAIT_AFTER_SECONDS) + cr = k8s.wait_resource_consumed_by_controller(ref) + assert cr is not None + + yield (ref, cr, resource_arn) + + @service_marker @pytest.mark.canary @@ -197,3 +226,39 @@ def test_crud(self, simple_policy): after_pv = policy.get_version(policy_arn, "v2") after_doc = after_pv["Document"] assert after_doc == new_policy_doc + + def test_policy_adopt_update(self, adopt_policy): + ref, cr, policy_arn = adopt_policy + + condition.assert_synced(ref) + + assert cr is not None + assert 'status' in cr + assert 'defaultVersionID' in cr['status'] + assert cr['status']['defaultVersionID'] == 'v1' + + new_policy_doc = { + "Version":"2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*", + }, + ], + } + + updates = { + "spec": {"policyDocument": json.dumps(new_policy_doc)}, + } + k8s.patch_custom_resource(ref, updates) + time.sleep(MODIFY_WAIT_AFTER_SECONDS) + + cr = k8s.get_resource(ref) + assert cr is not None + assert 'status' in cr + assert 'defaultVersionID' in cr['status'] + assert cr['status']['defaultVersionID'] == 'v2' + + policy_doc = policy.get_version(policy_arn, "v2")["Document"] + assert policy_doc == new_policy_doc diff --git a/test/e2e/tests/test_role.py b/test/e2e/tests/test_role.py index 8ec8626..e2bc49f 100644 --- a/test/e2e/tests/test_role.py +++ b/test/e2e/tests/test_role.py @@ -24,6 +24,7 @@ from acktest.resources import random_suffix_name from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_resource from e2e.common.types import ROLE_RESOURCE_PLURAL +from e2e.bootstrap_resources import get_bootstrap_resources from e2e.replacement_values import REPLACEMENT_VALUES from e2e import role from e2e import tag @@ -71,6 +72,31 @@ def simple_role(): role.wait_until_deleted(role_name) +@pytest.fixture(scope="module") +def adopt_role(): + resource_name = get_bootstrap_resources().AdoptedRole.name + replacements = REPLACEMENT_VALUES.copy() + replacements['ROLE_ADOPTION_NAME'] = resource_name + replacements['ADOPTION_POLICY'] = "adopt" + replacements['ADOPTION_FIELDS'] = f"{{\\\"name\\\": \\\"{resource_name}\\\"}}" + + resource_data = load_resource( + "role_adoption", + additional_replacements=replacements, + ) + + ref = k8s.CustomResourceReference( + CRD_GROUP, CRD_VERSION, ROLE_RESOURCE_PLURAL, + resource_name, namespace="default", + ) + k8s.create_custom_resource(ref, resource_data) + + time.sleep(CHECK_STATUS_WAIT_SECONDS) + cr = k8s.wait_resource_consumed_by_controller(ref) + assert cr is not None + + yield (ref, cr) + @service_marker @pytest.mark.canary @@ -348,3 +374,17 @@ def test_crud(self, simple_role): # make sure the resource is not in an "update infinite loop" condition.assert_synced(ref) + + + def test_role_adopt(self, adopt_role): + ref, cr = adopt_role + + condition.assert_synced(ref) + + assert cr is not None + assert 'status' in cr + assert 'spec' in cr + assert 'policies' in cr['spec'] + + user_policies = get_bootstrap_resources().AdoptedRole.managed_policies + assert set(cr['spec']['policies']) == set(user_policies)