├── test └── e2e │ ├── .gitignore │ ├── requirements.txt │ ├── resources │ ├── snapshot_kms.yaml │ ├── usergroup.yaml │ ├── user_nopass.yaml │ ├── serverless_cache_snapshot_basic.yaml │ ├── user_password.yaml │ ├── serverless_cache_basic.yaml │ ├── cache_cluster_simple.yaml │ ├── replicationgroup_create_delete.yaml │ ├── replicationgroup_cmd_fromsnapshot.yaml │ ├── replicationgroup_primary_cluster.yaml │ ├── replicationgroup_fault_tolerance.yaml │ └── replicationgroup_update.yaml │ ├── tests │ ├── __init__.py │ ├── test_usergroup.py │ └── test_snapshot.py │ ├── replacement_values.py │ ├── __init__.py │ ├── conftest.py │ └── bootstrap_resources.py ├── NOTICE ├── config ├── iam │ ├── recommended-policy-arn │ ├── KMS-policy-template.json │ └── README.md ├── overlays │ └── namespaced │ │ ├── role.json │ │ ├── role-binding.json │ │ └── kustomization.yaml ├── 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 ├── crd │ ├── common │ │ ├── kustomization.yaml │ │ └── bases │ │ │ └── services.k8s.aws_iamroleselectors.yaml │ └── kustomization.yaml ├── controller │ ├── kustomization.yaml │ ├── service.yaml │ └── deployment.yaml └── default │ └── kustomization.yaml ├── OWNERS ├── templates └── hooks │ ├── replication_group │ ├── sdk_file_end_set_output_post_populate.go.tpl │ ├── sdk_update_pre_build_request.go.tpl │ ├── sdk_delete_post_request.go.tpl │ ├── sdk_file_end.go.tpl │ ├── sdk_delete_pre_build_request.go.tpl │ ├── sdk_update_post_build_request.go.tpl │ └── sdk_read_many_post_set_output.go.tpl │ ├── cache_cluster │ ├── sdk_read_many_post_build_request.go.tpl │ ├── sdk_update_post_build_request.go.tpl │ ├── sdk_create_post_set_output.go.tpl │ ├── sdk_update_pre_build_request.go.tpl │ ├── sdk_update_post_set_output.go.tpl │ ├── sdk_read_many_post_set_output.go.tpl │ └── sdk_delete_pre_build_request.go.tpl │ ├── serverless_cache_snapshot │ ├── sdk_create_post_set_output.go.tpl │ └── sdk_read_many_post_set_output.go.tpl │ ├── cache_subnet_group │ └── sdk_read_many_post_set_output.go.tpl │ └── serverless_cache │ └── sdk_read_many_post_set_output.go.tpl ├── .gitignore ├── apis └── v1alpha1 │ ├── doc.go │ ├── ack-generate-metadata.yaml │ ├── annotations.go │ ├── groupversion_info.go │ ├── user_group.go │ └── cache_subnet_group.go ├── .github └── workflows │ ├── postsubmit.yaml │ └── create-release.yml ├── metadata.yaml ├── CODE_OF_CONDUCT.md ├── OWNERS_ALIASES ├── 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 └── crds │ └── services.k8s.aws_iamroleselectors.yaml ├── pkg ├── version │ └── version.go ├── common │ └── delta.go ├── resource │ ├── user │ │ ├── identifiers.go │ │ ├── references.go │ │ ├── manager_factory.go │ │ ├── delta.go │ │ └── resource.go │ ├── snapshot │ │ ├── identifiers.go │ │ ├── references.go │ │ ├── manager_factory.go │ │ ├── delta.go │ │ └── resource.go │ ├── user_group │ │ ├── identifiers.go │ │ ├── references.go │ │ ├── delta.go │ │ ├── manager_factory.go │ │ └── resource.go │ ├── cache_cluster │ │ ├── identifiers.go │ │ ├── delta_util.go │ │ ├── manager_factory.go │ │ └── resource.go │ ├── serverless_cache │ │ ├── identifiers.go │ │ └── manager_factory.go │ ├── cache_subnet_group │ │ ├── identifiers.go │ │ ├── delta.go │ │ ├── hooks.go │ │ └── manager_factory.go │ ├── replication_group │ │ ├── identifiers.go │ │ ├── manager_factory.go │ │ └── resource.go │ ├── cache_parameter_group │ │ ├── identifiers.go │ │ ├── references.go │ │ ├── delta.go │ │ └── manager_factory.go │ ├── serverless_cache_snapshot │ │ ├── identifiers.go │ │ ├── delta.go │ │ ├── manager_factory.go │ │ └── hooks.go │ └── registry.go └── util │ └── engine_version.go ├── Makefile ├── README.md ├── GOVERNANCE.md ├── olm └── olmconfig.yaml ├── CONTRIBUTING.md └── go.local.mod /test/e2e/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.py[cod] 3 | **/bootstrap.yaml -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /config/iam/recommended-policy-arn: -------------------------------------------------------------------------------- 1 | arn:aws:iam::aws:policy/AmazonElastiCacheFullAccess 2 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - core-ack-team -------------------------------------------------------------------------------- /templates/hooks/replication_group/sdk_file_end_set_output_post_populate.go.tpl: -------------------------------------------------------------------------------- 1 | rm.customSetOutput(ctx, *obj, ko) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~ 4 | .idea 5 | go.local.sum 6 | coverage.out 7 | /docs/site 8 | bin 9 | build 10 | -------------------------------------------------------------------------------- /test/e2e/requirements.txt: -------------------------------------------------------------------------------- 1 | acktest @ git+https://github.com/aws-controllers-k8s/test-infra.git@5a09bbdb961ea14a65b15b63769134125023ac61 -------------------------------------------------------------------------------- /config/overlays/namespaced/role.json: -------------------------------------------------------------------------------- 1 | [{"op": "replace", "path": "/kind", "value": "Role"}, 2 | {"op": "add", "path": "/metadata/namespace", "value": "ack-system"}] -------------------------------------------------------------------------------- /config/rbac/service-account.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: ack-elasticache-controller 6 | namespace: ack-system 7 | -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_read_many_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | // Include cache node info to get endpoint details for clusters 2 | input.ShowCacheNodeInfo = aws.Bool(true) -------------------------------------------------------------------------------- /apis/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // +k8s:deepcopy-gen=package 2 | // Package v1alpha1 is the v1alpha1 version of the elasticache.services.k8s.aws API. 3 | // +groupName=elasticache.services.k8s.aws 4 | package v1alpha1 5 | -------------------------------------------------------------------------------- /templates/hooks/replication_group/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if delta.DifferentAt("Spec.Tags") { 2 | if err = rm.syncTags(ctx, desired, latest); err != nil { 3 | return nil, err 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_update_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if err := rm.updateCacheClusterPayload(input, desired, latest, delta); err != nil { 2 | return nil, ackerr.NewTerminalError(err) 3 | } 4 | -------------------------------------------------------------------------------- /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"}] -------------------------------------------------------------------------------- /test/e2e/resources/snapshot_kms.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: Snapshot 3 | metadata: 4 | name: $SNAPSHOT_NAME 5 | spec: 6 | snapshotName: $SNAPSHOT_NAME 7 | cacheClusterID: $CC_ID 8 | kmsKeyID: $KMS_KEY_ID -------------------------------------------------------------------------------- /templates/hooks/serverless_cache_snapshot/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // If tags are specified, mark the resource as needing a sync 2 | if ko.Spec.Tags != nil { 3 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 4 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /test/e2e/resources/usergroup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: UserGroup 3 | metadata: 4 | name: $USER_GROUP_ID 5 | spec: 6 | engine: redis 7 | userGroupID: $USER_GROUP_ID 8 | userIDs: 9 | - default 10 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /test/e2e/resources/user_nopass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: User 3 | metadata: 4 | name: $USER_ID 5 | spec: 6 | accessString: $ACCESS_STRING 7 | engine: redis 8 | noPasswordRequired: true 9 | userID: $USER_ID 10 | userName: $USER_ID -------------------------------------------------------------------------------- /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/elasticache-controller 9 | newTag: 1.3.0 10 | -------------------------------------------------------------------------------- /metadata.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | full_name: "Amazon ElastiCache" 3 | short_name: "ElastiCache" 4 | link: "https://aws.amazon.com/elasticache/" 5 | documentation: "https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/WhatIs.html" 6 | api_versions: 7 | - api_version: v1alpha1 8 | status: available 9 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /templates/hooks/cache_subnet_group/sdk_read_many_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | 2 | subnets := make([]*string, 0, len(ko.Status.Subnets)) 3 | for _, subnetIdIter := range ko.Status.Subnets { 4 | if subnetIdIter.SubnetIdentifier != nil { 5 | subnets = append(subnets, subnetIdIter.SubnetIdentifier) 6 | } 7 | } 8 | ko.Spec.SubnetIDs = subnets 9 | -------------------------------------------------------------------------------- /test/e2e/resources/serverless_cache_snapshot_basic.yaml: -------------------------------------------------------------------------------- 1 | # Basic ServerlessCacheSnapshot for testing basic creation and deletion 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: ServerlessCacheSnapshot 4 | metadata: 5 | name: $SNAPSHOT_NAME 6 | spec: 7 | serverlessCacheSnapshotName: $SNAPSHOT_NAME 8 | serverlessCacheName: $SC_NAME -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_create_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if isCreating(&resource{ko}) { 2 | // Setting resource synced condition to false will trigger a requeue of 3 | // the resource. No need to return a requeue error here. 4 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 5 | return &resource{ko}, nil 6 | } 7 | -------------------------------------------------------------------------------- /config/controller/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: ack-elasticache-metrics-service 5 | namespace: ack-system 6 | spec: 7 | selector: 8 | app.kubernetes.io/name: ack-elasticache-controller 9 | ports: 10 | - name: metricsport 11 | port: 8080 12 | targetPort: http 13 | protocol: TCP 14 | type: ClusterIP 15 | -------------------------------------------------------------------------------- /config/rbac/cluster-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: ack-elasticache-controller-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: ack-elasticache-controller 9 | subjects: 10 | - kind: ServiceAccount 11 | name: ack-elasticache-controller 12 | namespace: ack-system 13 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /test/e2e/resources/user_password.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: User 3 | metadata: 4 | name: $USER_ID 5 | spec: 6 | accessString: $ACCESS_STRING 7 | engine: redis 8 | passwords: 9 | - namespace: default 10 | name: $NAME1 11 | key: $KEY1 12 | - namespace: default 13 | name: $NAME2 14 | key: $KEY2 15 | userID: $USER_ID 16 | userName: $USER_ID -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_update_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if delta.DifferentAt("Spec.Tags") { 2 | if err = rm.syncTags(ctx, desired, latest); err != nil { 3 | return nil, err 4 | } 5 | } else if !delta.DifferentExcept("Spec.Tags") { 6 | // If the only difference between the desired and latest is in the 7 | // Spec.Tags field, we can skip the ModifyCacheCluster call. 8 | return desired, nil 9 | } 10 | -------------------------------------------------------------------------------- /templates/hooks/serverless_cache/sdk_read_many_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // Get the ARN from the resource metadata 2 | if ko.Status.ACKResourceMetadata != nil && ko.Status.ACKResourceMetadata.ARN != nil { 3 | // Retrieve the tags for the resource 4 | resourceARN := string(*ko.Status.ACKResourceMetadata.ARN) 5 | tags, err := rm.getTags(ctx, resourceARN) 6 | if err == nil { 7 | ko.Spec.Tags = tags 8 | } 9 | } -------------------------------------------------------------------------------- /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-elasticache-controller 10 | - path: role-binding.json 11 | target: 12 | group: rbac.authorization.k8s.io 13 | version: v1 14 | kind: ClusterRoleBinding 15 | name: ack-elasticache-controller-rolebinding -------------------------------------------------------------------------------- /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: elasticache-leader-election-rolebinding 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: Role 10 | name: elasticache-leader-election-role 11 | subjects: 12 | - kind: ServiceAccount 13 | name: ack-elasticache-controller 14 | namespace: ack-system 15 | -------------------------------------------------------------------------------- /test/e2e/resources/serverless_cache_basic.yaml: -------------------------------------------------------------------------------- 1 | # Basic ServerlessCache for testing basic creation and deletion 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: ServerlessCache 4 | metadata: 5 | name: $SC_NAME 6 | spec: 7 | serverlessCacheName: $SC_NAME 8 | engine: $ENGINE 9 | majorEngineVersion: "$MAJOR_ENGINE_VERSION" 10 | cacheUsageLimits: 11 | eCPUPerSecond: 12 | minimum: $ECPU_MIN 13 | maximum: $ECPU_MAX -------------------------------------------------------------------------------- /test/e2e/resources/cache_cluster_simple.yaml: -------------------------------------------------------------------------------- 1 | # A simple CacheCluster manifest. 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: CacheCluster 4 | metadata: 5 | name: $CACHE_CLUSTER_ID 6 | spec: 7 | cacheClusterID: $CACHE_CLUSTER_ID 8 | cacheNodeType: cache.t3.micro 9 | numCacheNodes: 2 10 | engine: memcached 11 | autoMinorVersionUpgrade: false 12 | tags: 13 | - key: t1 14 | value: v1 15 | - key: t2 16 | value: v2 17 | -------------------------------------------------------------------------------- /test/e2e/resources/replicationgroup_create_delete.yaml: -------------------------------------------------------------------------------- 1 | # Basic CMD replication group for testing Update behavior 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: ReplicationGroup 4 | metadata: 5 | name: $RG_ID 6 | spec: 7 | cacheNodeType: cache.t3.micro 8 | engine: redis 9 | engineVersion: $ENGINE_VERSION 10 | numNodeGroups: $NUM_NODE_GROUPS 11 | replicasPerNodeGroup: $REPLICAS_PER_NODE_GROUP 12 | description: cluster-mode disabled RG 13 | replicationGroupID: $RG_ID -------------------------------------------------------------------------------- /config/rbac/leader-election-role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: elasticache-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 | -------------------------------------------------------------------------------- /apis/v1alpha1/ack-generate-metadata.yaml: -------------------------------------------------------------------------------- 1 | ack_generate_info: 2 | build_date: "2025-11-29T02:58:34Z" 3 | build_hash: 23c7074fa310ad1ccb38946775397c203b49f024 4 | go_version: go1.25.4 5 | version: v0.56.0 6 | api_directory_checksum: 65127f2f0a24a801fad4e043be37857f0e6bcfb9 7 | api_version: v1alpha1 8 | aws_sdk_go_version: v1.32.6 9 | generator_config_info: 10 | file_checksum: 64095ac8a26b456580bc303aceec26581b1b6f6a 11 | original_file_name: generator.yaml 12 | last_modification: 13 | reason: API generation 14 | -------------------------------------------------------------------------------- /test/e2e/resources/replicationgroup_cmd_fromsnapshot.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: ReplicationGroup 3 | metadata: 4 | name: $RG_ID 5 | spec: 6 | cacheNodeType: cache.t3.micro 7 | engine: redis 8 | description: test replication group for input field coverage 9 | replicationGroupID: $RG_ID 10 | snapshotName: $SNAPSHOT_NAME 11 | numNodeGroups: 1 12 | replicasPerNodeGroup: 2 13 | preferredCacheClusterAZs: 14 | - us-west-2a 15 | - us-west-2b 16 | - us-west-2c 17 | -------------------------------------------------------------------------------- /test/e2e/resources/replicationgroup_primary_cluster.yaml: -------------------------------------------------------------------------------- 1 | # CMD replication group manifest for specifying an existing node to use as primary 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: ReplicationGroup 4 | metadata: 5 | name: $RG_ID 6 | spec: 7 | # cache node type and engine cannot be used when specifying existing primary node, even if DNE 8 | numNodeGroups: 1 9 | replicasPerNodeGroup: 1 10 | description: cluster-mode disabled RG 11 | replicationGroupID: $RG_ID 12 | primaryClusterID: $PRIMARY_NODE -------------------------------------------------------------------------------- /test/e2e/resources/replicationgroup_fault_tolerance.yaml: -------------------------------------------------------------------------------- 1 | # CMD replication group for testing modification fault tolerance features (multi AZ, auto failover, primary promotion) 2 | apiVersion: elasticache.services.k8s.aws/v1alpha1 3 | kind: ReplicationGroup 4 | metadata: 5 | name: $RG_ID 6 | spec: 7 | automaticFailoverEnabled: $AF_ENABLED 8 | cacheNodeType: cache.t3.micro 9 | engine: redis 10 | multiAZEnabled: $MAZ_ENABLED 11 | numNodeGroups: 1 12 | replicasPerNodeGroup: 1 13 | description: description 14 | replicationGroupID: $RG_ID -------------------------------------------------------------------------------- /config/rbac/role-reader.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-elasticache-reader 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - elasticache.services.k8s.aws 11 | resources: 12 | - cacheclusters 13 | - cacheparametergroups 14 | - cachesubnetgroups 15 | - replicationgroups 16 | - serverlesscaches 17 | - serverlesscachesnapshots 18 | - snapshots 19 | - users 20 | - usergroups 21 | verbs: 22 | - get 23 | - list 24 | - watch 25 | -------------------------------------------------------------------------------- /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/serverless_cache_snapshot/sdk_read_many_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | // Only fetch tags if the snapshot is available 2 | // ListTagsForResource fails when snapshot is still creating 3 | if ko.Status.ACKResourceMetadata != nil && ko.Status.ACKResourceMetadata.ARN != nil && 4 | isServerlessCacheSnapshotAvailable(&resource{ko}) { 5 | resourceARN := (*string)(ko.Status.ACKResourceMetadata.ARN) 6 | tags, err := rm.getTags(ctx, *resourceARN) 7 | if err != nil { 8 | return nil, err 9 | } 10 | ko.Spec.Tags = tags 11 | } -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_update_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if pendingModifications := resp.CacheCluster.PendingModifiedValues; pendingModifications != nil { 2 | if pendingModifications.NumCacheNodes != nil { 3 | ko.Spec.NumCacheNodes = Int64OrNil(pendingModifications.NumCacheNodes) 4 | } 5 | if pendingModifications.CacheNodeType != nil { 6 | ko.Spec.CacheNodeType = pendingModifications.CacheNodeType 7 | } 8 | if pendingModifications.TransitEncryptionEnabled != nil { 9 | ko.Spec.TransitEncryptionEnabled = pendingModifications.TransitEncryptionEnabled 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /test/e2e/resources/replicationgroup_update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticache.services.k8s.aws/v1alpha1 2 | kind: ReplicationGroup 3 | metadata: 4 | name: $RG_ID 5 | spec: 6 | cacheNodeType: cache.t3.micro 7 | engine: redis 8 | ipDiscovery: $IP_DISCOVERY 9 | networkType: $NETWORK_TYPE 10 | numNodeGroups: 2 11 | preferredMaintenanceWindow: $PMW 12 | replicasPerNodeGroup: 1 13 | description: $DESCRIPTION 14 | replicationGroupID: $RG_ID 15 | snapshotRetentionLimit: $SRL 16 | snapshotWindow: $SW 17 | tags: 18 | - key: tag_to_remove 19 | value: should_be_removed 20 | - key: tag_to_update 21 | value: old_value -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - common 5 | - bases/elasticache.services.k8s.aws_cacheclusters.yaml 6 | - bases/elasticache.services.k8s.aws_cacheparametergroups.yaml 7 | - bases/elasticache.services.k8s.aws_cachesubnetgroups.yaml 8 | - bases/elasticache.services.k8s.aws_replicationgroups.yaml 9 | - bases/elasticache.services.k8s.aws_serverlesscaches.yaml 10 | - bases/elasticache.services.k8s.aws_serverlesscachesnapshots.yaml 11 | - bases/elasticache.services.k8s.aws_snapshots.yaml 12 | - bases/elasticache.services.k8s.aws_users.yaml 13 | - bases/elasticache.services.k8s.aws_usergroups.yaml 14 | -------------------------------------------------------------------------------- /helm/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | name: elasticache-chart 3 | description: A Helm chart for the ACK service controller for Amazon ElastiCache (ElastiCache) 4 | version: 1.3.0 5 | appVersion: 1.3.0 6 | home: https://github.com/aws-controllers-k8s/elasticache-controller 7 | icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png 8 | sources: 9 | - https://github.com/aws-controllers-k8s/elasticache-controller 10 | maintainers: 11 | - name: ACK Admins 12 | url: https://github.com/orgs/aws-controllers-k8s/teams/ack-admin 13 | - name: ElastiCache Admins 14 | url: https://github.com/orgs/aws-controllers-k8s/teams/elasticache-maintainer 15 | keywords: 16 | - aws 17 | - kubernetes 18 | - elasticache 19 | -------------------------------------------------------------------------------- /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 | RDS-specific test variables. 15 | """ 16 | 17 | REPLACEMENT_VALUES = { 18 | } 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/replication_group/sdk_delete_post_request.go.tpl: -------------------------------------------------------------------------------- 1 | // delete call successful 2 | if err == nil { 3 | rp, _ := rm.setReplicationGroupOutput(ctx, r, resp.ReplicationGroup) 4 | // Setting resource synced condition to false will trigger a requeue of 5 | // the resource. 6 | ackcondition.SetSynced( 7 | rp, 8 | corev1.ConditionFalse, 9 | &condMsgCurrentlyDeleting, 10 | nil, 11 | ) 12 | // Need to return a requeue error here, otherwise: 13 | // - reconciler.deleteResource() marks the resource unmanaged 14 | // - reconciler.HandleReconcileError() does not update status for unmanaged resource 15 | // - reconciler.handleRequeues() is not invoked for delete code path. 16 | // TODO: return err as nil when reconciler is updated. 17 | return rp, requeueWaitWhileDeleting 18 | } 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-elasticache-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-elasticache-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 12 | name: {{ include "ack-elasticache-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 | -------------------------------------------------------------------------------- /helm/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | {{ .Chart.Name }} has been installed. 2 | This chart deploys "public.ecr.aws/aws-controllers-k8s/elasticache-controller:1.3.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 ElastiCache (ElastiCache) 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 | -------------------------------------------------------------------------------- /apis/v1alpha1/annotations.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 | const ( 17 | // AnnotationPrefix is the prefix for all annotations specifically for 18 | // the elasticache service. 19 | AnnotationPrefix = "elasticache.services.k8s.aws/" 20 | ) 21 | -------------------------------------------------------------------------------- /config/iam/KMS-policy-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "kms:DescribeCustomKeyStores", 8 | "kms:ListKeys", 9 | "kms:DeleteCustomKeyStore", 10 | "kms:GenerateRandom", 11 | "kms:UpdateCustomKeyStore", 12 | "kms:ListAliases", 13 | "kms:DisconnectCustomKeyStore", 14 | "kms:CreateKey", 15 | "kms:ConnectCustomKeyStore", 16 | "kms:CreateCustomKeyStore", 17 | "logs:DescribeResourcePolicies", 18 | "logs:CreateLogGroup", 19 | "logs:DeleteLogGroup" 20 | ], 21 | "Resource": "*" 22 | }, 23 | { 24 | "Effect": "Allow", 25 | "Action": "kms:*", 26 | "Resource": [ 27 | "arn:aws:kms:*::key/*", 28 | "arn:aws:kms:*::alias/*" 29 | ] 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /config/rbac/role-writer.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-elasticache-writer 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - elasticache.services.k8s.aws 11 | resources: 12 | - cacheclusters 13 | - cacheparametergroups 14 | - cachesubnetgroups 15 | - replicationgroups 16 | - serverlesscaches 17 | - serverlesscachesnapshots 18 | - snapshots 19 | - users 20 | - usergroups 21 | verbs: 22 | - create 23 | - delete 24 | - get 25 | - list 26 | - patch 27 | - update 28 | - watch 29 | - apiGroups: 30 | - elasticache.services.k8s.aws 31 | resources: 32 | - cacheclusters 33 | - cacheparametergroups 34 | - cachesubnetgroups 35 | - replicationgroups 36 | - serverlesscaches 37 | - serverlesscachesnapshots 38 | - snapshots 39 | - users 40 | - usergroups 41 | verbs: 42 | - get 43 | - patch 44 | - update 45 | -------------------------------------------------------------------------------- /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/replication_group/sdk_file_end.go.tpl: -------------------------------------------------------------------------------- 1 | // This method copies the data from given {{ .CRD.Names.Camel }} by populating it 2 | // into copy of supplied resource and returns that. 3 | func (rm *resourceManager) set{{ .CRD.Names.Camel }}Output ( 4 | ctx context.Context, 5 | r *resource, 6 | obj *svcsdktypes.{{ .CRD.Names.Camel }}, 7 | ) (*resource, error) { 8 | if obj == nil || 9 | r == nil || 10 | r.ko == nil { 11 | return nil, nil 12 | } 13 | resp := &svcsdk.{{ .CRD.Ops.Create.OutputRef.Shape.ShapeName }}{ {{ .CRD.Names.Camel }}:obj } 14 | // Merge in the information we read from the API call above to the copy of 15 | // the original Kubernetes object we passed to the function 16 | ko := r.ko.DeepCopy() 17 | {{ $createCode := GoCodeSetCreateOutput .CRD "resp" "ko" 1 }} 18 | {{ $createCode }} 19 | rm.setStatusDefaults(ko) 20 | {{- if $hookCode := Hook .CRD "sdk_file_end_set_output_post_populate" }} 21 | {{ $hookCode }} 22 | {{- end }} 23 | return &resource{ko}, nil 24 | } 25 | -------------------------------------------------------------------------------- /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-elasticache-controller.app.fullname" . }}-reader 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 14 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 15 | rules: 16 | - apiGroups: 17 | - elasticache.services.k8s.aws 18 | resources: 19 | - cacheclusters 20 | - cacheparametergroups 21 | - cachesubnetgroups 22 | - replicationgroups 23 | - serverlesscaches 24 | - serverlesscachesnapshots 25 | - snapshots 26 | - users 27 | - usergroups 28 | verbs: 29 | - get 30 | - list 31 | - watch 32 | -------------------------------------------------------------------------------- /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-elasticache-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-elasticache-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-elasticache-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-elasticache-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-elasticache-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-elasticache-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-elasticache-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 18 | roleRef: 19 | apiGroup: rbac.authorization.k8s.io 20 | kind: Role 21 | name: {{ include "ack-elasticache-controller.app.fullname" . }}-leaderelection 22 | subjects: 23 | - kind: ServiceAccount 24 | name: {{ include "ack-elasticache-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-elasticache-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-elasticache-controller.app.name" . }} 13 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 14 | spec: 15 | selector: 16 | app.kubernetes.io/name: {{ include "ack-elasticache-controller.app.name" . }} 17 | app.kubernetes.io/instance: {{ .Release.Name }} 18 | app.kubernetes.io/managed-by: Helm 19 | k8s-app: {{ include "ack-elasticache-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 | -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_read_many_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | if pendingModifications := ko.Status.PendingModifiedValues; pendingModifications != nil { 2 | if pendingModifications.NumCacheNodes != nil { 3 | ko.Spec.NumCacheNodes = pendingModifications.NumCacheNodes 4 | } 5 | if pendingModifications.CacheNodeType != nil { 6 | ko.Spec.CacheNodeType = pendingModifications.CacheNodeType 7 | } 8 | if pendingModifications.TransitEncryptionEnabled != nil { 9 | ko.Spec.TransitEncryptionEnabled = pendingModifications.TransitEncryptionEnabled 10 | } 11 | } 12 | if isAvailable(r) { 13 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionTrue, nil, nil) 14 | } else { 15 | // Setting resource synced condition to false will trigger a requeue of 16 | // the resource. No need to return a requeue error here. 17 | ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil) 18 | return &resource{ko}, nil 19 | } 20 | if ko.Status.ACKResourceMetadata != nil && ko.Status.ACKResourceMetadata.ARN != nil { 21 | resourceARN := (*string)(ko.Status.ACKResourceMetadata.ARN) 22 | tags, err := rm.getTags(ctx, *resourceARN) 23 | if err != nil { 24 | return nil, err 25 | } 26 | ko.Spec.Tags = tags 27 | } 28 | -------------------------------------------------------------------------------- /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: "elasticache.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ACK service controller for Amazon ElastiCache 2 | 3 | This repository contains source code for the AWS Controllers for Kubernetes 4 | (ACK) service controller for Amazon ElastiCache. 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/aws-controllers-k8s/issues 10 | 11 | ## Resources supported 12 | 13 | The ACK service controller for Amazon ElastiCache supports the following Amazon ElastiCache API resources in `DEVELOPER PREVIEW`: 14 | - [x] Replication Group 15 | - [x] Cache Subnet Group 16 | - [x] User Group 17 | - [x] User 18 | - [x] Snapshot Group 19 | - [x] Cache Parameter Group 20 | - [x] Serverless Cache 21 | - [x] Serverless Cache Snapshot 22 | - [x] Cache Cluster 23 | 24 | ## Contributing 25 | 26 | We welcome community contributions and pull requests. 27 | 28 | See our [contribution guide](/CONTRIBUTING.md) for more information on how to 29 | report issues, set up a development environment, and submit code. 30 | 31 | We adhere to the [Amazon Open Source Code of Conduct][coc]. 32 | 33 | You can also learn more about our [Governance](/GOVERNANCE.md) structure. 34 | 35 | [coc]: https://aws.github.io/code-of-conduct 36 | 37 | ## License 38 | 39 | This project is [licensed](/LICENSE) under the Apache-2.0 License. 40 | -------------------------------------------------------------------------------- /templates/hooks/cache_cluster/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if isDeleting(r) { 2 | // Setting resource synced condition to false will trigger a requeue of 3 | // the resource. 4 | ackcondition.SetSynced( 5 | r, 6 | corev1.ConditionFalse, 7 | &condMsgCurrentlyDeleting, 8 | nil, 9 | ) 10 | // Need to return a requeue error here, otherwise: 11 | // - reconciler.deleteResource() marks the resource unmanaged 12 | // - reconciler.HandleReconcileError() does not update status for unmanaged resource 13 | // - reconciler.handleRequeues() is not invoked for delete code path. 14 | // TODO: return err as nil when reconciler is updated. 15 | return r, requeueWaitWhileDeleting 16 | } 17 | if isModifying(r) { 18 | // Setting resource synced condition to false will trigger a requeue of 19 | // the resource. 20 | ackcondition.SetSynced( 21 | r, 22 | corev1.ConditionFalse, 23 | &condMsgNoDeleteWhileModifying, 24 | nil, 25 | ) 26 | // Need to return a requeue error here, otherwise: 27 | // - reconciler.deleteResource() marks the resource unmanaged 28 | // - reconciler.HandleReconcileError() does not update status for unmanaged resource 29 | // - reconciler.handleRequeues() is not invoked for delete code path. 30 | // TODO: return err as nil when reconciler is updated. 31 | return r, requeueWaitWhileModifying 32 | } 33 | -------------------------------------------------------------------------------- /templates/hooks/replication_group/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if isDeleting(r) { 2 | // Setting resource synced condition to false will trigger a requeue of 3 | // the resource. 4 | ackcondition.SetSynced( 5 | r, 6 | corev1.ConditionFalse, 7 | &condMsgCurrentlyDeleting, 8 | nil, 9 | ) 10 | // Need to return a requeue error here, otherwise: 11 | // - reconciler.deleteResource() marks the resource unmanaged 12 | // - reconciler.HandleReconcileError() does not update status for unmanaged resource 13 | // - reconciler.handleRequeues() is not invoked for delete code path. 14 | // TODO: return err as nil when reconciler is updated. 15 | return r, requeueWaitWhileDeleting 16 | } 17 | if isModifying(r) { 18 | // Setting resource synced condition to false will trigger a requeue of 19 | // the resource. 20 | ackcondition.SetSynced( 21 | r, 22 | corev1.ConditionFalse, 23 | &condMsgNoDeleteWhileModifying, 24 | nil, 25 | ) 26 | // Need to return a requeue error here, otherwise: 27 | // - reconciler.deleteResource() marks the resource unmanaged 28 | // - reconciler.HandleReconcileError() does not update status for unmanaged resource 29 | // - reconciler.handleRequeues() is not invoked for delete code path. 30 | // TODO: return err as nil when reconciler is updated. 31 | return r, requeueWaitWhileModifying 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-elasticache-controller.app.fullname" . }}-writer 7 | namespace: {{ .Release.Namespace }} 8 | labels: 9 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 14 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 15 | rules: 16 | - apiGroups: 17 | - elasticache.services.k8s.aws 18 | resources: 19 | - cacheclusters 20 | - cacheparametergroups 21 | - cachesubnetgroups 22 | - replicationgroups 23 | - serverlesscaches 24 | - serverlesscachesnapshots 25 | - snapshots 26 | - users 27 | - usergroups 28 | verbs: 29 | - create 30 | - delete 31 | - get 32 | - list 33 | - patch 34 | - update 35 | - watch 36 | - apiGroups: 37 | - elasticache.services.k8s.aws 38 | resources: 39 | - cacheclusters 40 | - cacheparametergroups 41 | - cachesubnetgroups 42 | - replicationgroups 43 | - serverlesscaches 44 | - serverlesscachesnapshots 45 | - snapshots 46 | - users 47 | - usergroups 48 | verbs: 49 | - get 50 | - patch 51 | - update 52 | -------------------------------------------------------------------------------- /helm/templates/caches-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "ack-elasticache-controller.app.fullname" . }}-namespaces-cache 5 | labels: 6 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-elasticache-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-elasticache-controller.app.fullname" . }}-configmaps-cache 26 | namespace: {{ .Release.Namespace }} 27 | labels: 28 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 33 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 34 | rules: 35 | - apiGroups: 36 | - "" 37 | resources: 38 | - configmaps 39 | verbs: 40 | - get 41 | - list 42 | - watch -------------------------------------------------------------------------------- /pkg/common/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 | package common 15 | 16 | import ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 17 | 18 | // remove the Difference corresponding to the given subject from the delta struct 19 | // TODO: ideally this would have a common implementation in compare/delta.go 20 | func RemoveFromDelta( 21 | delta *ackcompare.Delta, 22 | subject string, 23 | ) { 24 | // copy slice 25 | differences := delta.Differences 26 | 27 | // identify index of Difference to remove 28 | //TODO: this could require a stricter Path.Equals down the road 29 | var i *int = nil 30 | for j, diff := range differences { 31 | if diff.Path.Contains(subject) { 32 | i = &j 33 | break 34 | } 35 | } 36 | 37 | // if found, create a new slice and replace the original 38 | if i != nil { 39 | differences = append(differences[:*i], differences[*i+1:]...) 40 | delta.Differences = differences 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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 = "elasticache" 21 | CRD_GROUP = "elasticache.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 | scenarios_directory = Path(__file__).parent / "scenarios" 30 | 31 | 32 | def load_elasticache_resource(resource_name: str, additional_replacements: Dict[str, Any] = {}): 33 | """ Overrides the default `load_resource_file` to access the specific resources 34 | directory for the current service. 35 | """ 36 | return load_resource_file(resource_directory, resource_name, additional_replacements=additional_replacements) -------------------------------------------------------------------------------- /templates/hooks/replication_group/sdk_update_post_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | if !delta.DifferentAt("Spec.LogDeliveryConfigurations") { 2 | input.LogDeliveryConfigurations = nil 3 | } 4 | if !delta.DifferentAt("Spec.TransitEncryptionEnabled") { 5 | input.TransitEncryptionEnabled = nil 6 | } 7 | if delta.DifferentAt("UserGroupIDs") { 8 | for _, diff := range delta.Differences { 9 | if diff.Path.Contains("UserGroupIDs") { 10 | existingUserGroups := diff.B.([]*string) 11 | requiredUserGroups := diff.A.([]*string) 12 | 13 | // User groups to add 14 | { 15 | var userGroupsToAdd []string 16 | 17 | for _, requiredUserGroup := range requiredUserGroups { 18 | found := false 19 | for _, existingUserGroup := range existingUserGroups { 20 | if requiredUserGroup == existingUserGroup { 21 | found = true 22 | break 23 | } 24 | } 25 | 26 | if !found { 27 | if requiredUserGroup != nil { 28 | userGroupsToAdd = append(userGroupsToAdd, *requiredUserGroup) 29 | } 30 | } 31 | } 32 | 33 | input.UserGroupIdsToAdd = userGroupsToAdd 34 | } 35 | 36 | // User groups to remove 37 | { 38 | var userGroupsToRemove []string 39 | 40 | for _, existingUserGroup := range existingUserGroups { 41 | found := false 42 | for _, requiredUserGroup := range requiredUserGroups { 43 | if requiredUserGroup == existingUserGroup { 44 | found = true 45 | break 46 | } 47 | } 48 | 49 | if !found { 50 | if existingUserGroup != nil { 51 | userGroupsToRemove = append(userGroupsToRemove, *existingUserGroup) 52 | } 53 | } 54 | } 55 | 56 | input.UserGroupIdsToRemove = userGroupsToRemove 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /config/iam/README.md: -------------------------------------------------------------------------------- 1 | # Additional IAM policies required for testing 2 | As outlined in the 3 | [documentation for test setup](https://aws-controllers-k8s.github.io/community/dev-docs/testing/#iam-setup), 4 | the `Admin-k8s` IAM role used to execute the tests requires permission to create and manage resources from the service whose controller 5 | is being tested. For example, attaching the policy specified in the `recommended-policy-arn` file (located in this directory) 6 | to the `Admin-k8s` role ensures the tests can perform all ElastiCache operations. 7 | 8 | However, the ElastiCache tests also depend on other services and therefore require additional policies to be attached to 9 | the `Admin-k8s` IAM role, or some tests may fail. See the below sections for instructions to set this up: 10 | 11 | 12 | ## KMS (Key Management Service) 13 | The AWS-managed `AWSKeyManagementServicePowerUser` policy does not contain all the required permissions, so we will have 14 | to manually create and attach a full-access policy: 15 | 16 | 1. The template for this policy is located in the `KMS-policy.json` file in this directory. Replace the two occurrences of 17 | `` with the AWS account ID used to execute these tests. This a complete policy specification. 18 | 19 | 2. Create the IAM policy by following the directions [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html), 20 | providing a name like `KMSFullAccess`. In the AWS console this basically amounts to pasting in 21 | the policy JSON from step 1, but this is also doable in the AWS CLI/SDKs. 22 | 23 | 3. Attach the newly created policy to the `Admin-k8s` role via the console or the 24 | [attach-role-policy](https://docs.aws.amazon.com/cli/latest/reference/iam/attach-role-policy.html) operation in the CLI. 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /helm/templates/cluster-role-controller.yaml: -------------------------------------------------------------------------------- 1 | {{ $labels := .Values.role.labels }} 2 | {{ $appVersion := .Chart.AppVersion | quote }} 3 | {{ $rbacRules := include "ack-elasticache-controller.rbac-rules" . }} 4 | {{ $fullname := include "ack-elasticache-controller.app.fullname" . }} 5 | {{ $chartVersion := include "ack-elasticache-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-elasticache-controller.app.fullname" . }} 11 | labels: 12 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 17 | helm.sh/chart: {{ include "ack-elasticache-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-elasticache-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 }} -------------------------------------------------------------------------------- /templates/hooks/replication_group/sdk_read_many_post_set_output.go.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | rm.updateSpecFields(ctx, resp.ReplicationGroups[0], &resource{ko}) 4 | if isDeleting(r) { 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( 8 | &resource{ko}, 9 | corev1.ConditionFalse, 10 | &condMsgCurrentlyDeleting, 11 | nil, 12 | ) 13 | return &resource{ko}, nil 14 | } 15 | if isModifying(r) { 16 | // Setting resource synced condition to false will trigger a requeue of 17 | // the resource. No need to return a requeue error here. 18 | ackcondition.SetSynced( 19 | &resource{ko}, 20 | corev1.ConditionFalse, 21 | &condMsgNoDeleteWhileModifying, 22 | nil, 23 | ) 24 | return &resource{ko}, nil 25 | } 26 | 27 | if isCreating(r){ 28 | // Setting resource synced condition to false will trigger a requeue of 29 | // the resource. No need to return a requeue error here. 30 | ackcondition.SetSynced( 31 | &resource{ko}, 32 | corev1.ConditionFalse, 33 | &condMsgCurrentlyCreating, 34 | nil, 35 | ) 36 | return &resource{ko}, nil 37 | } 38 | 39 | if isCreateFailed(r) { 40 | // This is a terminal state and by setting a Terminal condition on the 41 | // resource, we will prevent it from being requeued. 42 | ackcondition.SetTerminal( 43 | &resource{ko}, 44 | corev1.ConditionTrue, 45 | &condMsgTerminalCreateFailed, 46 | nil, 47 | ) 48 | return &resource{ko}, nil 49 | } 50 | 51 | if ko.Status.ACKResourceMetadata != nil && ko.Status.ACKResourceMetadata.ARN != nil { 52 | resourceARN := (*string)(ko.Status.ACKResourceMetadata.ARN) 53 | tags, err := rm.getTags(ctx, *resourceARN) 54 | if err != nil { 55 | return nil, err 56 | } 57 | ko.Spec.Tags = tags 58 | } 59 | -------------------------------------------------------------------------------- /helm/templates/caches-role-binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: {{ include "ack-elasticache-controller.app.fullname" . }}-namespaces-cache 5 | labels: 6 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 11 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 12 | roleRef: 13 | kind: ClusterRole 14 | apiGroup: rbac.authorization.k8s.io 15 | name: {{ include "ack-elasticache-controller.app.fullname" . }}-namespaces-cache 16 | subjects: 17 | - kind: ServiceAccount 18 | name: {{ include "ack-elasticache-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-elasticache-controller.app.fullname" . }}-configmaps-cache 25 | namespace: {{ .Release.Namespace }} 26 | labels: 27 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 32 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 33 | roleRef: 34 | kind: Role 35 | apiGroup: rbac.authorization.k8s.io 36 | name: {{ include "ack-elasticache-controller.app.fullname" . }}-configmaps-cache 37 | subjects: 38 | - kind: ServiceAccount 39 | name: {{ include "ack-elasticache-controller.service-account.name" . }} 40 | namespace: {{ .Release.Namespace }} 41 | -------------------------------------------------------------------------------- /pkg/resource/user/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 user 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/snapshot/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 snapshot 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/user_group/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 user_group 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/cache_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 cache_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/serverless_cache/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 serverless_cache 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/cache_subnet_group/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 cache_subnet_group 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/replication_group/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 replication_group 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/cache_parameter_group/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 cache_parameter_group 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/serverless_cache_snapshot/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 serverless_cache_snapshot 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 | -------------------------------------------------------------------------------- /olm/olmconfig.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | annotations: 3 | capabilityLevel: Basic Install 4 | shortDescription: AWS ElastiCache controller is a service controller for managing ElastiCache resources 5 | in Kubernetes 6 | displayName: AWS Controllers for Kubernetes - Amazon ElastiCache 7 | description: |- 8 | Manage Amazon ElastiCache resources in AWS from within your Kubernetes 9 | cluster. 10 | 11 | 12 | **About Amazon ElastiCache** 13 | 14 | 15 | Amazon ElastiCache allows you to seamlessly set up, run, and scale popular 16 | open-source compatible in-memory data stores in the cloud. Build 17 | data-intensive apps or boost the performance of your existing databases by 18 | retrieving data from high throughput and low latency in-memory data stores. 19 | Amazon ElastiCache is a popular choice for real-time use cases like Caching, 20 | Session Stores, Gaming, Geospatial Services, Real-Time Analytics, and Queuing. 21 | 22 | 23 | Amazon ElastiCache offers fully managed Redis, voted the most loved database 24 | by developers in the Stack Overflow 2020 Developer Survey, and Memcached for 25 | your most demanding applications that require sub-millisecond response times. 26 | 27 | 28 | **About the AWS Controllers for Kubernetes** 29 | 30 | 31 | This controller is a component of the 32 | [AWS Controller for Kubernetes](https://github.com/aws/aws-controllers-k8s) 33 | project. This project is currently in **developer preview**. 34 | 35 | 36 | **Pre-Installation Steps** 37 | 38 | 39 | Please follow the following link: [Red Hat OpenShift](https://aws-controllers-k8s.github.io/community/docs/user-docs/openshift/) 40 | samples: 41 | - kind: CacheParameterGroup 42 | spec: '{}' 43 | - kind: CacheSubnetGroup 44 | spec: '{}' 45 | - kind: ReplicationGroup 46 | spec: '{}' 47 | - kind: Snapshot 48 | spec: '{}' 49 | - kind: UserGroup 50 | spec: '{}' 51 | - kind: User 52 | spec: '{}' 53 | maintainers: 54 | - name: "elasticache maintainer team" 55 | email: "ack-maintainers@amazon.com" 56 | links: 57 | - name: Amazon ElastiCache Developer Resources 58 | url: https://aws.amazon.com/elasticache/developer-resources/ 59 | -------------------------------------------------------------------------------- /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-elasticache-controller.app.fullname" . }}-rolebinding 6 | labels: 7 | app.kubernetes.io/name: {{ include "ack-elasticache-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-elasticache-controller.app.name" . }} 12 | helm.sh/chart: {{ include "ack-elasticache-controller.chart.name-version" . }} 13 | roleRef: 14 | kind: ClusterRole 15 | apiGroup: rbac.authorization.k8s.io 16 | name: {{ include "ack-elasticache-controller.app.fullname" . }} 17 | subjects: 18 | - kind: ServiceAccount 19 | name: {{ include "ack-elasticache-controller.service-account.name" . }} 20 | namespace: {{ .Release.Namespace }} 21 | {{ else if eq .Values.installScope "namespace" }} 22 | {{ $wn := include "ack-elasticache-controller.watch-namespace" . }} 23 | {{ $namespaces := split "," $wn }} 24 | {{ $fullname := include "ack-elasticache-controller.app.fullname" . }} 25 | {{ $releaseNamespace := .Release.Namespace }} 26 | {{ $serviceAccountName := include "ack-elasticache-controller.service-account.name" . }} 27 | {{ $chartVersion := include "ack-elasticache-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 }} -------------------------------------------------------------------------------- /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 pytest 15 | from acktest import k8s 16 | 17 | 18 | def pytest_addoption(parser): 19 | parser.addoption("--runslow", action="store_true", default=False, help="run slow tests") 20 | parser.addoption("--runblocked", action="store_true", default=False, help="run blocked tests") 21 | 22 | 23 | def pytest_configure(config): 24 | config.addinivalue_line( 25 | "markers", "canary: mark test to also run in canary tests" 26 | ) 27 | config.addinivalue_line( 28 | "markers", "service(arg): mark test associated with a given service" 29 | ) 30 | config.addinivalue_line( 31 | "markers", "slow: mark test as slow to run" 32 | ) 33 | config.addinivalue_line( 34 | "markers", "blocked: mark test as failing due to unresolved issue" 35 | ) 36 | 37 | 38 | def pytest_collection_modifyitems(config, items): 39 | # create skip markers 40 | skip_slow = pytest.mark.skip(reason="need --runslow option to run") 41 | skip_blocked = pytest.mark.skip(reason="need --runblocked option to run") 42 | 43 | # add skip markers to tests if the relevant command line option was not specified 44 | for item in items: 45 | if "slow" in item.keywords and not config.getoption("--runslow"): 46 | item.add_marker(skip_slow) 47 | if "blocked" in item.keywords and not config.getoption("--runblocked"): 48 | item.add_marker(skip_blocked) 49 | 50 | 51 | # Provide a k8s client to interact with the integration test cluster 52 | @pytest.fixture(scope='class') 53 | def k8s_client(): 54 | return k8s._get_k8s_api_client() 55 | -------------------------------------------------------------------------------- /config/rbac/cluster-role-controller.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: ack-elasticache-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 | - elasticache.services.k8s.aws 37 | resources: 38 | - cacheclusters 39 | - cacheparametergroups 40 | - cachesubnetgroups 41 | - replicationgroups 42 | - serverlesscaches 43 | - serverlesscachesnapshots 44 | - snapshots 45 | - usergroups 46 | - users 47 | verbs: 48 | - create 49 | - delete 50 | - get 51 | - list 52 | - patch 53 | - update 54 | - watch 55 | - apiGroups: 56 | - elasticache.services.k8s.aws 57 | resources: 58 | - cacheclusters/status 59 | - cacheparametergroups/status 60 | - cachesubnetgroups/status 61 | - replicationgroups/status 62 | - serverlesscaches/status 63 | - serverlesscachesnapshots/status 64 | - snapshots/status 65 | - usergroups/status 66 | - users/status 67 | verbs: 68 | - get 69 | - patch 70 | - update 71 | - apiGroups: 72 | - kms.services.k8s.aws 73 | resources: 74 | - keys 75 | - keys/status 76 | verbs: 77 | - get 78 | - list 79 | - apiGroups: 80 | - services.k8s.aws 81 | resources: 82 | - fieldexports 83 | - iamroleselectors 84 | verbs: 85 | - create 86 | - delete 87 | - get 88 | - list 89 | - patch 90 | - update 91 | - watch 92 | - apiGroups: 93 | - services.k8s.aws 94 | resources: 95 | - fieldexports/status 96 | - iamroleselectors/status 97 | verbs: 98 | - get 99 | - patch 100 | - update 101 | - apiGroups: 102 | - sns.services.k8s.aws 103 | resources: 104 | - topics 105 | - topics/status 106 | verbs: 107 | - get 108 | - list 109 | -------------------------------------------------------------------------------- /pkg/util/engine_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 | package util 15 | 16 | import ( 17 | "strconv" 18 | "strings" 19 | ) 20 | 21 | // EngineVersionsMatch returns true if desired and latest engine versions match and false otherwise 22 | // precondition: both desiredEV and latestEV are non-nil 23 | // this handles the case where only the major EV is specified, e.g. "6.x" (or similar), 24 | // but the latest version shows the minor version, e.g. "6.0.5". 25 | func EngineVersionsMatch(desiredEV, latestEV string) bool { 26 | if desiredEV == latestEV { 27 | return true 28 | } 29 | 30 | dMaj, dMin := versionNumbersFromString(desiredEV) 31 | lMaj, lMin := versionNumbersFromString(latestEV) 32 | last := len(desiredEV) - 1 33 | 34 | // if the last character of desiredEV is "x" or the major version is higher than 5, ignore patch version when comparing. 35 | // See https://github.com/aws-controllers-k8s/community/issues/1737 36 | if dMaj > 5 || desiredEV[last:] == "x" { 37 | return dMaj == lMaj && (dMin < 0 || dMin == lMin) 38 | } 39 | 40 | return false 41 | } 42 | 43 | // versionNumbersFromString takes a version string like "6.2", "6.x" or "7.0.4" and 44 | // returns the major, minor and patch numbers. If no minor or patch numbers are present 45 | // or contain the "x" placeholder, -1 is returned for that version number. 46 | func versionNumbersFromString(version string) (int, int) { 47 | parts := strings.Split(version, ".") 48 | major := -1 49 | minor := -1 50 | if len(parts) == 0 { 51 | return major, minor 52 | } 53 | major, _ = strconv.Atoi(parts[0]) 54 | if len(parts) > 1 { 55 | if !strings.EqualFold(parts[1], "x") { 56 | minor, _ = strconv.Atoi(parts[1]) 57 | } 58 | } 59 | return major, minor 60 | } 61 | -------------------------------------------------------------------------------- /pkg/resource/user/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 user 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/elasticache-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.User) error { 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/resource/snapshot/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 snapshot 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/elasticache-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.Snapshot) error { 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/resource/user_group/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 user_group 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/elasticache-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.UserGroup) error { 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/resource/cache_parameter_group/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 cache_parameter_group 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/elasticache-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.CacheParameterGroup) error { 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /pkg/resource/user_group/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 user_group 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.Engine, b.ko.Spec.Engine) { 47 | delta.Add("Spec.Engine", a.ko.Spec.Engine, b.ko.Spec.Engine) 48 | } else if a.ko.Spec.Engine != nil && b.ko.Spec.Engine != nil { 49 | if *a.ko.Spec.Engine != *b.ko.Spec.Engine { 50 | delta.Add("Spec.Engine", a.ko.Spec.Engine, b.ko.Spec.Engine) 51 | } 52 | } 53 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 54 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 55 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 56 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 57 | } 58 | if ackcompare.HasNilDifference(a.ko.Spec.UserGroupID, b.ko.Spec.UserGroupID) { 59 | delta.Add("Spec.UserGroupID", a.ko.Spec.UserGroupID, b.ko.Spec.UserGroupID) 60 | } else if a.ko.Spec.UserGroupID != nil && b.ko.Spec.UserGroupID != nil { 61 | if *a.ko.Spec.UserGroupID != *b.ko.Spec.UserGroupID { 62 | delta.Add("Spec.UserGroupID", a.ko.Spec.UserGroupID, b.ko.Spec.UserGroupID) 63 | } 64 | } 65 | if len(a.ko.Spec.UserIDs) != len(b.ko.Spec.UserIDs) { 66 | delta.Add("Spec.UserIDs", a.ko.Spec.UserIDs, b.ko.Spec.UserIDs) 67 | } else if len(a.ko.Spec.UserIDs) > 0 { 68 | if !ackcompare.SliceStringPEqual(a.ko.Spec.UserIDs, b.ko.Spec.UserIDs) { 69 | delta.Add("Spec.UserIDs", a.ko.Spec.UserIDs, b.ko.Spec.UserIDs) 70 | } 71 | } 72 | 73 | return delta 74 | } 75 | -------------------------------------------------------------------------------- /pkg/resource/cache_cluster/delta_util.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 cache_cluster 15 | 16 | import ( 17 | "encoding/json" 18 | "reflect" 19 | 20 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 21 | 22 | "github.com/aws-controllers-k8s/elasticache-controller/pkg/common" 23 | "github.com/aws-controllers-k8s/elasticache-controller/pkg/util" 24 | ) 25 | 26 | // modifyDelta removes non-meaningful differences from the delta and adds additional differences if necessary. 27 | func modifyDelta( 28 | delta *ackcompare.Delta, 29 | desired *resource, 30 | latest *resource, 31 | ) { 32 | if delta.DifferentAt("Spec.EngineVersion") && desired.ko.Spec.EngineVersion != nil && latest.ko.Spec.EngineVersion != nil && 33 | util.EngineVersionsMatch(*desired.ko.Spec.EngineVersion, *latest.ko.Spec.EngineVersion) { 34 | common.RemoveFromDelta(delta, "Spec.EngineVersion") 35 | // TODO: handle the case of a nil difference (especially when desired EV is nil) 36 | } 37 | 38 | // if server has given PreferredMaintenanceWindow a default value, no action needs to be taken. 39 | if delta.DifferentAt("Spec.PreferredMaintenanceWindow") && desired.ko.Spec.PreferredMaintenanceWindow == nil && 40 | latest.ko.Spec.PreferredMaintenanceWindow != nil { 41 | common.RemoveFromDelta(delta, "Spec.PreferredMaintenanceWindow") 42 | } 43 | 44 | if delta.DifferentAt("Spec.PreferredAvailabilityZone") && desired.ko.Spec.PreferredAvailabilityZone == nil && 45 | latest.ko.Spec.PreferredAvailabilityZone != nil { 46 | common.RemoveFromDelta(delta, "Spec.PreferredAvailabilityZone") 47 | } 48 | 49 | updatePAZsDelta(desired, delta) 50 | } 51 | 52 | // updatePAZsDelta retrieves the last requested configurations saved in annotations and compares them 53 | // to the current desired configurations. If a diff is found, it adds it to delta. 54 | func updatePAZsDelta(desired *resource, delta *ackcompare.Delta) { 55 | var lastRequestedPAZs []*string 56 | unmarshalAnnotation(desired, AnnotationLastRequestedPAZs, &lastRequestedPAZs) 57 | if !reflect.DeepEqual(desired.ko.Spec.PreferredAvailabilityZones, lastRequestedPAZs) { 58 | delta.Add("Spec.PreferredAvailabilityZones", desired.ko.Spec.PreferredAvailabilityZones, 59 | lastRequestedPAZs) 60 | } 61 | } 62 | 63 | func unmarshalAnnotation(desired *resource, annotation string, val interface{}) { 64 | if data, ok := desired.ko.ObjectMeta.GetAnnotations()[annotation]; ok { 65 | _ = json.Unmarshal([]byte(data), val) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /test/e2e/tests/test_usergroup.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 Elasticache UserGroup resource 15 | """ 16 | import pytest 17 | from acktest.k8s import resource as k8s 18 | from acktest.resources import random_suffix_name 19 | 20 | from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_elasticache_resource 21 | from e2e.bootstrap_resources import get_bootstrap_resources 22 | 23 | RESOURCE_PLURAL = "usergroups" 24 | KIND_NAME = "UserGroup" 25 | 26 | 27 | @pytest.fixture(scope="module") 28 | def bootstrap_resources(): 29 | return get_bootstrap_resources() 30 | 31 | 32 | @pytest.fixture(scope="module") 33 | def get_user_group_yaml(): 34 | def _get_user_group_yaml(user_group_id): 35 | input_dict = { 36 | "USER_GROUP_ID": user_group_id, 37 | } 38 | user_group = load_elasticache_resource("usergroup", additional_replacements=input_dict) 39 | 40 | return user_group 41 | return _get_user_group_yaml 42 | 43 | 44 | # setup/teardown for test_user_group_create_update 45 | @pytest.fixture(scope="module") 46 | def user_group_create(get_user_group_yaml): 47 | user_group_id = random_suffix_name("ack-usergroup", 32) 48 | 49 | reference = k8s.CustomResourceReference( 50 | CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, user_group_id, namespace="default") 51 | 52 | user_group = get_user_group_yaml(user_group_id) 53 | 54 | # Create new user group 55 | _ = k8s.create_custom_resource(reference, user_group) 56 | resource = k8s.wait_resource_consumed_by_controller(reference, wait_periods=10) 57 | assert resource is not None 58 | yield reference, resource 59 | 60 | # Teardown 61 | _, deleted = k8s.delete_custom_resource(reference) 62 | assert deleted is True 63 | 64 | 65 | @service_marker 66 | class TestUserGroup: 67 | def test_user_group_create_update(self, user_group_create, get_user_group_yaml, bootstrap_resources): 68 | (reference, resource) = user_group_create 69 | assert k8s.wait_on_condition(reference, "ACK.ResourceSynced", "True", wait_periods=15) 70 | 71 | # Update the usergroup to include one more user 72 | updated_user_group = get_user_group_yaml(reference.name) 73 | updated_user_group["spec"]["userIDs"].append(bootstrap_resources.NonDefaultUser) 74 | 75 | k8s.patch_custom_resource(reference, updated_user_group) 76 | 77 | assert k8s.wait_on_condition(reference, "ACK.ResourceSynced", "True", wait_periods=15) 78 | resource = k8s.get_resource(reference) 79 | assert len(resource["spec"]["userIDs"]) == 2 80 | assert resource["status"]["status"] == "active" 81 | -------------------------------------------------------------------------------- /test/e2e/tests/test_snapshot.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 Elasticache Snapshot resource 15 | """ 16 | 17 | import pytest 18 | import logging 19 | import boto3 20 | from time import sleep 21 | 22 | from acktest.resources import random_suffix_name 23 | from acktest.k8s import resource as k8s 24 | from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_elasticache_resource 25 | from e2e.bootstrap_resources import get_bootstrap_resources 26 | from e2e.util import wait_snapshot_deleted 27 | 28 | RESOURCE_PLURAL = "snapshots" 29 | DEFAULT_WAIT_SECS = 30 30 | 31 | @pytest.fixture(scope="module") 32 | def ec_client(): 33 | ec = boto3.client("elasticache") 34 | return ec 35 | 36 | # retrieve resources created in the bootstrap step 37 | @pytest.fixture(scope="module") 38 | def bootstrap_resources(): 39 | return get_bootstrap_resources() 40 | 41 | # factory for snapshots 42 | @pytest.fixture(scope="module") 43 | def make_snapshot(): 44 | def _make_snapshot(yaml_name, input_dict, snapshot_name): 45 | snapshot = load_elasticache_resource( 46 | yaml_name, additional_replacements=input_dict) 47 | logging.debug(snapshot) 48 | 49 | reference = k8s.CustomResourceReference( 50 | CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL, snapshot_name, namespace="default") 51 | _ = k8s.create_custom_resource(reference, snapshot) 52 | resource = k8s.wait_resource_consumed_by_controller(reference, wait_periods=10) 53 | assert resource is not None 54 | return (reference, resource) 55 | 56 | return _make_snapshot 57 | 58 | # setup/teardown for test_snapshot_kms 59 | @pytest.fixture(scope="module") 60 | def snapshot_kms(ec_client, bootstrap_resources, make_snapshot): 61 | response = ec_client.describe_snapshots(SnapshotName=bootstrap_resources.SnapshotName) 62 | cc_id = response['Snapshots'][0]['CacheClusterId'] 63 | 64 | snapshot_name = random_suffix_name("ack-snapshot-kms", 32) 65 | 66 | input_dict = { 67 | "SNAPSHOT_NAME": snapshot_name, 68 | "CC_ID": cc_id, 69 | "KMS_KEY_ID": bootstrap_resources.KmsKeyID, 70 | } 71 | 72 | (reference, resource) = make_snapshot("snapshot_kms", input_dict, input_dict['SNAPSHOT_NAME']) 73 | yield (reference, resource) 74 | 75 | # teardown 76 | k8s.delete_custom_resource(reference) 77 | assert wait_snapshot_deleted(snapshot_name) 78 | 79 | @service_marker 80 | class TestSnapshot: 81 | 82 | # test create of snapshot while providing KMS key 83 | def test_snapshot_kms(self, snapshot_kms): 84 | (reference, _) = snapshot_kms 85 | assert k8s.wait_on_condition(reference, "ACK.ResourceSynced", "True", wait_periods=15) 86 | -------------------------------------------------------------------------------- /pkg/resource/cache_subnet_group/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 cache_subnet_group 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.CacheSubnetGroupDescription, b.ko.Spec.CacheSubnetGroupDescription) { 47 | delta.Add("Spec.CacheSubnetGroupDescription", a.ko.Spec.CacheSubnetGroupDescription, b.ko.Spec.CacheSubnetGroupDescription) 48 | } else if a.ko.Spec.CacheSubnetGroupDescription != nil && b.ko.Spec.CacheSubnetGroupDescription != nil { 49 | if *a.ko.Spec.CacheSubnetGroupDescription != *b.ko.Spec.CacheSubnetGroupDescription { 50 | delta.Add("Spec.CacheSubnetGroupDescription", a.ko.Spec.CacheSubnetGroupDescription, b.ko.Spec.CacheSubnetGroupDescription) 51 | } 52 | } 53 | if ackcompare.HasNilDifference(a.ko.Spec.CacheSubnetGroupName, b.ko.Spec.CacheSubnetGroupName) { 54 | delta.Add("Spec.CacheSubnetGroupName", a.ko.Spec.CacheSubnetGroupName, b.ko.Spec.CacheSubnetGroupName) 55 | } else if a.ko.Spec.CacheSubnetGroupName != nil && b.ko.Spec.CacheSubnetGroupName != nil { 56 | if *a.ko.Spec.CacheSubnetGroupName != *b.ko.Spec.CacheSubnetGroupName { 57 | delta.Add("Spec.CacheSubnetGroupName", a.ko.Spec.CacheSubnetGroupName, b.ko.Spec.CacheSubnetGroupName) 58 | } 59 | } 60 | if len(a.ko.Spec.SubnetIDs) != len(b.ko.Spec.SubnetIDs) { 61 | delta.Add("Spec.SubnetIDs", a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) 62 | } else if len(a.ko.Spec.SubnetIDs) > 0 { 63 | if !ackcompare.SliceStringPEqual(a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) { 64 | delta.Add("Spec.SubnetIDs", a.ko.Spec.SubnetIDs, b.ko.Spec.SubnetIDs) 65 | } 66 | } 67 | if !reflect.DeepEqual(a.ko.Spec.SubnetRefs, b.ko.Spec.SubnetRefs) { 68 | delta.Add("Spec.SubnetRefs", a.ko.Spec.SubnetRefs, b.ko.Spec.SubnetRefs) 69 | } 70 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 71 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 72 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 73 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 74 | } 75 | 76 | return delta 77 | } 78 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /go.local.mod: -------------------------------------------------------------------------------- 1 | module github.com/aws-controllers-k8s/elasticache-controller 2 | 3 | go 1.17 4 | 5 | replace github.com/aws-controllers-k8s/runtime => ../runtime 6 | 7 | require ( 8 | github.com/aws-controllers-k8s/runtime v0.0.0-20210204203051-91a6bd53a48c 9 | github.com/aws/aws-sdk-go v1.42.0 10 | github.com/ghodss/yaml v1.0.0 11 | github.com/go-logr/logr v1.2.0 12 | github.com/google/go-cmp v0.5.5 13 | github.com/pkg/errors v0.9.1 14 | github.com/spf13/pflag v1.0.5 15 | github.com/stretchr/testify v1.7.0 16 | go.uber.org/zap v1.19.1 17 | k8s.io/api v0.23.0 18 | k8s.io/apimachinery v0.23.0 19 | k8s.io/client-go v0.23.0 20 | sigs.k8s.io/controller-runtime v0.11.0 21 | ) 22 | 23 | require ( 24 | github.com/beorn7/perks v1.0.1 // indirect 25 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 26 | github.com/davecgh/go-spew v1.1.1 // indirect 27 | github.com/evanphx/json-patch v4.12.0+incompatible // indirect 28 | github.com/fsnotify/fsnotify v1.5.1 // indirect 29 | github.com/go-logr/zapr v1.2.0 // indirect 30 | github.com/gogo/protobuf v1.3.2 // indirect 31 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 32 | github.com/golang/protobuf v1.5.2 // indirect 33 | github.com/google/gofuzz v1.1.0 // indirect 34 | github.com/google/uuid v1.1.2 // indirect 35 | github.com/googleapis/gnostic v0.5.5 // indirect 36 | github.com/imdario/mergo v0.3.12 // indirect 37 | github.com/itchyny/gojq v0.12.6 // indirect 38 | github.com/itchyny/timefmt-go v0.1.3 // indirect 39 | github.com/jaypipes/envutil v1.0.0 // indirect 40 | github.com/jmespath/go-jmespath v0.4.0 // indirect 41 | github.com/json-iterator/go v1.1.12 // indirect 42 | github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect 43 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 44 | github.com/modern-go/reflect2 v1.0.2 // indirect 45 | github.com/pmezard/go-difflib v1.0.0 // indirect 46 | github.com/prometheus/client_golang v1.11.0 // indirect 47 | github.com/prometheus/client_model v0.2.0 // indirect 48 | github.com/prometheus/common v0.28.0 // indirect 49 | github.com/prometheus/procfs v0.6.0 // indirect 50 | github.com/stretchr/objx v0.2.0 // indirect 51 | go.uber.org/atomic v1.7.0 // indirect 52 | go.uber.org/multierr v1.6.0 // indirect 53 | golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect 54 | golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect 55 | golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 // indirect 56 | golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect 57 | golang.org/x/text v0.3.7 // indirect 58 | golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect 59 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 60 | gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect 61 | google.golang.org/appengine v1.6.7 // indirect 62 | google.golang.org/protobuf v1.27.1 // indirect 63 | gopkg.in/inf.v0 v0.9.1 // indirect 64 | gopkg.in/yaml.v2 v2.4.0 // indirect 65 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 66 | k8s.io/apiextensions-apiserver v0.23.0 // indirect 67 | k8s.io/component-base v0.23.0 // indirect 68 | k8s.io/klog/v2 v2.30.0 // indirect 69 | k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect 70 | k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect 71 | sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect 72 | sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect 73 | sigs.k8s.io/yaml v1.3.0 // indirect 74 | ) 75 | -------------------------------------------------------------------------------- /pkg/resource/serverless_cache_snapshot/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 serverless_cache_snapshot 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) { 47 | delta.Add("Spec.KMSKeyID", a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) 48 | } else if a.ko.Spec.KMSKeyID != nil && b.ko.Spec.KMSKeyID != nil { 49 | if *a.ko.Spec.KMSKeyID != *b.ko.Spec.KMSKeyID { 50 | delta.Add("Spec.KMSKeyID", a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) 51 | } 52 | } 53 | if !reflect.DeepEqual(a.ko.Spec.KMSKeyRef, b.ko.Spec.KMSKeyRef) { 54 | delta.Add("Spec.KMSKeyRef", a.ko.Spec.KMSKeyRef, b.ko.Spec.KMSKeyRef) 55 | } 56 | if ackcompare.HasNilDifference(a.ko.Spec.ServerlessCacheName, b.ko.Spec.ServerlessCacheName) { 57 | delta.Add("Spec.ServerlessCacheName", a.ko.Spec.ServerlessCacheName, b.ko.Spec.ServerlessCacheName) 58 | } else if a.ko.Spec.ServerlessCacheName != nil && b.ko.Spec.ServerlessCacheName != nil { 59 | if *a.ko.Spec.ServerlessCacheName != *b.ko.Spec.ServerlessCacheName { 60 | delta.Add("Spec.ServerlessCacheName", a.ko.Spec.ServerlessCacheName, b.ko.Spec.ServerlessCacheName) 61 | } 62 | } 63 | if !reflect.DeepEqual(a.ko.Spec.ServerlessCacheRef, b.ko.Spec.ServerlessCacheRef) { 64 | delta.Add("Spec.ServerlessCacheRef", a.ko.Spec.ServerlessCacheRef, b.ko.Spec.ServerlessCacheRef) 65 | } 66 | if ackcompare.HasNilDifference(a.ko.Spec.ServerlessCacheSnapshotName, b.ko.Spec.ServerlessCacheSnapshotName) { 67 | delta.Add("Spec.ServerlessCacheSnapshotName", a.ko.Spec.ServerlessCacheSnapshotName, b.ko.Spec.ServerlessCacheSnapshotName) 68 | } else if a.ko.Spec.ServerlessCacheSnapshotName != nil && b.ko.Spec.ServerlessCacheSnapshotName != nil { 69 | if *a.ko.Spec.ServerlessCacheSnapshotName != *b.ko.Spec.ServerlessCacheSnapshotName { 70 | delta.Add("Spec.ServerlessCacheSnapshotName", a.ko.Spec.ServerlessCacheSnapshotName, b.ko.Spec.ServerlessCacheSnapshotName) 71 | } 72 | } 73 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 74 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 75 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 76 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 77 | } 78 | 79 | return delta 80 | } 81 | -------------------------------------------------------------------------------- /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 e2e import bootstrap_directory 20 | import yaml 21 | import logging 22 | from pathlib import Path 23 | 24 | @dataclass 25 | class TestBootstrapResources: 26 | SnsTopic1: str 27 | SnsTopic2: str 28 | SecurityGroup1: str 29 | SecurityGroup2: str 30 | UserGroup1: str 31 | UserGroup2: str 32 | KmsKeyID: str 33 | SnapshotName: str 34 | NonDefaultUser: str 35 | CWLogGroup1: str 36 | CWLogGroup2: str 37 | CPGName: str 38 | 39 | def replacement_dict(self): 40 | return { 41 | "SNS_TOPIC_ARN": self.SnsTopic1, 42 | "SNS_TOPIC_ARN_2": self.SnsTopic2, 43 | "SG_ID": self.SecurityGroup1, 44 | "SG_ID_2": self.SecurityGroup2, 45 | "USERGROUP_ID": self.UserGroup1, 46 | "USERGROUP_ID_2": self.UserGroup2, 47 | "KMS_KEY_ID": self.KmsKeyID, 48 | "SNAPSHOT_NAME": self.SnapshotName, 49 | "NON_DEFAULT_USER": self.NonDefaultUser, 50 | "LOG_GROUP": self.CWLogGroup1, 51 | "LOG_GROUP_2": self.CWLogGroup2, 52 | "CACHE_PARAMETER_GROUP_NAME": self.CPGName 53 | } 54 | 55 | _bootstrap_resources = None 56 | 57 | 58 | def get_bootstrap_resources(bootstrap_file_name: str = "bootstrap.yaml"): 59 | global _bootstrap_resources 60 | if _bootstrap_resources is None: 61 | _bootstrap_resources = TestBootstrapResources( 62 | **read_bootstrap_config(bootstrap_directory, bootstrap_file_name=bootstrap_file_name), 63 | ) 64 | return _bootstrap_resources 65 | 66 | 67 | def write_bootstrap_config(bootstrap: dict, output_path: Path, bootstrap_file_name: str = "bootstrap.yaml"): 68 | """ Dumps the bootstrap object into a YAML file at a given path. 69 | 70 | Args: 71 | bootstrap: The bootstrap object. 72 | output_path: The directory in which to dump the bootstrap yaml. 73 | bootstrap_file_name: The name of the created bootstrap yaml file. 74 | """ 75 | path = output_path / bootstrap_file_name 76 | logging.info(f"Wrote bootstrap to {path}") 77 | with open(path, "w") as stream: 78 | yaml.safe_dump(bootstrap, stream) 79 | 80 | 81 | def read_bootstrap_config(config_dir: Path, bootstrap_file_name: str = "bootstrap.yaml") -> dict: 82 | """ Reads a bootstrap dictionary from a given bootstrap file. 83 | 84 | Args: 85 | config_dir: The directory in which the bootstrap yaml exists. 86 | bootstrap_file_name: The name of the created bootstrap yaml file. 87 | 88 | Returns: 89 | dict: The bootstrap dictionary read from the file. 90 | """ 91 | path = config_dir / bootstrap_file_name 92 | with open(path, "r") as stream: 93 | bootstrap = yaml.safe_load(stream) 94 | return bootstrap -------------------------------------------------------------------------------- /pkg/resource/cache_subnet_group/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 cache_subnet_group 15 | 16 | import ( 17 | "context" 18 | 19 | svcapitypes "github.com/aws-controllers-k8s/elasticache-controller/apis/v1alpha1" 20 | "github.com/aws/aws-sdk-go-v2/aws" 21 | svcsdk "github.com/aws/aws-sdk-go-v2/service/elasticache" 22 | svcsdktypes "github.com/aws/aws-sdk-go-v2/service/elasticache/types" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | ) 25 | 26 | const ( 27 | // The number of minutes worth of events to retrieve. 28 | // 14 days in minutes 29 | eventsDuration = 20160 30 | ) 31 | 32 | func (rm *resourceManager) CustomDescribeCacheSubnetGroupsSetOutput( 33 | ctx context.Context, 34 | r *resource, 35 | resp *svcsdk.DescribeCacheSubnetGroupsOutput, 36 | ko *svcapitypes.CacheSubnetGroup, 37 | ) (*svcapitypes.CacheSubnetGroup, error) { 38 | if len(resp.CacheSubnetGroups) == 0 { 39 | return ko, nil 40 | } 41 | elem := resp.CacheSubnetGroups[0] 42 | err := rm.customSetOutputSupplementAPIs(ctx, r, &elem, ko) 43 | if err != nil { 44 | return nil, err 45 | } 46 | return ko, nil 47 | } 48 | 49 | func (rm *resourceManager) customSetOutputSupplementAPIs( 50 | ctx context.Context, 51 | r *resource, 52 | subnetGroup *svcsdktypes.CacheSubnetGroup, 53 | ko *svcapitypes.CacheSubnetGroup, 54 | ) error { 55 | events, err := rm.provideEvents(ctx, r.ko.Spec.CacheSubnetGroupName, 20) 56 | if err != nil { 57 | return err 58 | } 59 | ko.Status.Events = events 60 | return nil 61 | } 62 | 63 | func (rm *resourceManager) provideEvents( 64 | ctx context.Context, 65 | subnetGroupName *string, 66 | maxRecords int64, 67 | ) ([]*svcapitypes.Event, error) { 68 | input := &svcsdk.DescribeEventsInput{} 69 | input.SourceType = svcsdktypes.SourceTypeCacheSubnetGroup 70 | input.SourceIdentifier = subnetGroupName 71 | input.MaxRecords = aws.Int32(int32(maxRecords)) 72 | input.Duration = aws.Int32(eventsDuration) 73 | resp, err := rm.sdkapi.DescribeEvents(ctx, input) 74 | rm.metrics.RecordAPICall("READ_MANY", "DescribeEvents-CacheSubnetGroup", err) 75 | if err != nil { 76 | rm.log.V(1).Info("Error during DescribeEvents-CacheSubnetGroup", "error", err) 77 | return nil, err 78 | } 79 | events := []*svcapitypes.Event{} 80 | if resp.Events != nil { 81 | for _, respEvent := range resp.Events { 82 | event := &svcapitypes.Event{} 83 | if respEvent.Message != nil { 84 | event.Message = respEvent.Message 85 | } 86 | if respEvent.Date != nil { 87 | eventDate := metav1.NewTime(*respEvent.Date) 88 | event.Date = &eventDate 89 | } 90 | // Not copying redundant source id (replication id) 91 | // and source type (replication group) 92 | // into each event object 93 | events = append(events, event) 94 | } 95 | } 96 | return events, nil 97 | } 98 | 99 | func Int32OrNil(i *int64) *int32 { 100 | if i == nil { 101 | return nil 102 | } 103 | return aws.Int32(int32(*i)) 104 | } 105 | -------------------------------------------------------------------------------- /pkg/resource/user/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 user 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/elasticache-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/snapshot/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 snapshot 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/elasticache-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/user/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 user 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.AccessString, b.ko.Spec.AccessString) { 47 | delta.Add("Spec.AccessString", a.ko.Spec.AccessString, b.ko.Spec.AccessString) 48 | } else if a.ko.Spec.AccessString != nil && b.ko.Spec.AccessString != nil { 49 | if *a.ko.Spec.AccessString != *b.ko.Spec.AccessString { 50 | delta.Add("Spec.AccessString", a.ko.Spec.AccessString, b.ko.Spec.AccessString) 51 | } 52 | } 53 | if ackcompare.HasNilDifference(a.ko.Spec.Engine, b.ko.Spec.Engine) { 54 | delta.Add("Spec.Engine", a.ko.Spec.Engine, b.ko.Spec.Engine) 55 | } else if a.ko.Spec.Engine != nil && b.ko.Spec.Engine != nil { 56 | if *a.ko.Spec.Engine != *b.ko.Spec.Engine { 57 | delta.Add("Spec.Engine", a.ko.Spec.Engine, b.ko.Spec.Engine) 58 | } 59 | } 60 | if ackcompare.HasNilDifference(a.ko.Spec.NoPasswordRequired, b.ko.Spec.NoPasswordRequired) { 61 | delta.Add("Spec.NoPasswordRequired", a.ko.Spec.NoPasswordRequired, b.ko.Spec.NoPasswordRequired) 62 | } else if a.ko.Spec.NoPasswordRequired != nil && b.ko.Spec.NoPasswordRequired != nil { 63 | if *a.ko.Spec.NoPasswordRequired != *b.ko.Spec.NoPasswordRequired { 64 | delta.Add("Spec.NoPasswordRequired", a.ko.Spec.NoPasswordRequired, b.ko.Spec.NoPasswordRequired) 65 | } 66 | } 67 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 68 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 69 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 70 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 71 | } 72 | if ackcompare.HasNilDifference(a.ko.Spec.UserID, b.ko.Spec.UserID) { 73 | delta.Add("Spec.UserID", a.ko.Spec.UserID, b.ko.Spec.UserID) 74 | } else if a.ko.Spec.UserID != nil && b.ko.Spec.UserID != nil { 75 | if *a.ko.Spec.UserID != *b.ko.Spec.UserID { 76 | delta.Add("Spec.UserID", a.ko.Spec.UserID, b.ko.Spec.UserID) 77 | } 78 | } 79 | if ackcompare.HasNilDifference(a.ko.Spec.UserName, b.ko.Spec.UserName) { 80 | delta.Add("Spec.UserName", a.ko.Spec.UserName, b.ko.Spec.UserName) 81 | } else if a.ko.Spec.UserName != nil && b.ko.Spec.UserName != nil { 82 | if *a.ko.Spec.UserName != *b.ko.Spec.UserName { 83 | delta.Add("Spec.UserName", a.ko.Spec.UserName, b.ko.Spec.UserName) 84 | } 85 | } 86 | 87 | filterDelta(delta, a, b) 88 | return delta 89 | } 90 | -------------------------------------------------------------------------------- /pkg/resource/user_group/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 user_group 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/elasticache-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/cache_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 cache_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/elasticache-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/serverless_cache/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 serverless_cache 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/elasticache-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/cache_subnet_group/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 cache_subnet_group 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/elasticache-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/replication_group/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 replication_group 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/elasticache-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/cache_parameter_group/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 cache_parameter_group 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.CacheParameterGroupFamily, b.ko.Spec.CacheParameterGroupFamily) { 47 | delta.Add("Spec.CacheParameterGroupFamily", a.ko.Spec.CacheParameterGroupFamily, b.ko.Spec.CacheParameterGroupFamily) 48 | } else if a.ko.Spec.CacheParameterGroupFamily != nil && b.ko.Spec.CacheParameterGroupFamily != nil { 49 | if *a.ko.Spec.CacheParameterGroupFamily != *b.ko.Spec.CacheParameterGroupFamily { 50 | delta.Add("Spec.CacheParameterGroupFamily", a.ko.Spec.CacheParameterGroupFamily, b.ko.Spec.CacheParameterGroupFamily) 51 | } 52 | } 53 | if ackcompare.HasNilDifference(a.ko.Spec.CacheParameterGroupName, b.ko.Spec.CacheParameterGroupName) { 54 | delta.Add("Spec.CacheParameterGroupName", a.ko.Spec.CacheParameterGroupName, b.ko.Spec.CacheParameterGroupName) 55 | } else if a.ko.Spec.CacheParameterGroupName != nil && b.ko.Spec.CacheParameterGroupName != nil { 56 | if *a.ko.Spec.CacheParameterGroupName != *b.ko.Spec.CacheParameterGroupName { 57 | delta.Add("Spec.CacheParameterGroupName", a.ko.Spec.CacheParameterGroupName, b.ko.Spec.CacheParameterGroupName) 58 | } 59 | } 60 | if ackcompare.HasNilDifference(a.ko.Spec.Description, b.ko.Spec.Description) { 61 | delta.Add("Spec.Description", a.ko.Spec.Description, b.ko.Spec.Description) 62 | } else if a.ko.Spec.Description != nil && b.ko.Spec.Description != nil { 63 | if *a.ko.Spec.Description != *b.ko.Spec.Description { 64 | delta.Add("Spec.Description", a.ko.Spec.Description, b.ko.Spec.Description) 65 | } 66 | } 67 | if len(a.ko.Spec.ParameterNameValues) != len(b.ko.Spec.ParameterNameValues) { 68 | delta.Add("Spec.ParameterNameValues", a.ko.Spec.ParameterNameValues, b.ko.Spec.ParameterNameValues) 69 | } else if len(a.ko.Spec.ParameterNameValues) > 0 { 70 | if !reflect.DeepEqual(a.ko.Spec.ParameterNameValues, b.ko.Spec.ParameterNameValues) { 71 | delta.Add("Spec.ParameterNameValues", a.ko.Spec.ParameterNameValues, b.ko.Spec.ParameterNameValues) 72 | } 73 | } 74 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 75 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 76 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 77 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 78 | } 79 | 80 | return delta 81 | } 82 | -------------------------------------------------------------------------------- /pkg/resource/cache_parameter_group/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 cache_parameter_group 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/elasticache-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/serverless_cache_snapshot/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 serverless_cache_snapshot 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/elasticache-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/serverless_cache_snapshot/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 serverless_cache_snapshot 15 | 16 | import ( 17 | "context" 18 | "fmt" 19 | "time" 20 | 21 | svcapitypes "github.com/aws-controllers-k8s/elasticache-controller/apis/v1alpha1" 22 | "github.com/aws-controllers-k8s/elasticache-controller/pkg/util" 23 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 24 | ackrequeue "github.com/aws-controllers-k8s/runtime/pkg/requeue" 25 | ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log" 26 | ) 27 | 28 | const ( 29 | ServerlessCacheSnapshotStatusAvailable = "available" 30 | ) 31 | 32 | var requeueWaitUntilCanModify = 10 * time.Second 33 | 34 | // customUpdateServerlessCacheSnapshot handles updates for serverless cache snapshots. 35 | // Since immutable fields are enforced by generator configuration, this method 36 | // only needs to handle tag updates. 37 | func (rm *resourceManager) customUpdateServerlessCacheSnapshot( 38 | ctx context.Context, 39 | desired *resource, 40 | latest *resource, 41 | delta *ackcompare.Delta, 42 | ) (updated *resource, err error) { 43 | rlog := ackrtlog.FromContext(ctx) 44 | exit := rlog.Trace("rm.customUpdateServerlessCacheSnapshot") 45 | defer func() { exit(err) }() 46 | 47 | // Check if the snapshot is in a state that allows updates 48 | if !isServerlessCacheSnapshotAvailable(latest) { 49 | return desired, ackrequeue.NeededAfter( 50 | fmt.Errorf("snapshot not in active state"), 51 | requeueWaitUntilCanModify, 52 | ) 53 | } 54 | 55 | ko := desired.ko.DeepCopy() 56 | rm.setStatusDefaults(ko) 57 | 58 | // Handle tag updates 59 | if delta.DifferentAt("Spec.Tags") { 60 | if err := rm.syncTags(ctx, desired, latest); err != nil { 61 | return &resource{ko}, err 62 | } 63 | return &resource{ko}, nil 64 | } 65 | 66 | return latest, nil 67 | } 68 | 69 | // isServerlessCacheSnapshotAvailable returns true if the snapshot is in a state 70 | // that allows modifications (currently only tag updates) 71 | func isServerlessCacheSnapshotAvailable(r *resource) bool { 72 | if r.ko.Status.Status == nil { 73 | return false 74 | } 75 | status := *r.ko.Status.Status 76 | return status == ServerlessCacheSnapshotStatusAvailable 77 | } 78 | 79 | // getTags retrieves the tags for a given ServerlessCacheSnapshot 80 | func (rm *resourceManager) getTags( 81 | ctx context.Context, 82 | resourceARN string, 83 | ) ([]*svcapitypes.Tag, error) { 84 | return util.GetTags(ctx, rm.sdkapi, rm.metrics, resourceARN) 85 | } 86 | 87 | // syncTags synchronizes the tags between the resource spec and the AWS resource 88 | func (rm *resourceManager) syncTags( 89 | ctx context.Context, 90 | desired *resource, 91 | latest *resource, 92 | ) error { 93 | if latest.ko.Status.ACKResourceMetadata == nil || latest.ko.Status.ACKResourceMetadata.ARN == nil { 94 | return nil 95 | } 96 | 97 | return util.SyncTags( 98 | ctx, 99 | desired.ko.Spec.Tags, 100 | latest.ko.Spec.Tags, 101 | latest.ko.Status.ACKResourceMetadata, 102 | convertToOrderedACKTags, 103 | rm.sdkapi, 104 | rm.metrics, 105 | ) 106 | } 107 | -------------------------------------------------------------------------------- /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-elasticache-controller 10 | namespace: ack-system 11 | labels: 12 | app.kubernetes.io/name: ack-elasticache-controller 13 | app.kubernetes.io/part-of: ack-system 14 | spec: 15 | selector: 16 | matchLabels: 17 | app.kubernetes.io/name: ack-elasticache-controller 18 | replicas: 1 19 | template: 20 | metadata: 21 | labels: 22 | app.kubernetes.io/name: ack-elasticache-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-elasticache-controller 110 | hostIPC: false 111 | hostPID: false 112 | hostNetwork: false 113 | dnsPolicy: ClusterFirst 114 | -------------------------------------------------------------------------------- /apis/v1alpha1/user_group.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 | // UserGroupSpec defines the desired state of UserGroup. 24 | // 25 | 26 | type UserGroupSpec struct { 27 | 28 | // The current supported value is Redis user. 29 | // 30 | // Regex Pattern: `^[a-zA-Z]*$` 31 | // +kubebuilder:validation:Required 32 | Engine *string `json:"engine"` 33 | // A list of tags to be added to this resource. A tag is a key-value pair. A 34 | // tag key must be accompanied by a tag value, although null is accepted. Available 35 | // for Valkey and Redis OSS only. 36 | Tags []*Tag `json:"tags,omitempty"` 37 | // The ID of the user group. 38 | // +kubebuilder:validation:Required 39 | UserGroupID *string `json:"userGroupID"` 40 | // The list of user IDs that belong to the user group. 41 | UserIDs []*string `json:"userIDs,omitempty"` 42 | } 43 | 44 | // UserGroupStatus defines the observed state of UserGroup 45 | type UserGroupStatus struct { 46 | // All CRs managed by ACK have a common `Status.ACKResourceMetadata` member 47 | // that is used to contain resource sync state, account ownership, 48 | // constructed ARN for the resource 49 | // +kubebuilder:validation:Optional 50 | ACKResourceMetadata *ackv1alpha1.ResourceMetadata `json:"ackResourceMetadata"` 51 | // All CRs managed by ACK have a common `Status.Conditions` member that 52 | // contains a collection of `ackv1alpha1.Condition` objects that describe 53 | // the various terminal states of the CR and its backend AWS service API 54 | // resource 55 | // +kubebuilder:validation:Optional 56 | Conditions []*ackv1alpha1.Condition `json:"conditions"` 57 | // The minimum engine version required, which is Redis OSS 6.0 58 | // +kubebuilder:validation:Optional 59 | MinimumEngineVersion *string `json:"minimumEngineVersion,omitempty"` 60 | // A list of updates being applied to the user group. 61 | // +kubebuilder:validation:Optional 62 | PendingChanges *UserGroupPendingChanges `json:"pendingChanges,omitempty"` 63 | // A list of replication groups that the user group can access. 64 | // +kubebuilder:validation:Optional 65 | ReplicationGroups []*string `json:"replicationGroups,omitempty"` 66 | // Indicates user group status. Can be "creating", "active", "modifying", "deleting". 67 | // +kubebuilder:validation:Optional 68 | Status *string `json:"status,omitempty"` 69 | } 70 | 71 | // UserGroup is the Schema for the UserGroups API 72 | // +kubebuilder:object:root=true 73 | // +kubebuilder:subresource:status 74 | type UserGroup struct { 75 | metav1.TypeMeta `json:",inline"` 76 | metav1.ObjectMeta `json:"metadata,omitempty"` 77 | Spec UserGroupSpec `json:"spec,omitempty"` 78 | Status UserGroupStatus `json:"status,omitempty"` 79 | } 80 | 81 | // UserGroupList contains a list of UserGroup 82 | // +kubebuilder:object:root=true 83 | type UserGroupList struct { 84 | metav1.TypeMeta `json:",inline"` 85 | metav1.ListMeta `json:"metadata,omitempty"` 86 | Items []UserGroup `json:"items"` 87 | } 88 | 89 | func init() { 90 | SchemeBuilder.Register(&UserGroup{}, &UserGroupList{}) 91 | } 92 | -------------------------------------------------------------------------------- /pkg/resource/snapshot/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 snapshot 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 | 46 | if ackcompare.HasNilDifference(a.ko.Spec.CacheClusterID, b.ko.Spec.CacheClusterID) { 47 | delta.Add("Spec.CacheClusterID", a.ko.Spec.CacheClusterID, b.ko.Spec.CacheClusterID) 48 | } else if a.ko.Spec.CacheClusterID != nil && b.ko.Spec.CacheClusterID != nil { 49 | if *a.ko.Spec.CacheClusterID != *b.ko.Spec.CacheClusterID { 50 | delta.Add("Spec.CacheClusterID", a.ko.Spec.CacheClusterID, b.ko.Spec.CacheClusterID) 51 | } 52 | } 53 | if ackcompare.HasNilDifference(a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) { 54 | delta.Add("Spec.KMSKeyID", a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) 55 | } else if a.ko.Spec.KMSKeyID != nil && b.ko.Spec.KMSKeyID != nil { 56 | if *a.ko.Spec.KMSKeyID != *b.ko.Spec.KMSKeyID { 57 | delta.Add("Spec.KMSKeyID", a.ko.Spec.KMSKeyID, b.ko.Spec.KMSKeyID) 58 | } 59 | } 60 | if ackcompare.HasNilDifference(a.ko.Spec.ReplicationGroupID, b.ko.Spec.ReplicationGroupID) { 61 | delta.Add("Spec.ReplicationGroupID", a.ko.Spec.ReplicationGroupID, b.ko.Spec.ReplicationGroupID) 62 | } else if a.ko.Spec.ReplicationGroupID != nil && b.ko.Spec.ReplicationGroupID != nil { 63 | if *a.ko.Spec.ReplicationGroupID != *b.ko.Spec.ReplicationGroupID { 64 | delta.Add("Spec.ReplicationGroupID", a.ko.Spec.ReplicationGroupID, b.ko.Spec.ReplicationGroupID) 65 | } 66 | } 67 | if ackcompare.HasNilDifference(a.ko.Spec.SnapshotName, b.ko.Spec.SnapshotName) { 68 | delta.Add("Spec.SnapshotName", a.ko.Spec.SnapshotName, b.ko.Spec.SnapshotName) 69 | } else if a.ko.Spec.SnapshotName != nil && b.ko.Spec.SnapshotName != nil { 70 | if *a.ko.Spec.SnapshotName != *b.ko.Spec.SnapshotName { 71 | delta.Add("Spec.SnapshotName", a.ko.Spec.SnapshotName, b.ko.Spec.SnapshotName) 72 | } 73 | } 74 | if ackcompare.HasNilDifference(a.ko.Spec.SourceSnapshotName, b.ko.Spec.SourceSnapshotName) { 75 | delta.Add("Spec.SourceSnapshotName", a.ko.Spec.SourceSnapshotName, b.ko.Spec.SourceSnapshotName) 76 | } else if a.ko.Spec.SourceSnapshotName != nil && b.ko.Spec.SourceSnapshotName != nil { 77 | if *a.ko.Spec.SourceSnapshotName != *b.ko.Spec.SourceSnapshotName { 78 | delta.Add("Spec.SourceSnapshotName", a.ko.Spec.SourceSnapshotName, b.ko.Spec.SourceSnapshotName) 79 | } 80 | } 81 | desiredACKTags, _ := convertToOrderedACKTags(a.ko.Spec.Tags) 82 | latestACKTags, _ := convertToOrderedACKTags(b.ko.Spec.Tags) 83 | if !ackcompare.MapStringStringEqual(desiredACKTags, latestACKTags) { 84 | delta.Add("Spec.Tags", a.ko.Spec.Tags, b.ko.Spec.Tags) 85 | } 86 | 87 | return delta 88 | } 89 | -------------------------------------------------------------------------------- /apis/v1alpha1/cache_subnet_group.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 | // CacheSubnetGroupSpec defines the desired state of CacheSubnetGroup. 24 | // 25 | // Represents the output of one of the following operations: 26 | // 27 | // - CreateCacheSubnetGroup 28 | // 29 | // - ModifyCacheSubnetGroup 30 | type CacheSubnetGroupSpec struct { 31 | 32 | // A description for the cache subnet group. 33 | // +kubebuilder:validation:Required 34 | CacheSubnetGroupDescription *string `json:"cacheSubnetGroupDescription"` 35 | // A name for the cache subnet group. This value is stored as a lowercase string. 36 | // 37 | // Constraints: Must contain no more than 255 alphanumeric characters or hyphens. 38 | // 39 | // Example: mysubnetgroup 40 | // +kubebuilder:validation:Required 41 | CacheSubnetGroupName *string `json:"cacheSubnetGroupName"` 42 | // A list of VPC subnet IDs for the cache subnet group. 43 | SubnetIDs []*string `json:"subnetIDs,omitempty"` 44 | SubnetRefs []*ackv1alpha1.AWSResourceReferenceWrapper `json:"subnetRefs,omitempty"` 45 | // A list of tags to be added to this resource. A tag is a key-value pair. A 46 | // tag key must be accompanied by a tag value, although null is accepted. 47 | Tags []*Tag `json:"tags,omitempty"` 48 | } 49 | 50 | // CacheSubnetGroupStatus defines the observed state of CacheSubnetGroup 51 | type CacheSubnetGroupStatus struct { 52 | // All CRs managed by ACK have a common `Status.ACKResourceMetadata` member 53 | // that is used to contain resource sync state, account ownership, 54 | // constructed ARN for the resource 55 | // +kubebuilder:validation:Optional 56 | ACKResourceMetadata *ackv1alpha1.ResourceMetadata `json:"ackResourceMetadata"` 57 | // All CRs managed by ACK have a common `Status.Conditions` member that 58 | // contains a collection of `ackv1alpha1.Condition` objects that describe 59 | // the various terminal states of the CR and its backend AWS service API 60 | // resource 61 | // +kubebuilder:validation:Optional 62 | Conditions []*ackv1alpha1.Condition `json:"conditions"` 63 | // A list of events. Each element in the list contains detailed information 64 | // about one event. 65 | // +kubebuilder:validation:Optional 66 | Events []*Event `json:"events,omitempty"` 67 | // A list of subnets associated with the cache subnet group. 68 | // +kubebuilder:validation:Optional 69 | Subnets []*Subnet `json:"subnets,omitempty"` 70 | // The Amazon Virtual Private Cloud identifier (VPC ID) of the cache subnet 71 | // group. 72 | // +kubebuilder:validation:Optional 73 | VPCID *string `json:"vpcID,omitempty"` 74 | } 75 | 76 | // CacheSubnetGroup is the Schema for the CacheSubnetGroups API 77 | // +kubebuilder:object:root=true 78 | // +kubebuilder:subresource:status 79 | type CacheSubnetGroup struct { 80 | metav1.TypeMeta `json:",inline"` 81 | metav1.ObjectMeta `json:"metadata,omitempty"` 82 | Spec CacheSubnetGroupSpec `json:"spec,omitempty"` 83 | Status CacheSubnetGroupStatus `json:"status,omitempty"` 84 | } 85 | 86 | // CacheSubnetGroupList contains a list of CacheSubnetGroup 87 | // +kubebuilder:object:root=true 88 | type CacheSubnetGroupList struct { 89 | metav1.TypeMeta `json:",inline"` 90 | metav1.ListMeta `json:"metadata,omitempty"` 91 | Items []CacheSubnetGroup `json:"items"` 92 | } 93 | 94 | func init() { 95 | SchemeBuilder.Register(&CacheSubnetGroup{}, &CacheSubnetGroupList{}) 96 | } 97 | -------------------------------------------------------------------------------- /pkg/resource/user/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 user 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/elasticache-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.User 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.UserID = &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 | f3, ok := fields["userID"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: userID")) 103 | } 104 | r.ko.Spec.UserID = &f3 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 | -------------------------------------------------------------------------------- /pkg/resource/snapshot/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 snapshot 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/elasticache-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.Snapshot 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.SnapshotName = &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 | f3, ok := fields["snapshotName"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: snapshotName")) 103 | } 104 | r.ko.Spec.SnapshotName = &f3 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 | -------------------------------------------------------------------------------- /pkg/resource/user_group/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 user_group 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/elasticache-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.UserGroup 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.UserGroupID = &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 | f2, ok := fields["userGroupID"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: userGroupID")) 103 | } 104 | r.ko.Spec.UserGroupID = &f2 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 | -------------------------------------------------------------------------------- /pkg/resource/cache_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 cache_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/elasticache-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.CacheCluster 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.CacheClusterID = &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["cacheClusterID"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: cacheClusterID")) 103 | } 104 | r.ko.Spec.CacheClusterID = &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 | -------------------------------------------------------------------------------- /pkg/resource/replication_group/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 replication_group 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/elasticache-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.ReplicationGroup 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.ReplicationGroupID = &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 | f2, ok := fields["replicationGroupID"] 101 | if !ok { 102 | return ackerrors.NewTerminalError(fmt.Errorf("required field missing: replicationGroupID")) 103 | } 104 | r.ko.Spec.ReplicationGroupID = &f2 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 | --------------------------------------------------------------------------------