├── .codespellrc ├── .github └── workflows │ └── create-release.yml ├── .gitignore ├── ATTRIBUTION.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile.local ├── GOVERNANCE.md ├── LICENSE ├── Makefile ├── NOTICE ├── OWNERS ├── OWNERS_ALIASES ├── README.md ├── cmd └── ack-generate │ ├── README.md │ ├── command │ ├── apis.go │ ├── common.go │ ├── controller.go │ ├── crossplane.go │ ├── olm.go │ ├── release.go │ ├── root.go │ └── version.go │ └── main.go ├── go.mod ├── go.sum ├── pkg ├── api │ ├── api.go │ ├── api_test.go │ ├── codegentest │ │ ├── models │ │ │ ├── awsquerycompatible │ │ │ │ └── api-2.json │ │ │ ├── endpointdiscovery │ │ │ │ └── 0000-00-00 │ │ │ │ │ ├── api-2.json │ │ │ │ │ └── docs-2.json │ │ │ ├── jsonrpc │ │ │ │ └── 0000-00-00 │ │ │ │ │ ├── api-2.json │ │ │ │ │ └── docs-2.json │ │ │ ├── restjson │ │ │ │ └── 0000-00-00 │ │ │ │ │ ├── api-2.json │ │ │ │ │ └── docs-2.json │ │ │ └── restxml │ │ │ │ └── 0000-00-00 │ │ │ │ ├── api-2.json │ │ │ │ └── docs-2.json │ │ └── service │ │ │ ├── awsendpointdiscoverytest │ │ │ ├── api.go │ │ │ ├── awsendpointdiscoverytestiface │ │ │ │ └── interface.go │ │ │ ├── doc.go │ │ │ ├── endpoint_discovery_test.go │ │ │ ├── errors.go │ │ │ └── service.go │ │ │ ├── awsquerycompatible │ │ │ ├── api.go │ │ │ ├── awsquerycompatible_test.go │ │ │ ├── awsquerycompatibleiface │ │ │ │ └── interface.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ └── service.go │ │ │ ├── generate.go │ │ │ ├── restjsonservice │ │ │ ├── api.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── eventstream_test.go │ │ │ ├── restjsonserviceiface │ │ │ │ └── interface.go │ │ │ └── service.go │ │ │ ├── restxmlservice │ │ │ ├── api.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── eventstream_test.go │ │ │ ├── restxmlserviceiface │ │ │ │ └── interface.go │ │ │ └── service.go │ │ │ └── rpcservice │ │ │ ├── api.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── eventstream_test.go │ │ │ ├── rpcserviceiface │ │ │ └── interface.go │ │ │ └── service.go │ ├── customization_passes.go │ ├── docstring.go │ ├── docstring_test.go │ ├── endpoint_arn.go │ ├── endpoint_trait.go │ ├── eventstream.go │ ├── eventstream_tmpl.go │ ├── eventstream_tmpl_reader.go │ ├── eventstream_tmpl_readertests.go │ ├── eventstream_tmpl_tests.go │ ├── eventstream_tmpl_writer.go │ ├── eventstream_tmpl_writertests.go │ ├── example.go │ ├── example_test.go │ ├── examples_builder.go │ ├── examples_builder_customizations.go │ ├── exportable_name.go │ ├── legacy_io_suffix.go │ ├── legacy_jsonvalue.go │ ├── legacy_struct_names.go │ ├── legacy_stutter.go │ ├── list_of_shame.go │ ├── load.go │ ├── load_test.go │ ├── logger.go │ ├── operation.go │ ├── pagination.go │ ├── param_filler.go │ ├── passes.go │ ├── passes_test.go │ ├── s3manger_input.go │ ├── service_name.go │ ├── shape.go │ ├── shape_alias.go │ ├── shape_validation.go │ ├── shape_value_builder.go │ ├── shapetag_test.go │ ├── smoke.go │ └── waiters.go ├── apiv2 │ ├── converter.go │ └── remove_defaults.go ├── config │ ├── config.go │ ├── documentation.go │ ├── field.go │ ├── operation.go │ ├── resource.go │ └── version.go ├── fieldpath │ ├── path.go │ └── path_test.go ├── generate │ ├── ack │ │ ├── apis.go │ │ ├── config.go │ │ ├── controller.go │ │ ├── hook.go │ │ ├── hook_test.go │ │ ├── release.go │ │ ├── runtime_test.go │ │ └── testdata │ │ │ └── templates │ │ │ └── sdk_delete_pre_build_request.go.tpl │ ├── code │ │ ├── check.go │ │ ├── check_test.go │ │ ├── common.go │ │ ├── common_test.go │ │ ├── compare.go │ │ ├── compare_test.go │ │ ├── initialize_field.go │ │ ├── initialize_field_test.go │ │ ├── late_initialize.go │ │ ├── late_initialize_test.go │ │ ├── resource_reference.go │ │ ├── resource_reference_test.go │ │ ├── set_resource.go │ │ ├── set_resource_test.go │ │ ├── set_sdk.go │ │ ├── set_sdk_test.go │ │ ├── set_sdk_whitebox_test.go │ │ ├── synced.go │ │ ├── synced_test.go │ │ ├── tags.go │ │ └── tags_test.go │ ├── crossplane │ │ ├── config.go │ │ └── crossplane.go │ ├── olm │ │ ├── olm.go │ │ └── types.go │ └── templateset │ │ ├── templateset.go │ │ └── vars.go ├── metadata │ ├── api_info.go │ ├── generation_metadata.go │ └── service_metadata.go ├── model │ ├── attr.go │ ├── crd.go │ ├── enum_def.go │ ├── enum_def_test.go │ ├── error.go │ ├── field.go │ ├── field_test.go │ ├── model.go │ ├── model_apigwv2_test.go │ ├── model_codedeploy_test.go │ ├── model_dynamodb_test.go │ ├── model_ec2_test.go │ ├── model_ecr_test.go │ ├── model_eks_test.go │ ├── model_elasticache_test.go │ ├── model_emrcontainers_test.go │ ├── model_lambda_test.go │ ├── model_memorydb_test.go │ ├── model_mq_test.go │ ├── model_rds_test.go │ ├── model_route53_test.go │ ├── model_s3_test.go │ ├── model_sagemaker_test.go │ ├── model_sns_test.go │ ├── model_sqs_test.go │ ├── multiversion │ │ ├── delta.go │ │ ├── delta_renames.go │ │ ├── delta_renames_test.go │ │ ├── delta_test.go │ │ └── manager.go │ ├── op.go │ ├── op_test.go │ ├── printer_column.go │ ├── sdk_api.go │ ├── tagging.go │ ├── type_def.go │ ├── types.go │ ├── types_test.go │ └── util_test.go ├── sdk │ ├── custom_shapes.go │ ├── custom_shapes_test.go │ ├── helper.go │ ├── helper_test.go │ └── repo.go ├── testdata │ ├── codegen │ │ └── sdk-codegen │ │ │ └── aws-models │ │ │ ├── apigatewayv2.json │ │ │ ├── codedeploy.json │ │ │ ├── dynamodb.json │ │ │ ├── ec2.json │ │ │ ├── ecr.json │ │ │ ├── eks.json │ │ │ ├── elasticache.json │ │ │ ├── emrcontainers.json │ │ │ ├── eventbridge.json │ │ │ ├── iam.json │ │ │ ├── lambda.json │ │ │ ├── memorydb.json │ │ │ ├── mq.json │ │ │ ├── opensearch.json │ │ │ ├── rds.json │ │ │ ├── route53.json │ │ │ ├── s3.json │ │ │ ├── sagemaker.json │ │ │ ├── sns.json │ │ │ ├── sqs.json │ │ │ └── wafv2.json │ └── models │ │ ├── apis │ │ ├── apigatewayv2 │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-with-nested-reference.yaml │ │ │ │ ├── generator-with-reference.yaml │ │ │ │ └── generator.yaml │ │ ├── codedeploy │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── dynamodb │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-with-custom-shapes.yaml │ │ │ │ └── generator.yaml │ │ ├── ec2 │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-with-nested-references.yaml │ │ │ │ └── generator.yaml │ │ ├── ecr │ │ │ ├── 0000-00-00 │ │ │ │ ├── generator-renamed-identifier-field.yaml │ │ │ │ ├── generator-v1alpha1.yaml │ │ │ │ ├── generator-v1alpha2.yaml │ │ │ │ ├── generator-v1alpha3.yaml │ │ │ │ ├── generator-with-field-config.yaml │ │ │ │ ├── generator-with-late-initialize.yaml │ │ │ │ ├── generator-with-nested-path-late-initialize.yaml │ │ │ │ └── generator.yaml │ │ │ └── 0000-00-01 │ │ │ │ ├── generator-v1beta1.yaml │ │ │ │ └── generator-v1beta2.yaml │ │ ├── eks │ │ │ └── 0000-00-00 │ │ │ │ ├── documentation.yaml │ │ │ │ ├── generator-with-gotag.yaml │ │ │ │ ├── generator-with-nested-reference.yaml │ │ │ │ └── generator.yaml │ │ ├── elasticache │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── emrcontainers │ │ │ └── 0000-00-00 │ │ │ │ └── generator-with-cycle.yaml │ │ ├── eventbridge │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── iam │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-oidc-url.yaml │ │ │ │ ├── generator-user-newpath.yaml │ │ │ │ └── generator.yaml │ │ ├── lambda │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-lambda-ignore-code-sha256.yaml │ │ │ │ ├── generator-with-custom-nested-types.yaml │ │ │ │ └── generator.yaml │ │ ├── memorydb │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── mq │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── opensearch │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── rds │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── route53 │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── s3 │ │ │ └── 0000-00-00 │ │ │ │ ├── generator-with-nested-references.yaml │ │ │ │ ├── generator-with-tags.yaml │ │ │ │ └── generator.yaml │ │ ├── sagemaker │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── sns │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ ├── sqs │ │ │ └── 0000-00-00 │ │ │ │ └── generator.yaml │ │ └── wafv2 │ │ │ └── 0000-00-00 │ │ │ └── generator.yaml │ │ └── metadata.yaml ├── testutil │ ├── get.go │ └── schema_helper.go ├── util │ ├── file.go │ ├── git.go │ └── in.go └── version │ └── version.go ├── scripts ├── build-controller-image.sh ├── build-controller-release.sh ├── build-controller.sh ├── construct-metadata.sh ├── install-controller-gen.sh ├── install-helm.sh ├── install-kustomize.sh ├── install-operator-sdk.sh ├── lib │ ├── aws.sh │ ├── common.sh │ └── metadata.sh ├── olm-build-bundle-image.sh ├── olm-create-bundle.sh └── olm-publish-bundle-image.sh └── templates ├── apis ├── crd.go.tpl ├── doc.go.tpl ├── enum_def.go.tpl ├── enums.go.tpl ├── groupversion_info.go.tpl ├── type_def.go.tpl └── types.go.tpl ├── boilerplate.go.tpl ├── boilerplate.txt ├── boilerplate_hash.go.tpl ├── cmd └── controller │ └── main.go.tpl ├── config ├── controller │ ├── deployment.yaml.tpl │ ├── kustomization.yaml.tpl │ ├── kustomization_def.yaml.tpl │ ├── olm-kustomization.yaml.tpl │ ├── service.yaml.tpl │ └── user-env.yaml.tpl ├── crd │ └── kustomization.yaml.tpl ├── default │ └── kustomization.yaml.tpl ├── manifests │ ├── bases │ │ └── clusterserviceversion.yaml.tpl │ └── kustomization.yaml ├── overlays │ └── namespaced │ │ ├── kustomization.yaml.tpl │ │ ├── role-binding.json │ │ └── role.json ├── rbac │ ├── cluster-role-binding.yaml.tpl │ ├── kustomization.yaml.tpl │ ├── leader-election-role-binding.yaml.tpl │ ├── leader-election-role.yaml.tpl │ ├── role-reader.yaml.tpl │ ├── role-writer.yaml.tpl │ └── service-account.yaml.tpl ├── samples │ ├── kustomization.yaml │ └── sample.yaml.tpl └── scorecard │ ├── bases │ └── config.yaml │ ├── kustomization.yaml │ └── patches │ ├── basic.config.yaml │ └── olm.config.yaml ├── crossplane ├── README.md ├── apis │ ├── crd.go.tpl │ ├── doc.go.tpl │ ├── enum_def.go.tpl │ ├── enums.go.tpl │ ├── groupversion_info.go.tpl │ ├── type_def.go.tpl │ └── types.go.tpl ├── boilerplate.go.tpl └── pkg │ ├── controller.go.tpl │ ├── conversions.go.tpl │ ├── sdk_find_get_attributes.go.tpl │ ├── sdk_find_read_many.go.tpl │ └── sdk_find_read_one.go.tpl ├── helm ├── Chart.yaml.tpl ├── templates │ ├── NOTES.txt.tpl │ ├── _helpers.tpl.tpl │ ├── caches-role-binding.yaml.tpl │ ├── caches-role.yaml.tpl │ ├── cluster-role-binding.yaml.tpl │ ├── cluster-role-controller.yaml.tpl │ ├── deployment.yaml.tpl │ ├── leader-election-role-binding.yaml.tpl │ ├── leader-election-role.yaml.tpl │ ├── metrics-service.yaml.tpl │ ├── role-reader.yaml.tpl │ ├── role-writer.yaml.tpl │ └── service-account.yaml.tpl ├── values.schema.json └── values.yaml.tpl ├── metadata.yaml └── pkg ├── resource ├── delta.go.tpl ├── descriptor.go.tpl ├── identifiers.go.tpl ├── manager.go.tpl ├── manager_factory.go.tpl ├── references.go.tpl ├── references_read_referenced_resource.go.tpl ├── registry.go.tpl ├── resource.go.tpl ├── sdk.go.tpl ├── sdk_delete_custom.go.tpl ├── sdk_find_custom.go.tpl ├── sdk_find_get_attributes.go.tpl ├── sdk_find_not_implemented.go.tpl ├── sdk_find_read_many.go.tpl ├── sdk_find_read_one.go.tpl ├── sdk_update.go.tpl ├── sdk_update_custom.go.tpl ├── sdk_update_not_implemented.go.tpl ├── sdk_update_set_attributes.go.tpl └── tags.go.tpl └── version └── version.go.tpl /.codespellrc: -------------------------------------------------------------------------------- 1 | [codespell] 2 | skip = .codespellrc,./.git,./go.local.sum,./pkg/testdata 3 | ignore-words-list = specfield,uptodate,fpr 4 | check-filenames = 5 | check-hidden = 6 | quiet = 2 7 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~ 4 | .idea 5 | .vscode 6 | /docs/site 7 | bin 8 | build -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Base image to use at runtime 2 | ARG base_image=public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-nonroot 3 | 4 | # Golang image to use for compiling the manager 5 | ARG builder_image=public.ecr.aws/docker/library/golang 6 | 7 | # Version of Golang 8 | ARG golang_version 9 | # Version of eks-distro 10 | ARG eks_distro_version 11 | 12 | # Build the manager binary 13 | FROM $builder_image:$golang_version as builder 14 | 15 | ARG service_alias 16 | ARG target_arch=amd64 17 | # The tuple of controller image version information 18 | ARG service_controller_git_version 19 | ARG service_controller_git_commit 20 | ARG build_date 21 | # The directory within the builder container into which we will copy our 22 | # service controller code. 23 | ARG work_dir=/github.com/aws-controllers-k8s/$service_alias-controller 24 | WORKDIR $work_dir 25 | ENV GOPROXY=https://proxy.golang.org|direct 26 | ENV GO111MODULE=on 27 | ENV GOARCH=$target_arch 28 | ENV GOOS=linux 29 | ENV CGO_ENABLED=0 30 | ENV VERSION_PKG=github.com/aws-controllers-k8s/$service_alias-controller/pkg/version 31 | # Copy the Go Modules manifests and LICENSE/ATTRIBUTION 32 | COPY $service_alias-controller/LICENSE $work_dir/LICENSE 33 | COPY $service_alias-controller/ATTRIBUTION.md $work_dir/ATTRIBUTION.md 34 | # Copy Go mod files 35 | COPY $service_alias-controller/go.mod $work_dir/go.mod 36 | COPY $service_alias-controller/go.sum $work_dir/go.sum 37 | # cache deps before building and copying source so that we don't need to re-download as much 38 | # and so that source changes don't invalidate our downloaded layer 39 | RUN go mod download 40 | 41 | # Now copy the go source code for the controller... 42 | COPY $service_alias-controller/apis $work_dir/apis 43 | COPY $service_alias-controller/cmd $work_dir/cmd 44 | COPY $service_alias-controller/pkg $work_dir/pkg 45 | # Build 46 | RUN GIT_VERSION=$service_controller_git_version && \ 47 | GIT_COMMIT=$service_controller_git_commit && \ 48 | BUILD_DATE=$build_date && \ 49 | go build -ldflags="-X ${VERSION_PKG}.GitVersion=${GIT_VERSION} \ 50 | -X ${VERSION_PKG}.GitCommit=${GIT_COMMIT} \ 51 | -X ${VERSION_PKG}.BuildDate=${BUILD_DATE}" \ 52 | -a -o $work_dir/bin/controller $work_dir/cmd/controller/main.go 53 | 54 | FROM $base_image:$eks_distro_version 55 | ARG base_image 56 | LABEL org.opencontainers.image.base.name=$base_image 57 | ARG service_alias 58 | ARG service_controller_git_version 59 | ARG work_dir=/github.com/aws-controllers-k8s/$service_alias-controller 60 | LABEL org.opencontainers.image.source=https://github.com/aws-controllers-k8s/$service_alias-controller 61 | LABEL org.opencontainers.image.version=$service_controller_git_version 62 | WORKDIR / 63 | COPY --from=builder $work_dir/bin/controller $work_dir/LICENSE $work_dir/ATTRIBUTION.md /bin/ 64 | # Make this image non-root by default 65 | USER 1000 66 | ENTRYPOINT ["/bin/controller"] 67 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash # Use bash syntax 2 | 3 | # Set up variables 4 | GO111MODULE=on 5 | 6 | AWS_SERVICE=$(shell echo $(SERVICE) | tr '[:upper:]' '[:lower:]') 7 | 8 | # Build ldflags 9 | VERSION ?= $(shell git describe --tags --always --dirty) 10 | GITCOMMIT=$(shell git rev-parse HEAD) 11 | BUILDDATE=$(shell date -u +'%Y-%m-%dT%H:%M:%SZ') 12 | IMPORT_PATH=github.com/aws-controllers-k8s/code-generator 13 | GO_LDFLAGS=-ldflags "-X $(IMPORT_PATH)/pkg/version.Version=$(VERSION) \ 14 | -X $(IMPORT_PATH)/pkg/version.BuildHash=$(GITCOMMIT) \ 15 | -X $(IMPORT_PATH)/pkg/version.BuildDate=$(BUILDDATE)" 16 | 17 | # We need to use the codegen tag when building and testing because the 18 | # aws-sdk-go/private/model/api package is gated behind a build tag "codegen"... 19 | GO_CMD_FLAGS=-tags codegen 20 | 21 | .PHONY: all build-ack-generate test \ 22 | build-controller build-controller-image \ 23 | local-build-controller-image lint-shell 24 | 25 | all: test 26 | 27 | build-ack-generate: ## Build ack-generate binary 28 | @echo -n "building ack-generate ... " 29 | @go build ${GO_CMD_FLAGS} ${GO_LDFLAGS} -o bin/ack-generate cmd/ack-generate/main.go 30 | @echo "ok." 31 | 32 | build-controller: build-ack-generate ## Generate controller code for SERVICE 33 | @./scripts/install-controller-gen.sh 34 | @echo "==== building $(AWS_SERVICE)-controller ====" 35 | @./scripts/build-controller.sh $(AWS_SERVICE) 36 | @echo "==== building $(AWS_SERVICE)-controller release artifacts ====" 37 | @./scripts/build-controller-release.sh $(AWS_SERVICE) 38 | 39 | build-controller-image: export LOCAL_MODULES = false 40 | build-controller-image: ## Build container image for SERVICE 41 | @./scripts/build-controller-image.sh $(AWS_SERVICE) 42 | 43 | local-build-controller-image: export LOCAL_MODULES = true 44 | local-build-controller-image: ## Build container image for SERVICE allowing local modules 45 | @./scripts/build-controller-image.sh $(AWS_SERVICE) 46 | 47 | test: ## Run code tests 48 | go test ${GO_CMD_FLAGS} ./... 49 | 50 | lint-shell: ## Run linters against all of the bash scripts 51 | @find . -type f -name "*.sh" | xargs shellcheck -e SC1091 52 | 53 | help: ## Show this help. 54 | @grep -F -h "##" $(MAKEFILE_LIST) | grep -F -v grep | sed -e 's/\\$$//' \ 55 | | awk -F'[:#]' '{print $$1 = sprintf("%-30s", $$1), $$4}' 56 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | 3 | approvers: 4 | - core-ack-team 5 | - brycahta 6 | -------------------------------------------------------------------------------- /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 | # - jaypipes 12 | # - jljaco 13 | # - mhausenblas 14 | # - RedbackThomson 15 | # - TiberiuGC 16 | # - vijtrip2 17 | # - ivelichkovich -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code generation for AWS Controllers for Kubernetes (ACK) 2 | 3 | This repository contains CLI tools and Go packages for generating Kubernetes 4 | custom controllers and AWS SDK linkage. The code generated by this project is 5 | used in the [AWS Controllers for Kubernetes][ack] and Crossplane projects. 6 | 7 | Please [log issues][ack-issues] and feedback on the main AWS Controllers for 8 | Kubernetes Github project. 9 | 10 | [ack]: https://github.com/aws/aws-controllers-k8s 11 | [ack-issues]: https://github.com/aws/aws-controllers-k8s/issues 12 | 13 | ## Contributing 14 | 15 | We welcome community contributions and pull requests. 16 | 17 | See our [contribution guide](/CONTRIBUTING.md) for more information on how to 18 | report issues, set up a development environment, and submit code. 19 | 20 | We adhere to the [Amazon Open Source Code of Conduct][coc]. 21 | 22 | You can also learn more about our [Governance](/GOVERNANCE.md) structure. 23 | 24 | [coc]: https://aws.github.io/code-of-conduct 25 | 26 | ## License 27 | 28 | This project is [licensed](/LICENSE) under the Apache-2.0 License. 29 | -------------------------------------------------------------------------------- /cmd/ack-generate/command/controller.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 command 15 | 16 | import ( 17 | "context" 18 | "fmt" 19 | "io/ioutil" 20 | "path/filepath" 21 | "strings" 22 | 23 | "github.com/spf13/cobra" 24 | 25 | ackgenerate "github.com/aws-controllers-k8s/code-generator/pkg/generate/ack" 26 | ackmetadata "github.com/aws-controllers-k8s/code-generator/pkg/metadata" 27 | "github.com/aws-controllers-k8s/code-generator/pkg/sdk" 28 | ) 29 | 30 | var ( 31 | cmdControllerPath string 32 | pkgResourcePath string 33 | latestAPIVersion string 34 | ) 35 | 36 | var controllerCmd = &cobra.Command{ 37 | Use: "controller ", 38 | Short: "Generates Go files containing service controller implementation for a given service", 39 | RunE: generateController, 40 | } 41 | 42 | func init() { 43 | rootCmd.AddCommand(controllerCmd) 44 | } 45 | 46 | // generateController generates the Go files for a service controller 47 | func generateController(cmd *cobra.Command, args []string) error { 48 | if len(args) != 1 { 49 | return fmt.Errorf("please specify the service alias for the AWS service API to generate") 50 | } 51 | svcAlias := strings.ToLower(args[0]) 52 | if optOutputPath == "" { 53 | optOutputPath = filepath.Join(optServicesDir, svcAlias) 54 | } 55 | 56 | ctx, cancel := sdk.ContextWithSigterm(context.Background()) 57 | defer cancel() 58 | sdkDirPath, err := sdk.EnsureRepo(ctx, optCacheDir, optRefreshCache, optAWSSDKGoVersion, optOutputPath) 59 | if err != nil { 60 | return err 61 | } 62 | sdkDir = sdkDirPath 63 | metadata, err := ackmetadata.NewServiceMetadata(optMetadataConfigPath) 64 | if err != nil { 65 | return err 66 | } 67 | m, err := loadModelWithLatestAPIVersion(svcAlias, metadata) 68 | if err != nil { 69 | return err 70 | } 71 | serviceAccountName, err := getServiceAccountName() 72 | if err != nil { 73 | return err 74 | } 75 | ts, err := ackgenerate.Controller(m, optTemplateDirs, serviceAccountName) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | if err = ts.Execute(); err != nil { 81 | return err 82 | } 83 | 84 | for path, contents := range ts.Executed() { 85 | if optDryRun { 86 | fmt.Printf("============================= %s ======================================\n", path) 87 | fmt.Println(strings.TrimSpace(contents.String())) 88 | continue 89 | } 90 | outPath := filepath.Join(optOutputPath, path) 91 | outDir := filepath.Dir(outPath) 92 | if _, err := sdk.EnsureDir(outDir); err != nil { 93 | return err 94 | } 95 | if err = ioutil.WriteFile(outPath, contents.Bytes(), 0666); err != nil { 96 | return err 97 | } 98 | } 99 | return nil 100 | } 101 | -------------------------------------------------------------------------------- /cmd/ack-generate/command/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 command 15 | 16 | import ( 17 | "fmt" 18 | 19 | "github.com/spf13/cobra" 20 | 21 | "github.com/aws-controllers-k8s/code-generator/pkg/version" 22 | ) 23 | 24 | const debugHeader = `Date: %s 25 | Build: %s 26 | Version: %s 27 | Git Hash: %s 28 | ` 29 | 30 | // versionCmd represents the version command 31 | var versionCmd = &cobra.Command{ 32 | Use: "version", 33 | Short: "Display the version of " + appName, 34 | Run: func(cmd *cobra.Command, args []string) { 35 | fmt.Printf(debugHeader, version.BuildDate, version.GoVersion, version.Version, version.BuildHash) 36 | }, 37 | } 38 | 39 | func init() { 40 | rootCmd.AddCommand(versionCmd) 41 | } 42 | -------------------------------------------------------------------------------- /cmd/ack-generate/main.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 main 15 | 16 | import ( 17 | "github.com/aws-controllers-k8s/code-generator/cmd/ack-generate/command" 18 | ) 19 | 20 | func main() { 21 | command.Execute() 22 | } 23 | -------------------------------------------------------------------------------- /pkg/api/api_test.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import ( 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestAPI_StructName(t *testing.T) { 10 | origAliases := serviceAliaseNames 11 | defer func() { serviceAliaseNames = origAliases }() 12 | 13 | cases := map[string]struct { 14 | Aliases map[string]string 15 | Metadata Metadata 16 | StructName string 17 | }{ 18 | "FullName": { 19 | Metadata: Metadata{ 20 | ServiceFullName: "Amazon Service Name-100", 21 | }, 22 | StructName: "ServiceName100", 23 | }, 24 | "Abbreviation": { 25 | Metadata: Metadata{ 26 | ServiceFullName: "Amazon Service Name-100", 27 | ServiceAbbreviation: "AWS SN100", 28 | }, 29 | StructName: "SN100", 30 | }, 31 | "Lowercase Name": { 32 | Metadata: Metadata{ 33 | EndpointPrefix: "other", 34 | ServiceFullName: "AWS Lowercase service", 35 | ServiceAbbreviation: "lowercase", 36 | }, 37 | StructName: "Lowercase", 38 | }, 39 | "Lowercase Name Mixed": { 40 | Metadata: Metadata{ 41 | EndpointPrefix: "other", 42 | ServiceFullName: "AWS Lowercase service", 43 | ServiceAbbreviation: "lowercase name Goes heRe", 44 | }, 45 | StructName: "LowercaseNameGoesHeRe", 46 | }, 47 | "Alias": { 48 | Aliases: map[string]string{ 49 | "elasticloadbalancing": "ELB", 50 | }, 51 | Metadata: Metadata{ 52 | ServiceFullName: "Elastic Load Balancing", 53 | }, 54 | StructName: "ELB", 55 | }, 56 | } 57 | 58 | for k, c := range cases { 59 | t.Run(k, func(t *testing.T) { 60 | serviceAliaseNames = c.Aliases 61 | 62 | a := API{ 63 | Metadata: c.Metadata, 64 | } 65 | 66 | a.Setup() 67 | 68 | if e, o := c.StructName, a.StructName(); e != o { 69 | t.Errorf("expect %v structName, got %v", e, o) 70 | } 71 | }) 72 | } 73 | } 74 | 75 | func TestAPI_Setup_documentShapes(t *testing.T) { 76 | api := API{ 77 | Shapes: map[string]*Shape{ 78 | "Document": { 79 | Type: "structure", 80 | Document: true, 81 | }, 82 | }, 83 | } 84 | 85 | err := api.Setup() 86 | if err == nil { 87 | t.Fatalf("expect error, but got nil") 88 | } 89 | expect := "model contains document shapes" 90 | if !strings.Contains(err.Error(), expect) { 91 | t.Errorf("expect %s, got %v", expect, err) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /pkg/api/codegentest/models/awsquerycompatible/api-2.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "version":"2.0", 4 | "metadata":{ 5 | "apiVersion":"2012-11-05", 6 | "awsQueryCompatible": { 7 | 8 | }, 9 | "endpointPrefix":"awsqc-exampleendpoint", 10 | "jsonVersion":"1.1", 11 | "protocol":"json", 12 | "serviceAbbreviation":"AwsQueryCompatible", 13 | "serviceFullName":"AWSQuery Compatible Service", 14 | "serviceId":"AWSQueryCompatible", 15 | "signatureVersion":"v4", 16 | "uid":"awsquerycompatible-2012-11-05", 17 | "xmlNamespace":"http://queue.amazonaws.com/doc/2012-11-05/" 18 | }, 19 | "operations":{ 20 | "CreateQueue":{ 21 | "name":"CreateQueue", 22 | "http":{ 23 | "method":"POST", 24 | "requestUri":"/" 25 | }, 26 | "input":{"shape":"CreateQueueRequest"}, 27 | "output":{ 28 | "shape":"CreateQueueResult", 29 | "resultWrapper":"CreateQueueResult" 30 | }, 31 | "errors":[ 32 | {"shape":"QueueDeletedRecently"}, 33 | {"shape":"QueueNameExists"} 34 | ] 35 | } 36 | }, 37 | "shapes":{ 38 | "CreateQueueRequest":{ 39 | "type":"structure", 40 | "required":["QueueName"], 41 | "members":{ 42 | "QueueName":{"shape":"String"} 43 | } 44 | }, 45 | "CreateQueueResult":{ 46 | "type":"structure", 47 | "members":{ 48 | "QueueUrl":{"shape":"String"} 49 | } 50 | }, 51 | "QueueDeletedRecently":{ 52 | "type":"structure", 53 | "members":{ 54 | }, 55 | "error":{ 56 | "code":"AWS.SimpleQueueService.QueueDeletedRecently", 57 | "httpStatusCode":400, 58 | "senderFault":true 59 | }, 60 | "exception":true 61 | }, 62 | "QueueNameExists":{ 63 | "type":"structure", 64 | "members":{ 65 | }, 66 | "error":{ 67 | "code":"QueueAlreadyExists", 68 | "httpStatusCode":400, 69 | "senderFault":true 70 | }, 71 | "exception":true 72 | }, 73 | "String":{"type":"string"} 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkg/api/codegentest/models/endpointdiscovery/0000-00-00/docs-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "service": null, 4 | "operations": { 5 | }, 6 | "shapes":{} 7 | } 8 | -------------------------------------------------------------------------------- /pkg/api/codegentest/models/jsonrpc/0000-00-00/docs-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "service": null, 4 | "operations": { 5 | }, 6 | "shapes":{} 7 | } 8 | -------------------------------------------------------------------------------- /pkg/api/codegentest/models/restjson/0000-00-00/docs-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "service": null, 4 | "operations": { 5 | }, 6 | "shapes":{} 7 | } 8 | -------------------------------------------------------------------------------- /pkg/api/codegentest/models/restxml/0000-00-00/docs-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "service": null, 4 | "operations": { 5 | }, 6 | "shapes":{} 7 | } 8 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/awsendpointdiscoverytest/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package awsendpointdiscoverytest provides the client and types for making API 4 | // requests to AwsEndpointDiscoveryTest. 5 | // 6 | // See awsendpointdiscoverytest package documentation for more information. 7 | // https://docs.aws.amazon.com/sdk-for-go/api/service/awsendpointdiscoverytest/ 8 | // 9 | // # Using the Client 10 | // 11 | // To contact AwsEndpointDiscoveryTest with the SDK use the New function to create 12 | // a new service client. With that client you can make API requests to the service. 13 | // These clients are safe to use concurrently. 14 | // 15 | // See the SDK's documentation for more information on how to use the SDK. 16 | // https://docs.aws.amazon.com/sdk-for-go/api/ 17 | // 18 | // See aws.Config documentation for more information on configuring SDK clients. 19 | // https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config 20 | // 21 | // See the AwsEndpointDiscoveryTest client AwsEndpointDiscoveryTest for more 22 | // information on creating client for this service. 23 | // https://docs.aws.amazon.com/sdk-for-go/api/service/awsendpointdiscoverytest/#New 24 | package awsendpointdiscoverytest 25 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/awsendpointdiscoverytest/errors.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | package awsendpointdiscoverytest 4 | 5 | import ( 6 | "github.com/aws/aws-sdk-go/private/protocol" 7 | ) 8 | 9 | var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{} 10 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/awsquerycompatible/awsquerycompatibleiface/interface.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package awsquerycompatibleiface provides an interface to enable mocking the AWSQuery Compatible Service service client 4 | // for testing your code. 5 | // 6 | // It is important to note that this interface will have breaking changes 7 | // when the service model is updated and adds new API operations, paginators, 8 | // and waiters. 9 | package awsquerycompatibleiface 10 | 11 | import ( 12 | "github.com/aws/aws-sdk-go/aws" 13 | "github.com/aws/aws-sdk-go/aws/request" 14 | "github.com/aws/aws-sdk-go/private/model/api/codegentest/service/awsquerycompatible" 15 | ) 16 | 17 | // AwsQueryCompatibleAPI provides an interface to enable mocking the 18 | // awsquerycompatible.AwsQueryCompatible service client's API operation, 19 | // paginators, and waiters. This make unit testing your code that calls out 20 | // to the SDK's service client's calls easier. 21 | // 22 | // The best way to use this interface is so the SDK's service client's calls 23 | // can be stubbed out for unit testing your code with the SDK without needing 24 | // to inject custom request handlers into the SDK's request pipeline. 25 | // 26 | // // myFunc uses an SDK service client to make a request to 27 | // // AWSQuery Compatible Service. 28 | // func myFunc(svc awsquerycompatibleiface.AwsQueryCompatibleAPI) bool { 29 | // // Make svc.CreateQueue request 30 | // } 31 | // 32 | // func main() { 33 | // sess := session.New() 34 | // svc := awsquerycompatible.New(sess) 35 | // 36 | // myFunc(svc) 37 | // } 38 | // 39 | // In your _test.go file: 40 | // 41 | // // Define a mock struct to be used in your unit tests of myFunc. 42 | // type mockAwsQueryCompatibleClient struct { 43 | // awsquerycompatibleiface.AwsQueryCompatibleAPI 44 | // } 45 | // func (m *mockAwsQueryCompatibleClient) CreateQueue(input *awsquerycompatible.CreateQueueInput) (*awsquerycompatible.CreateQueueOutput, error) { 46 | // // mock response/functionality 47 | // } 48 | // 49 | // func TestMyFunc(t *testing.T) { 50 | // // Setup Test 51 | // mockSvc := &mockAwsQueryCompatibleClient{} 52 | // 53 | // myfunc(mockSvc) 54 | // 55 | // // Verify myFunc's functionality 56 | // } 57 | // 58 | // It is important to note that this interface will have breaking changes 59 | // when the service model is updated and adds new API operations, paginators, 60 | // and waiters. Its suggested to use the pattern above for testing, or using 61 | // tooling to generate mocks to satisfy the interfaces. 62 | type AwsQueryCompatibleAPI interface { 63 | CreateQueue(*awsquerycompatible.CreateQueueInput) (*awsquerycompatible.CreateQueueOutput, error) 64 | CreateQueueWithContext(aws.Context, *awsquerycompatible.CreateQueueInput, ...request.Option) (*awsquerycompatible.CreateQueueOutput, error) 65 | CreateQueueRequest(*awsquerycompatible.CreateQueueInput) (*request.Request, *awsquerycompatible.CreateQueueOutput) 66 | } 67 | 68 | var _ AwsQueryCompatibleAPI = (*awsquerycompatible.AwsQueryCompatible)(nil) 69 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/awsquerycompatible/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package awsquerycompatible provides the client and types for making API 4 | // requests to AWSQuery Compatible Service. 5 | // 6 | // See https://docs.aws.amazon.com/goto/WebAPI/awsquerycompatible-2012-11-05 for more information on this service. 7 | // 8 | // See awsquerycompatible package documentation for more information. 9 | // https://docs.aws.amazon.com/sdk-for-go/api/service/awsquerycompatible/ 10 | // 11 | // # Using the Client 12 | // 13 | // To contact AWSQuery Compatible Service with the SDK use the New function to create 14 | // a new service client. With that client you can make API requests to the service. 15 | // These clients are safe to use concurrently. 16 | // 17 | // See the SDK's documentation for more information on how to use the SDK. 18 | // https://docs.aws.amazon.com/sdk-for-go/api/ 19 | // 20 | // See aws.Config documentation for more information on configuring SDK clients. 21 | // https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config 22 | // 23 | // See the AWSQuery Compatible Service client AwsQueryCompatible for more 24 | // information on creating client for this service. 25 | // https://docs.aws.amazon.com/sdk-for-go/api/service/awsquerycompatible/#New 26 | package awsquerycompatible 27 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/awsquerycompatible/errors.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | package awsquerycompatible 4 | 5 | import ( 6 | "github.com/aws/aws-sdk-go/private/protocol" 7 | ) 8 | 9 | const ( 10 | 11 | // ErrCodeQueueDeletedRecently for service response error code 12 | // "QueueDeletedRecently". 13 | ErrCodeQueueDeletedRecently = "QueueDeletedRecently" 14 | 15 | // ErrCodeQueueNameExists for service response error code 16 | // "QueueNameExists". 17 | ErrCodeQueueNameExists = "QueueNameExists" 18 | ) 19 | 20 | var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{ 21 | "QueueDeletedRecently": newErrorQueueDeletedRecently, 22 | "QueueNameExists": newErrorQueueNameExists, 23 | } 24 | var queryExceptionFromCode = map[string]func(protocol.ResponseMetadata, string) error{ 25 | "QueueDeletedRecently": newQueryCompatibleErrorQueueDeletedRecently, 26 | "QueueNameExists": newQueryCompatibleErrorQueueNameExists, 27 | } 28 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/generate.go: -------------------------------------------------------------------------------- 1 | // Package service contains automatically generated AWS clients. 2 | package service 3 | 4 | //go:generate go run -tags codegen ../../../cli/gen-api/main.go -path=../service -svc-import-path "github.com/aws/aws-sdk-go/private/model/api/codegentest/service" ../models/*/*/api-2.json 5 | //go:generate gofmt -s -w ../service 6 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/restjsonservice/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package restjsonservice provides the client and types for making API 4 | // requests to REST JSON Service. 5 | // 6 | // See https://docs.aws.amazon.com/goto/WebAPI/RESTJSONService-0000-00-00 for more information on this service. 7 | // 8 | // See restjsonservice package documentation for more information. 9 | // https://docs.aws.amazon.com/sdk-for-go/api/service/restjsonservice/ 10 | // 11 | // # Using the Client 12 | // 13 | // To contact REST JSON Service with the SDK use the New function to create 14 | // a new service client. With that client you can make API requests to the service. 15 | // These clients are safe to use concurrently. 16 | // 17 | // See the SDK's documentation for more information on how to use the SDK. 18 | // https://docs.aws.amazon.com/sdk-for-go/api/ 19 | // 20 | // See aws.Config documentation for more information on configuring SDK clients. 21 | // https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config 22 | // 23 | // See the REST JSON Service client RESTJSONService for more 24 | // information on creating client for this service. 25 | // https://docs.aws.amazon.com/sdk-for-go/api/service/restjsonservice/#New 26 | package restjsonservice 27 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/restjsonservice/errors.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | package restjsonservice 4 | 5 | import ( 6 | "github.com/aws/aws-sdk-go/private/protocol" 7 | ) 8 | 9 | const ( 10 | 11 | // ErrCodeExceptionEvent for service response error code 12 | // "ExceptionEvent". 13 | ErrCodeExceptionEvent = "ExceptionEvent" 14 | 15 | // ErrCodeExceptionEvent2 for service response error code 16 | // "ExceptionEvent2". 17 | ErrCodeExceptionEvent2 = "ExceptionEvent2" 18 | ) 19 | 20 | var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{ 21 | "ExceptionEvent": newErrorExceptionEvent, 22 | "ExceptionEvent2": newErrorExceptionEvent2, 23 | } 24 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/restxmlservice/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package restxmlservice provides the client and types for making API 4 | // requests to REST XML Service. 5 | // 6 | // See https://docs.aws.amazon.com/goto/WebAPI/RESTXMLService-0000-00-00 for more information on this service. 7 | // 8 | // See restxmlservice package documentation for more information. 9 | // https://docs.aws.amazon.com/sdk-for-go/api/service/restxmlservice/ 10 | // 11 | // # Using the Client 12 | // 13 | // To contact REST XML Service with the SDK use the New function to create 14 | // a new service client. With that client you can make API requests to the service. 15 | // These clients are safe to use concurrently. 16 | // 17 | // See the SDK's documentation for more information on how to use the SDK. 18 | // https://docs.aws.amazon.com/sdk-for-go/api/ 19 | // 20 | // See aws.Config documentation for more information on configuring SDK clients. 21 | // https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config 22 | // 23 | // See the REST XML Service client RESTXMLService for more 24 | // information on creating client for this service. 25 | // https://docs.aws.amazon.com/sdk-for-go/api/service/restxmlservice/#New 26 | package restxmlservice 27 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/restxmlservice/errors.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | package restxmlservice 4 | 5 | const ( 6 | 7 | // ErrCodeExceptionEvent for service response error code 8 | // "ExceptionEvent". 9 | ErrCodeExceptionEvent = "ExceptionEvent" 10 | 11 | // ErrCodeExceptionEvent2 for service response error code 12 | // "ExceptionEvent2". 13 | ErrCodeExceptionEvent2 = "ExceptionEvent2" 14 | ) 15 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/rpcservice/doc.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | // Package rpcservice provides the client and types for making API 4 | // requests to RPC Service. 5 | // 6 | // See https://docs.aws.amazon.com/goto/WebAPI/RPCService-0000-00-00 for more information on this service. 7 | // 8 | // See rpcservice package documentation for more information. 9 | // https://docs.aws.amazon.com/sdk-for-go/api/service/rpcservice/ 10 | // 11 | // # Using the Client 12 | // 13 | // To contact RPC Service with the SDK use the New function to create 14 | // a new service client. With that client you can make API requests to the service. 15 | // These clients are safe to use concurrently. 16 | // 17 | // See the SDK's documentation for more information on how to use the SDK. 18 | // https://docs.aws.amazon.com/sdk-for-go/api/ 19 | // 20 | // See aws.Config documentation for more information on configuring SDK clients. 21 | // https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config 22 | // 23 | // See the RPC Service client RPCService for more 24 | // information on creating client for this service. 25 | // https://docs.aws.amazon.com/sdk-for-go/api/service/rpcservice/#New 26 | package rpcservice 27 | -------------------------------------------------------------------------------- /pkg/api/codegentest/service/rpcservice/errors.go: -------------------------------------------------------------------------------- 1 | // Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT. 2 | 3 | package rpcservice 4 | 5 | import ( 6 | "github.com/aws/aws-sdk-go/private/protocol" 7 | ) 8 | 9 | const ( 10 | 11 | // ErrCodeExceptionEvent for service response error code 12 | // "ExceptionEvent". 13 | ErrCodeExceptionEvent = "ExceptionEvent" 14 | 15 | // ErrCodeExceptionEvent2 for service response error code 16 | // "ExceptionEvent2". 17 | ErrCodeExceptionEvent2 = "ExceptionEvent2" 18 | ) 19 | 20 | var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{ 21 | "ExceptionEvent": newErrorExceptionEvent, 22 | "ExceptionEvent2": newErrorExceptionEvent2, 23 | } 24 | -------------------------------------------------------------------------------- /pkg/api/endpoint_trait.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import ( 5 | "fmt" 6 | "text/template" 7 | ) 8 | 9 | func setupEndpointHostPrefix(op *Operation) { 10 | op.API.AddSDKImport("private/protocol") 11 | 12 | buildHandler := fmt.Sprintf("protocol.NewHostPrefixHandler(%q, ", 13 | op.Endpoint.HostPrefix) 14 | 15 | if op.InputRef.Shape.HasHostLabelMembers() { 16 | buildHandler += "input.hostLabels" 17 | } else { 18 | buildHandler += "nil" 19 | } 20 | 21 | buildHandler += ")" 22 | 23 | op.CustomBuildHandlers = append(op.CustomBuildHandlers, 24 | buildHandler, 25 | "protocol.ValidateEndpointHostHandler", 26 | ) 27 | } 28 | 29 | // HasHostLabelMembers returns true if the shape contains any members which are 30 | // decorated with the hostLabel trait. 31 | func (s *Shape) HasHostLabelMembers() bool { 32 | for _, ref := range s.MemberRefs { 33 | if ref.HostLabel { 34 | return true 35 | } 36 | } 37 | 38 | return false 39 | } 40 | 41 | var hostLabelsShapeTmpl = template.Must( 42 | template.New("hostLabelsShapeTmpl"). 43 | Parse(hostLabelsShapeTmplDef), 44 | ) 45 | 46 | const hostLabelsShapeTmplDef = ` 47 | {{- define "hostLabelsShapeTmpl" }} 48 | func (s *{{ $.ShapeName }}) hostLabels() map[string]string { 49 | return map[string]string{ 50 | {{- range $name, $ref := $.MemberRefs }} 51 | {{- if $ref.HostLabel }} 52 | "{{ $name }}": aws.StringValue(s.{{ $name }}), 53 | {{- end }} 54 | {{- end }} 55 | } 56 | } 57 | {{- end }} 58 | ` 59 | -------------------------------------------------------------------------------- /pkg/api/eventstream_tmpl_writer.go: -------------------------------------------------------------------------------- 1 | 2 | 3 | package api 4 | 5 | import "text/template" 6 | 7 | var eventStreamShapeWriterTmpl = template.Must(template.New("eventStreamShapeWriterTmpl"). 8 | Funcs(template.FuncMap{}). 9 | Parse(` 10 | {{- $es := $.EventStream }} 11 | 12 | // {{ $es.StreamWriterAPIName }} provides the interface for writing events to the stream. 13 | // The default implementation for this interface will be {{ $.ShapeName }}. 14 | // 15 | // The writer's Close method must allow multiple concurrent calls. 16 | // 17 | // These events are: 18 | // {{ range $_, $event := $es.Events }} 19 | // * {{ $event.Shape.ShapeName }} 20 | {{- end }} 21 | type {{ $es.StreamWriterAPIName }} interface { 22 | // Sends writes events to the stream blocking until the event has been 23 | // written. An error is returned if the write fails. 24 | Send(aws.Context, {{ $es.EventGroupName }}) error 25 | 26 | // Close will stop the writer writing to the event stream. 27 | Close() error 28 | 29 | // Returns any error that has occurred while writing to the event stream. 30 | Err() error 31 | } 32 | 33 | type {{ $es.StreamWriterImplName }} struct { 34 | *eventstreamapi.StreamWriter 35 | } 36 | 37 | func (w *{{ $es.StreamWriterImplName }}) Send(ctx aws.Context, event {{ $es.EventGroupName }}) error { 38 | return w.StreamWriter.Send(ctx, event) 39 | } 40 | 41 | func {{ $es.StreamEventTypeGetterName }}(event eventstreamapi.Marshaler) (string, error) { 42 | switch event.(type) { 43 | {{- range $_, $event := $es.Events }} 44 | case *{{ $event.Shape.ShapeName }}: 45 | return {{ printf "%q" $event.Name }}, nil 46 | {{- end }} 47 | {{- range $_, $event := $es.Exceptions }} 48 | case *{{ $event.Shape.ShapeName }}: 49 | return {{ printf "%q" $event.Name }}, nil 50 | {{- end }} 51 | default: 52 | return "", awserr.New( 53 | request.ErrCodeSerialization, 54 | fmt.Sprintf("unknown event type, %T, for {{ $es.Name }}", event), 55 | nil, 56 | ) 57 | } 58 | } 59 | `)) 60 | -------------------------------------------------------------------------------- /pkg/api/examples_builder.go: -------------------------------------------------------------------------------- 1 | 2 | 3 | package api 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/aws/aws-sdk-go/private/protocol" 9 | ) 10 | 11 | type examplesBuilder interface { 12 | BuildShape(*ShapeRef, map[string]interface{}, bool) string 13 | BuildList(string, string, *ShapeRef, []interface{}) string 14 | BuildComplex(string, string, *ShapeRef, *Shape, map[string]interface{}) string 15 | GoType(*ShapeRef, bool) string 16 | Imports(*API) string 17 | } 18 | 19 | type defaultExamplesBuilder struct { 20 | ShapeValueBuilder 21 | } 22 | 23 | // NewExamplesBuilder returns an initialized example builder for generating 24 | // example input API shapes from a model. 25 | func NewExamplesBuilder() defaultExamplesBuilder { 26 | b := defaultExamplesBuilder{ 27 | ShapeValueBuilder: NewShapeValueBuilder(), 28 | } 29 | b.ParseTimeString = parseExampleTimeString 30 | return b 31 | } 32 | 33 | func (builder defaultExamplesBuilder) Imports(a *API) string { 34 | return `"fmt" 35 | "strings" 36 | "time" 37 | 38 | "` + SDKImportRoot + `/aws" 39 | "` + SDKImportRoot + `/aws/awserr" 40 | "` + SDKImportRoot + `/aws/session" 41 | "` + a.ImportPath() + `" 42 | ` 43 | } 44 | 45 | // Returns a string which assigns the value of a time member by calling 46 | // parseTime function defined in the file 47 | func parseExampleTimeString(ref *ShapeRef, memName, v string) string { 48 | if ref.Location == "header" { 49 | return fmt.Sprintf("%s: parseTime(%q, %q),\n", memName, protocol.RFC822TimeFormat, v) 50 | } 51 | 52 | switch ref.API.Metadata.Protocol { 53 | case "json", "rest-json", "rest-xml", "ec2", "query": 54 | return fmt.Sprintf("%s: parseTime(%q, %q),\n", memName, protocol.ISO8601TimeFormat, v) 55 | default: 56 | panic("Unsupported time type: " + ref.API.Metadata.Protocol) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pkg/api/examples_builder_customizations.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | type wafregionalExamplesBuilder struct { 5 | defaultExamplesBuilder 6 | } 7 | 8 | func NewWAFregionalExamplesBuilder() wafregionalExamplesBuilder { 9 | return wafregionalExamplesBuilder{defaultExamplesBuilder: NewExamplesBuilder()} 10 | } 11 | func (builder wafregionalExamplesBuilder) Imports(a *API) string { 12 | return `"fmt" 13 | "strings" 14 | "time" 15 | 16 | "` + SDKImportRoot + `/aws" 17 | "` + SDKImportRoot + `/aws/awserr" 18 | "` + SDKImportRoot + `/aws/session" 19 | "` + SDKImportRoot + `/service/waf" 20 | "` + SDKImportRoot + `/service/` + a.PackageName() + `" 21 | ` 22 | } 23 | -------------------------------------------------------------------------------- /pkg/api/exportable_name.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import "strings" 5 | 6 | // ExportableName a name which is exportable as a value or name in Go code 7 | func (a *API) ExportableName(name string) string { 8 | if name == "" { 9 | return name 10 | } 11 | 12 | return strings.ToUpper(name[0:1]) + name[1:] 13 | } 14 | -------------------------------------------------------------------------------- /pkg/api/load_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "path/filepath" 5 | "reflect" 6 | "strconv" 7 | "testing" 8 | ) 9 | 10 | func TestResolvedReferences(t *testing.T) { 11 | json := `{ 12 | "operations": { 13 | "OperationName": { 14 | "input": { "shape": "TestName" } 15 | } 16 | }, 17 | "shapes": { 18 | "TestName": { 19 | "type": "structure", 20 | "members": { 21 | "memberName1": { "shape": "OtherTest" }, 22 | "memberName2": { "shape": "OtherTest" } 23 | } 24 | }, 25 | "OtherTest": { "type": "string" } 26 | } 27 | }` 28 | a := API{} 29 | a.AttachString(json) 30 | if len(a.Shapes["OtherTest"].Refs) != 2 { 31 | t.Errorf("Expected %d, but received %d", 2, len(a.Shapes["OtherTest"].Refs)) 32 | } 33 | } 34 | 35 | func TestTrimModelServiceVersions(t *testing.T) { 36 | cases := []struct { 37 | Paths []string 38 | Include []string 39 | Exclude []string 40 | }{ 41 | { 42 | Paths: []string{ 43 | filepath.Join("foo", "baz", "2018-01-02", "api-2.json"), 44 | filepath.Join("foo", "baz", "2019-01-02", "api-2.json"), 45 | filepath.Join("foo", "baz", "2017-01-02", "api-2.json"), 46 | filepath.Join("foo", "bar", "2019-01-02", "api-2.json"), 47 | filepath.Join("foo", "bar", "2013-04-02", "api-2.json"), 48 | filepath.Join("foo", "bar", "2019-01-03", "api-2.json"), 49 | }, 50 | Include: []string{ 51 | filepath.Join("foo", "baz", "2019-01-02", "api-2.json"), 52 | filepath.Join("foo", "bar", "2019-01-03", "api-2.json"), 53 | }, 54 | Exclude: []string{ 55 | filepath.Join("foo", "baz", "2018-01-02", "api-2.json"), 56 | filepath.Join("foo", "baz", "2017-01-02", "api-2.json"), 57 | filepath.Join("foo", "bar", "2019-01-02", "api-2.json"), 58 | filepath.Join("foo", "bar", "2013-04-02", "api-2.json"), 59 | }, 60 | }, 61 | } 62 | 63 | for i, c := range cases { 64 | t.Run(strconv.Itoa(i), func(t *testing.T) { 65 | include, exclude := TrimModelServiceVersions(c.Paths) 66 | if e, a := c.Include, include; !reflect.DeepEqual(e, a) { 67 | t.Errorf("expect include %v, got %v", e, a) 68 | } 69 | if e, a := c.Exclude, exclude; !reflect.DeepEqual(e, a) { 70 | t.Errorf("expect exclude %v, got %v", e, a) 71 | } 72 | }) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /pkg/api/logger.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import ( 5 | "fmt" 6 | "io" 7 | "sync" 8 | ) 9 | 10 | var debugLogger *logger 11 | var initDebugLoggerOnce sync.Once 12 | 13 | // logger provides a basic logging 14 | type logger struct { 15 | w io.Writer 16 | } 17 | 18 | // LogDebug initialize's the debug logger for the components in the api 19 | // package to log debug lines to. 20 | // 21 | // Panics if called multiple times. 22 | // 23 | // Must be used prior to any model loading or code gen. 24 | func LogDebug(w io.Writer) { 25 | var initialized bool 26 | initDebugLoggerOnce.Do(func() { 27 | debugLogger = &logger{ 28 | w: w, 29 | } 30 | initialized = true 31 | }) 32 | 33 | if !initialized && debugLogger != nil { 34 | panic("LogDebug called multiple times. Can only be called once") 35 | } 36 | } 37 | 38 | // Logf logs using the fmt printf pattern. Appends a new line to the end of the 39 | // logged statement. 40 | func (l *logger) Logf(format string, args ...interface{}) { 41 | if l == nil { 42 | return 43 | } 44 | fmt.Fprintf(l.w, format+"\n", args...) 45 | } 46 | 47 | // Logln logs using the fmt println pattern. 48 | func (l *logger) Logln(args ...interface{}) { 49 | if l == nil { 50 | return 51 | } 52 | fmt.Fprintln(l.w, args...) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/api/pagination.go: -------------------------------------------------------------------------------- 1 | 2 | package api 3 | 4 | import ( 5 | "encoding/json" 6 | "fmt" 7 | "os" 8 | ) 9 | 10 | // Paginator keeps track of pagination configuration for an API operation. 11 | type Paginator struct { 12 | InputTokens interface{} `json:"input_token"` 13 | OutputTokens interface{} `json:"output_token"` 14 | LimitKey string `json:"limit_key"` 15 | MoreResults string `json:"more_results"` 16 | } 17 | 18 | // InputTokensString returns output tokens formatted as a list 19 | func (p *Paginator) InputTokensString() string { 20 | str := p.InputTokens.([]string) 21 | return fmt.Sprintf("%#v", str) 22 | } 23 | 24 | // OutputTokensString returns output tokens formatted as a list 25 | func (p *Paginator) OutputTokensString() string { 26 | str := p.OutputTokens.([]string) 27 | return fmt.Sprintf("%#v", str) 28 | } 29 | 30 | // used for unmarshaling from the paginators JSON file 31 | type paginationDefinitions struct { 32 | *API 33 | Pagination map[string]Paginator 34 | } 35 | 36 | // AttachPaginators attaches pagination configuration from filename to the API. 37 | func (a *API) AttachPaginators(filename string) error { 38 | p := paginationDefinitions{API: a} 39 | 40 | f, err := os.Open(filename) 41 | defer f.Close() 42 | if err != nil { 43 | return err 44 | } 45 | err = json.NewDecoder(f).Decode(&p) 46 | if err != nil { 47 | return fmt.Errorf("failed to decode %s, err: %v", filename, err) 48 | } 49 | 50 | return p.setup() 51 | } 52 | 53 | // setup runs post-processing on the paginator configuration. 54 | func (p *paginationDefinitions) setup() error { 55 | for n, e := range p.Pagination { 56 | if e.InputTokens == nil || e.OutputTokens == nil { 57 | continue 58 | } 59 | if _, ok := p.Operations[n]; !ok { 60 | continue 61 | } 62 | paginator := e 63 | 64 | switch t := paginator.InputTokens.(type) { 65 | case string: 66 | paginator.InputTokens = []string{t} 67 | case []interface{}: 68 | toks := []string{} 69 | for _, e := range t { 70 | s := e.(string) 71 | toks = append(toks, s) 72 | } 73 | paginator.InputTokens = toks 74 | } 75 | switch t := paginator.OutputTokens.(type) { 76 | case string: 77 | paginator.OutputTokens = []string{t} 78 | case []interface{}: 79 | toks := []string{} 80 | for _, e := range t { 81 | s := e.(string) 82 | toks = append(toks, s) 83 | } 84 | paginator.OutputTokens = toks 85 | } 86 | 87 | p.Operations[n].Paginator = &paginator 88 | } 89 | 90 | return nil 91 | } 92 | 93 | func enableStopOnSameToken(service string) bool { 94 | switch service { 95 | case "cloudwatchlogs": 96 | return true 97 | default: 98 | return false 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /pkg/api/shape_alias.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | var shapeNameAliases = map[string]map[string]string{ 4 | "APIGateway": { 5 | "RequestValidator": "UpdateRequestValidatorOutput", 6 | "GatewayResponse": "UpdateGatewayResponseOutput", 7 | }, 8 | "Lambda": { 9 | "Concurrency": "PutFunctionConcurrencyOutput", 10 | }, 11 | "Neptune": { 12 | "DBClusterParameterGroupNameMessage": "ResetDBClusterParameterGroupOutput", 13 | "DBParameterGroupNameMessage": "ResetDBParameterGroupOutput", 14 | }, 15 | "RDS": { 16 | "DBClusterBacktrack": "BacktrackDBClusterOutput", 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /pkg/api/shapetag_test.go: -------------------------------------------------------------------------------- 1 | package api_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/aws-controllers-k8s/code-generator/pkg/api" 7 | ) 8 | 9 | func TestShapeTagJoin(t *testing.T) { 10 | s := api.ShapeTags{ 11 | {Key: "location", Val: "query"}, 12 | {Key: "locationName", Val: "abc"}, 13 | {Key: "type", Val: "string"}, 14 | } 15 | 16 | expected := `location:"query" locationName:"abc" type:"string"` 17 | 18 | o := s.Join(" ") 19 | o2 := s.String() 20 | if expected != o { 21 | t.Errorf("Expected %s, but received %s", expected, o) 22 | } 23 | if expected != o2 { 24 | t.Errorf("Expected %s, but received %s", expected, o2) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pkg/apiv2/remove_defaults.go: -------------------------------------------------------------------------------- 1 | package apiv2 2 | 3 | // BadDefaultsAssignment stores the Service Models that have members with defaultValues (considered non pointers) 4 | // but still have pointers. This list was retrieved from aws-sdk-go-v2, link below 5 | // https://github.com/aws/aws-sdk-go-v2/blob/4ad9d5996fd752f0756be2dbbdd4f8a4841fe362/codegen/smithy-aws-go-codegen/src/main/java/software/amazon/smithy/aws/go/codegen/customization/RemoveDefaults.java#L19-L39 6 | var BadDefaultsAssignment = map[string]map[string]bool{ 7 | "AWSS3ControlServiceV20180820": { 8 | "BlockPublicAcls": true, 9 | "IgnorePublicAcls": true, 10 | "BlockPublicPolicy": true, 11 | "RestrictPublicBuckets": true, 12 | }, 13 | "Evidently": { 14 | "ResultsPeriod": true, 15 | }, 16 | "AmplifyUIBuilder": { 17 | "MaxResults": true, 18 | "PlaceIndexSearchResultLimit": true, 19 | }, 20 | "PaymentCryptographyDataPlane": { 21 | "IntegerRangeBetween4And12": true, 22 | }, 23 | "AwsToledoWebService": { 24 | "WorkerCounts": true, 25 | }, 26 | "imagebuilder": { 27 | "setDefaultVersion": true, 28 | }, 29 | "AmazonBedrockAgentBuildTimeLambda": { 30 | "StorageDays": true, 31 | }, 32 | } 33 | 34 | func hasBadDefualtAssignment(serviceName, shapeName string) bool { 35 | service, found := BadDefaultsAssignment[serviceName] 36 | if !found { 37 | return false 38 | } 39 | 40 | return service[shapeName] 41 | } -------------------------------------------------------------------------------- /pkg/config/documentation.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "io/ioutil" 5 | 6 | "github.com/ghodss/yaml" 7 | ) 8 | 9 | // DocumentationConfig represents the configuration of the documentation file, 10 | // used to override or append documentation to any of the resource fields 11 | type DocumentationConfig struct { 12 | Resources map[string]*ResourceDocsConfig `json:"resources,omitempty"` 13 | } 14 | 15 | // ResourceDocsConfig represents the configuration for the documentation 16 | // overrides of a single resource 17 | type ResourceDocsConfig struct { 18 | Fields map[string]*FieldDocsConfig `json:"fields,omitempty"` 19 | } 20 | 21 | // FieldDocsConfig represents the configuration for the documentation overrides 22 | // of a single field 23 | type FieldDocsConfig struct { 24 | // Append specifies a string that will be added to the end of the existing 25 | // GoDoc comment for the field 26 | Append *string `json:"append,omitempty"` 27 | // Prepend specifies a string that will be added before the existing 28 | // GoDoc comment for the field 29 | Prepend *string `json:"prepend,omitempty"` 30 | // Override will entirely replace the GoDoc comment for the field 31 | Override *string `json:"override,omitempty"` 32 | } 33 | 34 | // NewDocumentationConfig returns a new DocumentationConfig object given a 35 | // supplied path to a config file 36 | func NewDocumentationConfig( 37 | configPath string, 38 | ) (DocumentationConfig, error) { 39 | if configPath == "" { 40 | return DocumentationConfig{}, nil 41 | } 42 | content, err := ioutil.ReadFile(configPath) 43 | if err != nil { 44 | return DocumentationConfig{}, err 45 | } 46 | gc := DocumentationConfig{} 47 | if err = yaml.Unmarshal(content, &gc); err != nil { 48 | return DocumentationConfig{}, err 49 | } 50 | return gc, nil 51 | } 52 | -------------------------------------------------------------------------------- /pkg/config/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 config 15 | 16 | // APIVersion represents an API version of the generated CRD. 17 | type APIVersion struct { 18 | // Name of the API version, e.g. v1beta1 19 | Name string `json:"name"` 20 | // Served whether this version is enabled or not 21 | Served *bool `json:"served,omitempty"` 22 | // Storage whether this version is the storage version. 23 | // One and only one version can be set as the storage version. 24 | Storage *bool `json:"storage,omitempty"` 25 | } 26 | 27 | // GetAPIVersions returns the API version(s) for a CRD 28 | func (c *Config) GetAPIVersions(crdName string) []APIVersion { 29 | res := []APIVersion{} 30 | if c == nil { 31 | return res 32 | } 33 | resConfig, found := c.Resources[crdName] 34 | if !found { 35 | return res 36 | } 37 | return resConfig.APIVersions 38 | } 39 | -------------------------------------------------------------------------------- /pkg/generate/ack/apis.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 ack 15 | 16 | import ( 17 | "path/filepath" 18 | "strings" 19 | ttpl "text/template" 20 | 21 | "github.com/aws-controllers-k8s/code-generator/pkg/generate/templateset" 22 | ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model" 23 | "github.com/iancoleman/strcase" 24 | ) 25 | 26 | var ( 27 | apisTemplatePaths = []string{ 28 | "apis/doc.go.tpl", 29 | "apis/enums.go.tpl", 30 | "apis/groupversion_info.go.tpl", 31 | "apis/types.go.tpl", 32 | } 33 | apisIncludePaths = []string{ 34 | "boilerplate.go.tpl", 35 | "apis/enum_def.go.tpl", 36 | "apis/type_def.go.tpl", 37 | } 38 | apisCopyPaths = []string{} 39 | apisFuncMap = ttpl.FuncMap{ 40 | "Join": strings.Join, 41 | } 42 | ) 43 | 44 | // APIs returns a pointer to a TemplateSet containing all the templates for 45 | // generating ACK service controller's apis/ contents 46 | func APIs( 47 | m *ackmodel.Model, 48 | templateBasePaths []string, 49 | ) (*templateset.TemplateSet, error) { 50 | enumDefs, err := m.GetEnumDefs() 51 | if err != nil { 52 | return nil, err 53 | } 54 | typeDefs, err := m.GetTypeDefs() 55 | if err != nil { 56 | return nil, err 57 | } 58 | crds, err := m.GetCRDs() 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | ts := templateset.New( 64 | templateBasePaths, 65 | apisIncludePaths, 66 | apisCopyPaths, 67 | apisFuncMap, 68 | ) 69 | 70 | metaVars := m.MetaVars() 71 | apiVars := &templateAPIVars{ 72 | metaVars, 73 | enumDefs, 74 | typeDefs, 75 | } 76 | for _, path := range apisTemplatePaths { 77 | outPath := strings.TrimSuffix(filepath.Base(path), ".tpl") 78 | if err = ts.Add(outPath, path, apiVars); err != nil { 79 | return nil, err 80 | } 81 | } 82 | 83 | for _, crd := range crds { 84 | crdFileName := strcase.ToSnake(crd.Kind) + ".go" 85 | crdVars := &templateCRDVars{ 86 | metaVars, 87 | m.SDKAPI, 88 | crd, 89 | } 90 | if err = ts.Add(crdFileName, "apis/crd.go.tpl", crdVars); err != nil { 91 | return nil, err 92 | } 93 | } 94 | return ts, nil 95 | } 96 | 97 | // templateAPIVars contains template variables for templates that output Go 98 | // code in the /services/$SERVICE/apis/$API_VERSION directory 99 | type templateAPIVars struct { 100 | templateset.MetaVars 101 | EnumDefs []*ackmodel.EnumDef 102 | TypeDefs []*ackmodel.TypeDef 103 | } 104 | 105 | // templateCRDVars contains template variables for the template that outputs Go 106 | // code for a single top-level resource's API definition 107 | type templateCRDVars struct { 108 | templateset.MetaVars 109 | SDKAPI *ackmodel.SDKAPI 110 | CRD *ackmodel.CRD 111 | } 112 | -------------------------------------------------------------------------------- /pkg/generate/ack/config.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package ack 15 | 16 | import "github.com/aws-controllers-k8s/code-generator/pkg/config" 17 | 18 | // DefaultConfig is the default configuration for generating ACK code 19 | var DefaultConfig = config.Config{ 20 | PrefixConfig: config.PrefixConfig{ 21 | SpecField: ".Spec", 22 | StatusField: ".Status", 23 | }, 24 | IncludeACKMetadata: true, 25 | SetManyOutputNotFoundErrReturn: "return nil, ackerr.NotFound", 26 | } 27 | -------------------------------------------------------------------------------- /pkg/generate/ack/hook_test.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 ack_test 15 | 16 | import ( 17 | "os" 18 | "path/filepath" 19 | "testing" 20 | 21 | "github.com/stretchr/testify/assert" 22 | "github.com/stretchr/testify/require" 23 | 24 | "github.com/aws-controllers-k8s/code-generator/pkg/generate/ack" 25 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 26 | ) 27 | 28 | func TestResourceHookCodeInline(t *testing.T) { 29 | assert := assert.New(t) 30 | require := require.New(t) 31 | basePaths := []string{} 32 | hookID := "sdk_update_pre_build_request" 33 | 34 | g := testutil.NewModelForService(t, "mq") 35 | 36 | crd := testutil.GetCRDByName(t, g, "Broker") 37 | require.NotNil(crd) 38 | 39 | // The Broker's update operation has a special hook callback configured 40 | expected := `if err := rm.requeueIfNotRunning(latest); err != nil { return nil, err }` 41 | got, err := ack.ResourceHookCode(basePaths, crd, hookID, nil, nil) 42 | assert.Nil(err) 43 | assert.Equal(expected, got) 44 | } 45 | 46 | func TestResourceHookCodeTemplatePath(t *testing.T) { 47 | assert := assert.New(t) 48 | require := require.New(t) 49 | wd, _ := os.Getwd() 50 | basePaths := []string{ 51 | filepath.Join(wd, "testdata", "templates"), 52 | } 53 | hookID := "sdk_delete_pre_build_request" 54 | 55 | g := testutil.NewModelForService(t, "mq") 56 | 57 | crd := testutil.GetCRDByName(t, g, "Broker") 58 | require.NotNil(crd) 59 | 60 | // The Broker's delete operation has a special hook configured to point to a template. 61 | expected := "// this is my template.\n" 62 | got, err := ack.ResourceHookCode(basePaths, crd, hookID, nil, nil) 63 | assert.Nil(err) 64 | assert.Equal(expected, got) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/generate/ack/testdata/templates/sdk_delete_pre_build_request.go.tpl: -------------------------------------------------------------------------------- 1 | // this is my template. 2 | -------------------------------------------------------------------------------- /pkg/generate/code/initialize_field_test.go: -------------------------------------------------------------------------------- 1 | package code_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/aws-controllers-k8s/code-generator/pkg/generate/code" 7 | 8 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestInitializeNestedStructField(t *testing.T) { 13 | assert := assert.New(t) 14 | 15 | g := testutil.NewModelForServiceWithOptions(t, "s3", 16 | &testutil.TestingModelOptions{GeneratorConfigFile: "generator-with-tags.yaml"}) 17 | 18 | crd := testutil.GetCRDByName(t, g, "Bucket") 19 | assert.NotNil(crd) 20 | 21 | f := crd.Fields["Logging.LoggingEnabled.TargetBucket"] 22 | 23 | s := code.InitializeNestedStructField(crd, "r.ko", f, 24 | "svcapitypes", 1) 25 | expected := 26 | ` r.ko.Spec.Logging = &svcapitypes.BucketLoggingStatus{} 27 | r.ko.Spec.Logging.LoggingEnabled = &svcapitypes.LoggingEnabled{} 28 | ` 29 | assert.Equal(expected, s) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/generate/crossplane/config.go: -------------------------------------------------------------------------------- 1 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 4 | // not use this file except in compliance with the License. A copy of the 5 | // License is located at 6 | // 7 | // http://aws.amazon.com/apache2.0/ 8 | // 9 | // or in the "license" file accompanying this file. This file is distributed 10 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 | // express or implied. See the License for the specific language governing 12 | // permissions and limitations under the License. 13 | 14 | package crossplane 15 | 16 | import "github.com/aws-controllers-k8s/code-generator/pkg/config" 17 | 18 | // DefaultConfig is the default config object for Crossplane controllers. 19 | var DefaultConfig = config.Config{ 20 | PrefixConfig: config.PrefixConfig{ 21 | SpecField: ".Spec.ForProvider", 22 | StatusField: ".Status.AtProvider", 23 | }, 24 | IncludeACKMetadata: false, 25 | SetManyOutputNotFoundErrReturn: "return cr", 26 | } 27 | -------------------------------------------------------------------------------- /pkg/generate/olm/types.go: -------------------------------------------------------------------------------- 1 | package olm 2 | 3 | import opsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" 4 | 5 | var ( 6 | capabilityBasicInstall = "basic install" 7 | capabilitySeamlessUpgrades = "seamless upgrades" 8 | capabilityFullLifecucle = "full lifecycle" 9 | capabilityDeepInsights = "deep insights" 10 | capabilityAutoPilot = "auto pilot" 11 | 12 | mediatypeGIF = "image/gif" 13 | mediatypeJPG = "image/jpeg" 14 | mediatypePNG = "image/png" 15 | mediatypeSVG = "image/svg+xml" 16 | ) 17 | 18 | // ServiceConfig represents a service controller's OLM configuration 19 | // input. 20 | type ServiceConfig struct { 21 | Annotations Annotations `json:"annotations"` 22 | Samples []Sample `json:"samples"` 23 | opsv1alpha1.ClusterServiceVersionSpec 24 | } 25 | 26 | // CommonMetadata represents common metadata for all service controllers 27 | // generated by this project. 28 | type CommonMetadata struct { 29 | Links []opsv1alpha1.AppLink `json:"links"` 30 | Keywords []string `json:"keywords"` 31 | } 32 | 33 | // CommonLinks are links that are likely to be common across service 34 | // controllers. 35 | var CommonLinks = []opsv1alpha1.AppLink{ 36 | { 37 | Name: "AWS Controllers for Kubernetes", 38 | URL: "https://github.com/aws-controllers-k8s/community", 39 | }, 40 | { 41 | Name: "Documentation", 42 | URL: "https://aws-controllers-k8s.github.io/community/", 43 | }, 44 | } 45 | 46 | // CommonKeywords are keywords that are likely to be common across 47 | // service controllers. 48 | var CommonKeywords = []string{ 49 | "aws", 50 | "amazon", 51 | "ack", 52 | } 53 | 54 | // Annotations represent metadata that is added to the ClusterServiceVersion 55 | // yaml. These keys inform the OLM graphical user interface. 56 | type Annotations struct { 57 | CapabilityLevel string `json:"capabilityLevel"` 58 | SuggestedNamespace string `json:"suggestedNamespace"` 59 | Repository string `json:"repository"` 60 | ContainerImage string `json:"containerImage"` 61 | ShortDescription string `json:"shortDescription"` 62 | Support string `json:"support"` 63 | IsCertified bool `json:"isCertified"` 64 | } 65 | 66 | // Sample is a basic representation of an instance of custom resource 67 | // managed by a given service controller. 68 | type Sample struct { 69 | Kind string `json:"kind"` 70 | Spec string `json:"spec"` 71 | DisplayName string `json:"displayName"` 72 | Description string `json:"description"` 73 | } 74 | -------------------------------------------------------------------------------- /pkg/generate/templateset/vars.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 templateset 15 | 16 | // MetaVars contains template variables that most templates need access to 17 | // that describe the service alias, its package name, etc 18 | type MetaVars struct { 19 | // ControllerName contains the exact string used to identify the ACK 20 | // controller in the aws-controllers-k8s project. This name is used as the 21 | // name of the ACK controller's module, repository and helm chart. 22 | ControllerName string 23 | // ServiceModelName contains the exact string used to identify the AWS 24 | // service API in the aws-sdk-go's models/apis/ directory. Note that some 25 | // APIs this name does not match the ServiceID. e.g. The AWS Step Functions 26 | // API has a ServiceID of "SFN" and a service model name of "states"... 27 | ServiceModelName string 28 | // ServicePackageName contains the exact string used to identify the AWS 29 | // service API in the aws-sdk-go `service/` directory. It is also used as 30 | // the identifier for the ACK controller's name and packages. 31 | ServicePackageName string 32 | // ServiceID is the exact string that appears in the AWS service API's 33 | // api-2.json descriptor file under `metadata.serviceId` 34 | ServiceID string 35 | // APIVersion contains the version of the Kubernetes API resources, e.g. 36 | // "v1alpha1" 37 | APIVersion string 38 | // APIGroup contains the normalized name of the Kubernetes APIGroup used 39 | // for custom resources, e.g. "sns.services.k8s.aws" or 40 | // "sfn.services.k8s.aws" 41 | APIGroup string 42 | // ClientInterfaceTypeName is the name of the interface type used by the 43 | // aws-sdk-go services/$SERVICE/api.go file 44 | ClientInterfaceTypeName string 45 | // ClientStructTypeName is the name of the struct type defining the service 46 | // sdk client. 47 | ClientStructTypeName string 48 | //CRDNames contains all crds names lowercased and in plural 49 | CRDNames []string 50 | } 51 | -------------------------------------------------------------------------------- /pkg/metadata/api_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 | package metadata 15 | 16 | type APIStatus string 17 | 18 | const ( 19 | APIStatusAvailable APIStatus = "available" 20 | APIStatusRemoved = "removed" 21 | APIStatusDeprecated = "deprecated" 22 | ) 23 | 24 | // APIInfo contains information related a specific apiVersion. 25 | type APIInfo struct { 26 | // The API status. Can be one of Available, Removed and Deprecated. 27 | Status APIStatus 28 | // the aws-sdk-go version used to generated the apiVersion. 29 | AWSSDKVersion string 30 | // Full path of the generator config file. 31 | GeneratorConfigPath string 32 | // Full path of the documentation config file. 33 | DocumentationConfigPath string 34 | // The API version. 35 | APIVersion string 36 | } 37 | -------------------------------------------------------------------------------- /pkg/model/attr.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 model 15 | 16 | import ( 17 | "fmt" 18 | 19 | awssdkmodel "github.com/aws-controllers-k8s/code-generator/pkg/api" 20 | "github.com/aws-controllers-k8s/pkg/names" 21 | ) 22 | 23 | type Attr struct { 24 | Names names.Names 25 | GoType string 26 | Shape *awssdkmodel.Shape 27 | GoTag string 28 | } 29 | 30 | func NewAttr( 31 | names names.Names, 32 | goType string, 33 | shape *awssdkmodel.Shape, 34 | ) *Attr { 35 | return &Attr{ 36 | Names: names, 37 | GoType: goType, 38 | Shape: shape, 39 | } 40 | } 41 | 42 | // GetGoTag returns the Go Tag to inject for this attribute. If the GoTag 43 | // field is not empty, it will be used. Otherwise, one will be generated 44 | // from the attribute's name. 45 | func (a *Attr) GetGoTag() string { 46 | if a.GoTag != "" { 47 | return a.GoTag 48 | } 49 | return fmt.Sprintf("`json:\"%s,omitempty\"`", a.Names.CamelLower) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/model/enum_def.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 model 15 | 16 | import ( 17 | "bytes" 18 | 19 | "github.com/aws-controllers-k8s/pkg/names" 20 | ) 21 | 22 | type EnumValue struct { 23 | Original string 24 | Clean string 25 | } 26 | 27 | // EnumDef is the definition of an enumeration type for a field present in 28 | // either a CRD or a TypeDef 29 | type EnumDef struct { 30 | Names names.Names 31 | Values []EnumValue 32 | } 33 | 34 | // NewEnumDef returns a pointer to an `ackmodel.EnumDef` struct representing a 35 | // constrained string value field 36 | func NewEnumDef(names names.Names, values []string) (*EnumDef, error) { 37 | enumVals := make([]EnumValue, len(values)) 38 | for x, item := range values { 39 | enumVals[x] = newEnumVal(item) 40 | } 41 | return &EnumDef{names, enumVals}, nil 42 | } 43 | 44 | func newEnumVal(orig string) EnumValue { 45 | // Convert values like "m5.xlarge" into "m5_xlarge" 46 | cleaner := func(r rune) rune { 47 | if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') { 48 | return r 49 | } 50 | return '_' 51 | } 52 | clean := bytes.Map(cleaner, []byte(orig)) 53 | 54 | return EnumValue{ 55 | Original: orig, 56 | Clean: string(clean), 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /pkg/model/error.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 model 15 | 16 | // TerminalExceptionCodes returns terminal exception codes as 17 | // []string for custom resource 18 | func (r *CRD) TerminalExceptionCodes() []string { 19 | return r.cfg.GetTerminalExceptionCodes(r.Names.Original) 20 | } 21 | 22 | // ExceptionCode returns the name of the resource's Exception code for the 23 | // Exception having the exception code. If the generator config has 24 | // instructions for overriding the name of an exception code for a resource for 25 | // a particular HTTP status code, we return that, otherwise we look through the 26 | // API model definitions looking for a match 27 | func (r *CRD) ExceptionCode(httpStatusCode int) string { 28 | if r.cfg != nil { 29 | resGenConfig, found := r.cfg.Resources[r.Names.Original] 30 | if found && resGenConfig.Exceptions != nil { 31 | if excConfig, present := resGenConfig.Exceptions.Errors[httpStatusCode]; present { 32 | return excConfig.Code 33 | } 34 | } 35 | } 36 | if r.Ops.ReadOne != nil { 37 | op := r.Ops.ReadOne 38 | for _, errShapeRef := range op.ErrorRefs { 39 | if errShapeRef.Shape.ErrorInfo.HTTPStatusCode == httpStatusCode { 40 | code := errShapeRef.Shape.ErrorInfo.Code 41 | if code != "" { 42 | return code 43 | } 44 | return errShapeRef.Shape.ShapeName 45 | } 46 | } 47 | } 48 | if r.Ops.ReadMany != nil { 49 | op := r.Ops.ReadMany 50 | for _, errShapeRef := range op.ErrorRefs { 51 | if errShapeRef.Shape.ErrorInfo.HTTPStatusCode == httpStatusCode { 52 | code := errShapeRef.Shape.ErrorInfo.Code 53 | if code != "" { 54 | return code 55 | } 56 | return errShapeRef.Shape.ShapeName 57 | } 58 | } 59 | } 60 | if r.Ops.GetAttributes != nil { 61 | op := r.Ops.GetAttributes 62 | for _, errShapeRef := range op.ErrorRefs { 63 | if errShapeRef.Shape.ErrorInfo.HTTPStatusCode == httpStatusCode { 64 | code := errShapeRef.Shape.ErrorInfo.Code 65 | if code != "" { 66 | return code 67 | } 68 | return errShapeRef.Shape.ShapeName 69 | } 70 | } 71 | } 72 | return "UNKNOWN" 73 | } 74 | -------------------------------------------------------------------------------- /pkg/model/model_eks_test.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 model_test 15 | 16 | import ( 17 | "strings" 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | "github.com/stretchr/testify/require" 22 | 23 | "github.com/aws-controllers-k8s/code-generator/pkg/model" 24 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 25 | ) 26 | 27 | func TestEKS_WithNestedReference(t *testing.T) { 28 | assert := assert.New(t) 29 | require := require.New(t) 30 | 31 | g := testutil.NewModelForServiceWithOptions(t, "eks", &testutil.TestingModelOptions{ 32 | GeneratorConfigFile: "generator-with-nested-reference.yaml", 33 | }) 34 | 35 | tds, err := g.GetTypeDefs() 36 | require.Nil(err) 37 | require.NotNil(tds) 38 | 39 | // ResourcesVpcConfig field's type is VpcConfigRequest 40 | var vpcConfigRequestTD *model.TypeDef 41 | 42 | for _, td := range tds { 43 | if td != nil && strings.EqualFold(td.Names.Original, "vpcConfigRequest") { 44 | vpcConfigRequestTD = td 45 | break 46 | } 47 | } 48 | assert.NotNil(vpcConfigRequestTD) 49 | securityGroupIdsAttr := vpcConfigRequestTD.GetAttribute("SecurityGroupIds") 50 | assert.NotNil(securityGroupIdsAttr) 51 | securityGroupRefsAttr := vpcConfigRequestTD.GetAttribute("SecurityGroupRefs") 52 | assert.NotNil(securityGroupRefsAttr) 53 | 54 | assert.Equal("SecurityGroupIDs", securityGroupIdsAttr.Names.Camel) 55 | assert.Equal("SecurityGroupRefs", securityGroupRefsAttr.Names.Camel) 56 | assert.Equal("[]*ackv1alpha1.AWSResourceReferenceWrapper", securityGroupRefsAttr.GoType) 57 | } 58 | -------------------------------------------------------------------------------- /pkg/model/model_emrcontainers_test.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 model_test 15 | 16 | import ( 17 | "testing" 18 | 19 | "github.com/stretchr/testify/assert" 20 | 21 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 22 | ) 23 | 24 | func TestEMRContainers_JobRun(t *testing.T) { 25 | assert := assert.New(t) 26 | 27 | g := testutil.NewModelForServiceWithOptions(t, "emrcontainers", &testutil.TestingModelOptions{ 28 | GeneratorConfigFile: "generator-with-cycle.yaml", 29 | }) 30 | 31 | assert.Panics(func() { g.GetCRDs() }) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/model/model_memorydb_test.go: -------------------------------------------------------------------------------- 1 | package model_test 2 | 3 | import ( 4 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 5 | "github.com/stretchr/testify/assert" 6 | "github.com/stretchr/testify/require" 7 | "testing" 8 | ) 9 | 10 | func TestUserPasswords_IsSecret(t *testing.T) { 11 | require := require.New(t) 12 | 13 | g := testutil.NewModelForService(t, "memorydb") 14 | crds, err := g.GetCRDs() 15 | 16 | require.Nil(err) 17 | 18 | crd := getCRDByName("User", crds) 19 | require.NotNil(crd) 20 | assert := assert.New(t) 21 | assert.Equal("[]*ackv1alpha1.SecretKeyReference", crd.SpecFields["AuthenticationMode"].MemberFields["Passwords"].GoType) 22 | assert.Equal("SecretKeyReference", crd.SpecFields["AuthenticationMode"].MemberFields["Passwords"].GoTypeElem) 23 | assert.Equal("[]*ackv1alpha1.SecretKeyReference", crd.SpecFields["AuthenticationMode"].MemberFields["Passwords"].GoTypeWithPkgName) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/model/model_mq_test.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 model_test 15 | 16 | import ( 17 | "testing" 18 | 19 | "github.com/stretchr/testify/assert" 20 | "github.com/stretchr/testify/require" 21 | 22 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 23 | ) 24 | 25 | func TestMQ_Broker(t *testing.T) { 26 | assert := assert.New(t) 27 | require := require.New(t) 28 | 29 | g := testutil.NewModelForService(t, "mq") 30 | 31 | crd := testutil.GetCRDByName(t, g, "Broker") 32 | require.NotNil(crd) 33 | 34 | // We want to verify that the `Password` field of the `Spec.Users` field 35 | // (which is a `[]*User` type) is findable in the CRD's Fields collection 36 | // by the path `Spec.Users..Password` and that the FieldConfig associated 37 | // with this Field is marked as a SecretKeyReference. 38 | passFieldPath := "Users.Password" 39 | passField, found := crd.Fields[passFieldPath] 40 | require.True(found) 41 | require.NotNil(passField.FieldConfig) 42 | assert.True(passField.FieldConfig.IsSecret) 43 | 44 | // We now verify that the User TypeDef that is inferred by the code 45 | // generator has had its Go type changed from `string` to 46 | // `*ackv1alpha1.SecretKeyReference` as part of the nested fields 47 | // post-processing of type defs in the GetTypeDefs() method. 48 | tdef := testutil.GetTypeDefByName(t, g, "User") 49 | require.NotNil(tdef) 50 | passAttr, found := tdef.Attrs["Password"] 51 | require.True(found) 52 | assert.Equal("*ackv1alpha1.SecretKeyReference", passAttr.GoType) 53 | } 54 | 55 | func TestMQ_GetOutputShapeGoType(t *testing.T) { 56 | assert := assert.New(t) 57 | require := require.New(t) 58 | 59 | g := testutil.NewModelForService(t, "mq") 60 | 61 | crd := testutil.GetCRDByName(t, g, "Broker") 62 | require.NotNil(crd) 63 | 64 | exp := "*svcsdk.CreateBrokerOutput" 65 | otype := crd.GetOutputShapeGoType(crd.Ops.Create) 66 | assert.Equal(exp, otype) 67 | } 68 | -------------------------------------------------------------------------------- /pkg/model/model_route53_test.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 model_test 15 | 16 | import ( 17 | "testing" 18 | 19 | "github.com/stretchr/testify/assert" 20 | "github.com/stretchr/testify/require" 21 | 22 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 23 | ) 24 | 25 | func TestRoute53_RecordSet(t *testing.T) { 26 | assert := assert.New(t) 27 | require := require.New(t) 28 | 29 | g := testutil.NewModelForService(t, "route53") 30 | 31 | crds, err := g.GetCRDs() 32 | require.Nil(err) 33 | 34 | crd := getCRDByName("RecordSet", crds) 35 | require.NotNil(crd) 36 | 37 | assert.Equal("RecordSet", crd.Names.Camel) 38 | assert.Equal("recordSet", crd.Names.CamelLower) 39 | assert.Equal("record_set", crd.Names.Snake) 40 | 41 | // The Route53 API has CD as one operation +L: 42 | // 43 | // * ChangeResourceRecordSets 44 | // * ChangeResourceRecordSets 45 | // * ListResourceRecordSets 46 | require.NotNil(crd.Ops) 47 | 48 | assert.NotNil(crd.Ops.Create) 49 | assert.NotNil(crd.Ops.ReadMany) 50 | assert.NotNil(crd.Ops.Delete) 51 | 52 | // But sadly, has no Update or ReadOne operation :( 53 | // for update we still use ChangeResourceRecordSets 54 | assert.Nil(crd.Ops.ReadOne) 55 | assert.Nil(crd.Ops.Update) 56 | 57 | specFields := crd.SpecFields 58 | statusFields := crd.StatusFields 59 | 60 | expSpecFieldCamel := []string{ 61 | "AliasTarget", 62 | // "ChangeBatch", <= Testing that this is removed from spec 63 | "CIDRRoutingConfig", 64 | "Failover", 65 | "GeoLocation", 66 | "HealthCheckID", 67 | "HostedZoneID", 68 | "HostedZoneRef", 69 | "MultiValueAnswer", 70 | "Name", 71 | "RecordType", 72 | "Region", 73 | "ResourceRecords", 74 | "SetIdentifier", 75 | "TTL", 76 | "Weight", 77 | } 78 | assert.Equal(expSpecFieldCamel, attrCamelNames(specFields)) 79 | 80 | expStatusFieldCamel := []string{ 81 | "ID", 82 | "Status", 83 | "SubmittedAt", 84 | } 85 | assert.Equal(expStatusFieldCamel, attrCamelNames(statusFields)) 86 | } 87 | -------------------------------------------------------------------------------- /pkg/model/model_sqs_test.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 model_test 15 | 16 | import ( 17 | "testing" 18 | 19 | "github.com/stretchr/testify/assert" 20 | "github.com/stretchr/testify/require" 21 | 22 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 23 | ) 24 | 25 | func TestSQS_Queue(t *testing.T) { 26 | assert := assert.New(t) 27 | require := require.New(t) 28 | 29 | g := testutil.NewModelForService(t, "sqs") 30 | 31 | crds, err := g.GetCRDs() 32 | require.Nil(err) 33 | 34 | crd := getCRDByName("Queue", crds) 35 | require.NotNil(crd) 36 | 37 | assert.Equal("Queue", crd.Names.Camel) 38 | assert.Equal("queue", crd.Names.CamelLower) 39 | assert.Equal("queue", crd.Names.Snake) 40 | 41 | // The SQS Queue API has CD+L operations: 42 | // 43 | // * CreateQueue 44 | // * DeleteQueue 45 | // * ListQueues 46 | require.NotNil(crd.Ops) 47 | 48 | assert.NotNil(crd.Ops.Create) 49 | assert.NotNil(crd.Ops.ReadMany) 50 | assert.NotNil(crd.Ops.Delete) 51 | assert.NotNil(crd.Ops.GetAttributes) 52 | assert.NotNil(crd.Ops.SetAttributes) 53 | 54 | // But sadly, has no Update or ReadOne operation :( 55 | // There is, however, GetQueueUrl and GetQueueAttributes calls... 56 | assert.Nil(crd.Ops.ReadOne) 57 | assert.Nil(crd.Ops.Update) 58 | 59 | specFields := crd.SpecFields 60 | statusFields := crd.StatusFields 61 | 62 | expSpecFieldCamel := []string{ 63 | "ContentBasedDeduplication", 64 | "CreatedTimestamp", 65 | "DelaySeconds", 66 | "FIFOQueue", 67 | "KMSDataKeyReusePeriodSeconds", 68 | "KMSMasterKeyID", 69 | "MaximumMessageSize", 70 | "MessageRetentionPeriod", 71 | "Policy", 72 | "QueueName", 73 | "ReceiveMessageWaitTimeSeconds", 74 | "RedrivePolicy", 75 | "Tags", 76 | "VisibilityTimeout", 77 | } 78 | assert.Equal(expSpecFieldCamel, attrCamelNames(specFields)) 79 | 80 | expStatusFieldCamel := []string{ 81 | // There are a set of Attribute map keys that are readonly 82 | // fields... 83 | // "CreatedTimestamp", 84 | // "LastModifiedTimestamp", 85 | // There is only a QueueURL field returned from CreateQueueResult shape 86 | "QueueURL", 87 | } 88 | assert.Equal(expStatusFieldCamel, attrCamelNames(statusFields)) 89 | } 90 | -------------------------------------------------------------------------------- /pkg/model/multiversion/delta_renames.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 multiversion 15 | 16 | import ( 17 | "errors" 18 | "fmt" 19 | ) 20 | 21 | var ( 22 | // ErrProhibitedRename is returned by ComputeRenamesDelta when a prohibited renaming 23 | // pattern is detected. 24 | // 25 | // One example of prohibited renaming is: renaming X to Y in v1 and Z to Y in v2. 26 | ErrProhibitedRename = errors.New("prohibited rename") 27 | ) 28 | 29 | // ComputeRenamesDelta returns a map representing the field renames map between two 30 | // distinguished api versions. 31 | // 32 | // Examples: 33 | // 34 | // if we rename X to Y in v1 and X to Y in v2 the map of renames is {} 35 | // if we rename X to Y in v1 and X to Z in v2 the map of renames is {Y: Z} 36 | // if we don't rename any field in v1 and we rename X to Y in v2 the map of renames if {X: Y} 37 | func ComputeRenamesDelta(srcRenames, dstRenames map[string]string) (map[string]string, error) { 38 | // returns an error if we find any prohibited or unsupported renaming pattern. 39 | for dstOld, dstNew := range dstRenames { 40 | for srcOld, srcNew := range srcRenames { 41 | if dstOld != srcOld && dstNew == srcNew { 42 | errMsg := fmt.Sprintf("found conflicting renames %s:%s and %s:%s", srcOld, srcNew, dstOld, dstNew) 43 | return nil, fmt.Errorf("%v: %s", ErrAPIVersionRemoved, errMsg) 44 | } 45 | } 46 | } 47 | 48 | renames := make(map[string]string) 49 | // loop over the destination renames and check if the same rename exists in the 50 | // source renames. 51 | for dstOld, dstNew := range dstRenames { 52 | srcNew, ok := srcRenames[dstOld] 53 | if ok { 54 | // if src and dst have the same renames - that's not a rename. 55 | if srcNew != dstNew { 56 | renames[srcNew] = dstNew 57 | } 58 | continue 59 | } 60 | renames[dstOld] = dstNew 61 | } 62 | 63 | // loop over the source renames and check the ones that don't exist in destination renames. 64 | for srcOld, srcNew := range srcRenames { 65 | _, ok := dstRenames[srcOld] 66 | if !ok { 67 | renames[srcNew] = srcOld 68 | } 69 | } 70 | return renames, nil 71 | } 72 | -------------------------------------------------------------------------------- /pkg/model/multiversion/delta_test.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 multiversion_test 15 | 16 | import ( 17 | "fmt" 18 | "testing" 19 | 20 | "github.com/stretchr/testify/assert" 21 | "github.com/stretchr/testify/require" 22 | 23 | "github.com/aws-controllers-k8s/code-generator/pkg/model/multiversion" 24 | "github.com/aws-controllers-k8s/code-generator/pkg/testutil" 25 | ) 26 | 27 | func TestAreEqualShapes_APIGatewayV2_DomainName(t *testing.T) { 28 | require := require.New(t) 29 | assert := assert.New(t) 30 | 31 | model := testutil.NewModelForServiceWithOptions(t, "apigatewayv2", &testutil.TestingModelOptions{}) 32 | crds, err := model.GetCRDs() 33 | require.Nil(err) 34 | require.Len(crds, 12) 35 | domainNameCRD := crds[4] 36 | 37 | for _, fieldNameX := range domainNameCRD.SpecFieldNames() { 38 | for _, fieldNameY := range domainNameCRD.SpecFieldNames() { 39 | testName := fmt.Sprintf("comparing %s with %s", fieldNameX, fieldNameY) 40 | t.Run(testName, func(t *testing.T) { 41 | 42 | fieldX := domainNameCRD.SpecFields[fieldNameX] 43 | fieldY := domainNameCRD.SpecFields[fieldNameY] 44 | equal, _ := multiversion.AreEqualShapes(fieldX.ShapeRef.Shape, fieldY.ShapeRef.Shape, false) 45 | if fieldNameY == fieldNameX { 46 | assert.True(equal) 47 | } else { 48 | assert.False(equal) 49 | } 50 | }) 51 | } 52 | } 53 | } 54 | 55 | func TestComputeCRDDeltas_APIGatewayV2_DomainName(t *testing.T) { 56 | require := require.New(t) 57 | assert := assert.New(t) 58 | 59 | model := testutil.NewModelForServiceWithOptions(t, "apigatewayv2", &testutil.TestingModelOptions{}) 60 | crds, err := model.GetCRDs() 61 | require.Nil(err) 62 | require.Len(crds, 12) 63 | domainNameCRD := crds[4] 64 | 65 | deltas, err := multiversion.ComputeCRDFieldDeltas(domainNameCRD, domainNameCRD) 66 | require.Nil(err) 67 | assert.Len(deltas.SpecDeltas, len(domainNameCRD.SpecFields)) 68 | assert.Len(deltas.StatusDeltas, len(domainNameCRD.StatusFields)) 69 | 70 | for _, delta := range deltas.SpecDeltas { 71 | assert.Equal(delta.ChangeType, multiversion.FieldChangeTypeNone) 72 | } 73 | for _, delta := range deltas.StatusDeltas { 74 | assert.Equal(delta.ChangeType, multiversion.FieldChangeTypeNone) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /pkg/model/type_def.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 model 15 | 16 | import ( 17 | "strings" 18 | 19 | awssdkmodel "github.com/aws-controllers-k8s/code-generator/pkg/api" 20 | "github.com/aws-controllers-k8s/pkg/names" 21 | ) 22 | 23 | // TypeDef is a Go type definition for structs that are member fields of the 24 | // Spec or Status structs in Custom Resource Definitions (CRDs). 25 | type TypeDef struct { 26 | Names names.Names 27 | Attrs map[string]*Attr 28 | Shape *awssdkmodel.Shape 29 | } 30 | 31 | // GetAttribute returns the Attribute with name "attrName". 32 | // This method performs case-insensitive matching to find the Attribute. 33 | func (td *TypeDef) GetAttribute(attrName string) *Attr { 34 | if td == nil { 35 | return nil 36 | } 37 | for aName, attr := range td.Attrs { 38 | if strings.EqualFold(aName, attrName) { 39 | return attr 40 | } 41 | } 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/model/types_test.go: -------------------------------------------------------------------------------- 1 | package model_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/aws-controllers-k8s/code-generator/pkg/model" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestReplacePkgName(t *testing.T) { 11 | assert := assert.New(t) 12 | testCases := []struct { 13 | subject string 14 | pkgName string 15 | replacePkgAlias string 16 | keepPointer bool 17 | want string 18 | }{ 19 | { // most frequent case 20 | "*ecr.Repository", 21 | "ecr", 22 | "svcsdk", 23 | true, 24 | "*svcsdk.Repository", 25 | }, 26 | { // don't keep pointer 27 | "*ecr.Repository", 28 | "ecr", 29 | "svcsdk", 30 | false, 31 | "svcsdk.Repository", 32 | }, 33 | { // non sdk type 34 | "*time.Time", 35 | "ecr", 36 | "svcsdk", 37 | true, 38 | "*time.Time", 39 | }, 40 | { // map type 41 | "map[string]*ecr.Repository", 42 | "ecr", 43 | "svcsdk", 44 | true, 45 | "map[string]*svcsdk.Repository", 46 | }, 47 | { // nested map type 48 | "map[string]map[string]uint8", 49 | "ec2", 50 | "svcsdk", 51 | true, 52 | "map[string]map[string]uint8", 53 | }, 54 | { // slice type 55 | "[]ecr.Repository", 56 | "ecr", 57 | "svcsdk", 58 | true, 59 | "[]svcsdk.Repository", 60 | }, 61 | { // nested slices type 62 | "[][]*codedeploy.EC2TagFilter", 63 | "codedeploy", 64 | "svcsdk", 65 | true, 66 | "[][]*svcsdk.EC2TagFilter", 67 | }, 68 | } 69 | 70 | for _, tc := range testCases { 71 | result := model.ReplacePkgName( 72 | tc.subject, 73 | tc.pkgName, 74 | tc.replacePkgAlias, 75 | tc.keepPointer, 76 | ) 77 | assert.Equal(tc.want, result) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /pkg/model/util_test.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 model_test 15 | 16 | import ( 17 | "sort" 18 | "strings" 19 | 20 | ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model" 21 | ) 22 | 23 | func attrCamelNames(fields map[string]*ackmodel.Field) []string { 24 | res := []string{} 25 | for _, attr := range fields { 26 | res = append(res, attr.Names.Camel) 27 | } 28 | sort.Strings(res) 29 | return res 30 | } 31 | 32 | func getCRDByName(name string, crds []*ackmodel.CRD) *ackmodel.CRD { 33 | for _, c := range crds { 34 | if strings.EqualFold(c.Names.Original, name) { 35 | return c 36 | } 37 | } 38 | return nil 39 | } 40 | 41 | func getTypeDefByName(name string, tdefs []*ackmodel.TypeDef) *ackmodel.TypeDef { 42 | for _, td := range tdefs { 43 | if strings.EqualFold(td.Names.Original, name) { 44 | return td 45 | } 46 | } 47 | return nil 48 | } 49 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/apigatewayv2/0000-00-00/generator-with-nested-reference.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Authorizer: 3 | fields: 4 | JwtConfiguration.Issuer: 5 | references: 6 | resource: API 7 | path: Status.APIID 8 | ignore: 9 | resource_names: 10 | - Api 11 | - ApiMapping 12 | - Deployment 13 | - DomainName 14 | - Integration 15 | - IntegrationResponse 16 | - Model 17 | - Route 18 | - RouteResponse 19 | - Stage 20 | - VpcLink 21 | 22 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/apigatewayv2/0000-00-00/generator-with-reference.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Integration: 3 | fields: 4 | ApiId: 5 | references: 6 | resource: API 7 | path: Status.APIID 8 | VpcLink: 9 | fields: 10 | SecurityGroupIds: 11 | references: 12 | resource: SecurityGroup 13 | path: Status.ID 14 | service_name: ec2 15 | SubnetIds: 16 | references: 17 | resource: Subnet 18 | path: Status.SubnetID 19 | service_name: ec2-modified #This is a dummy service name to validate multiple service references 20 | ignore: 21 | resource_names: 22 | - ApiMapping 23 | - Authorizer 24 | - Deployment 25 | - DomainName 26 | - IntegrationResponse 27 | - Model 28 | - Route 29 | - RouteResponse 30 | - Stage 31 | 32 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/apigatewayv2/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Api: 3 | fields: 4 | Body: 5 | from: 6 | operation: ImportApi 7 | path: Body 8 | Basepath: 9 | from: 10 | operation: ImportApi 11 | path: Basepath 12 | FailOnWarnings: 13 | from: 14 | operation: ImportApi 15 | path: FailOnWarnings 16 | Name: 17 | is_required: false 18 | ProtocolType: 19 | is_required: false 20 | update_operation: 21 | custom_method_name: customUpdateApi 22 | Route: 23 | tags: 24 | ignore: true 25 | operations: 26 | CreateApi: 27 | custom_implementation: customCreateApi 28 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/codedeploy/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Deployment: 3 | print: 4 | order_by: jsonpath 5 | exceptions: 6 | errors: 7 | 404: 8 | code: DeploymentDoesNotExistException 9 | # below, we're testing printer columns end up sorted properly in the CRD 10 | fields: 11 | DeploymentGroupName: 12 | print: 13 | name: DeploymentGroup 14 | ApplicationName: 15 | print: 16 | name: Application 17 | DeploymentConfigName: 18 | print: 19 | name: DeploymentConfig 20 | Description: 21 | print: {} 22 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/dynamodb/0000-00-00/generator-with-custom-shapes.yaml: -------------------------------------------------------------------------------- 1 | custom_shapes: 2 | RepicasState: 3 | RegionName: string 4 | RegionStatus: string 5 | RegionStatusDescription: string 6 | RegionStatusPercentProgress: string 7 | RegionInaccessibleDateTime: string 8 | 9 | resources: 10 | Table: 11 | fields: 12 | ReplicaStates: 13 | custom_field: 14 | list_of: RepicasState 15 | is_read_only: true -------------------------------------------------------------------------------- /pkg/testdata/models/apis/dynamodb/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Table: 3 | exceptions: 4 | errors: 5 | 404: 6 | code: ResourceNotFoundException 7 | synced: 8 | when: 9 | - path: Status.TableStatus 10 | in: 11 | - AVAILABLE 12 | - ACTIVE 13 | - path: Spec.ProvisionedThroughput.ReadCapacityUnits 14 | in: 15 | - 0 16 | - 10 17 | - path: Status.ItemCount 18 | in: 19 | - 0 20 | operations: 21 | DescribeBackup: 22 | # DescribeBackupOutput is an unusual shape because it contains information for 23 | # the backup it self (BackupDetails), the table details when the backup was 24 | # created (SourceTableDetails) and the table features (SourceTableFeatureDetails). 25 | # If not specified the code generator will try to determine the wrapper field by 26 | # selecting for the output shape that only have a single member, which is incorrect 27 | # in this case. 28 | output_wrapper_field_path: BackupDescription.BackupDetails 29 | ignore: 30 | field_paths: 31 | - DescribeTableOutput.Table.DeletionProtectionEnabled 32 | - DescribeTableOutput.Table.TableClassSummary 33 | - DescribeTableOutput.Table.WarmThroughput 34 | - GlobalSecondaryIndex.OnDemandThroughputOverride 35 | - GlobalSecondaryIndex.OnDemandThroughput 36 | - DescribeTableOutput.Table.OnDemandThroughput 37 | - GlobalSecondaryIndex.WarmThroughput 38 | - DescribeTableOutput.Table.MultiRegionConsistency 39 | - ReplicaGlobalSecondaryIndexDescription.OnDemandThroughputOverride 40 | - ReplicaGlobalSecondaryIndexDescription.WarmThroughput 41 | - ReplicaDescription.OnDemandThroughputOverride 42 | - ReplicaDescription.ReplicaInaccessibleDateTime 43 | - ReplicaDescription.ReplicaTableClassSummary 44 | - ReplicaDescription.WarmThroughput -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-renamed-identifier-field.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | renames: 4 | operations: 5 | CreateRepository: 6 | input_fields: 7 | RepositoryName: Name 8 | DescribeRepositories: 9 | input_fields: 10 | RepositoryName: Name 11 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-v1alpha1.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | exceptions: 4 | errors: 5 | 404: 6 | code: RepositoryNotFoundException 7 | list_operation: 8 | match_fields: 9 | - Name 10 | update_operation: 11 | custom_method_name: customUpdateRepository -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-v1alpha2.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | renames: 4 | operations: 5 | CreateRepository: 6 | input_fields: 7 | RepositoryName: Name 8 | ImageScanningConfiguration: ScanConfig 9 | DescribeRepository: 10 | input_fields: 11 | ImageScanningConfiguration: ScanConfig 12 | DeleteRepository: 13 | input_fields: 14 | RepositoryName: Name 15 | DescribeRepositories: 16 | input_fields: 17 | RepositoryName: Name 18 | ImageScanningConfiguration: ScanConfig 19 | exceptions: 20 | errors: 21 | 404: 22 | code: RepositoryNotFoundException 23 | list_operation: 24 | match_fields: 25 | - Name 26 | update_operation: 27 | custom_method_name: customUpdateRepository -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-v1alpha3.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | fields: 4 | ImageTagMutability: 5 | is_secret: true 6 | renames: 7 | operations: 8 | CreateRepository: 9 | input_fields: 10 | RepositoryName: Name 11 | ImageScanningConfiguration: ScanConfig 12 | DescribeRepository: 13 | input_fields: 14 | ImageScanningConfiguration: ScanConfig 15 | DeleteRepository: 16 | input_fields: 17 | RepositoryName: Name 18 | DescribeRepositories: 19 | input_fields: 20 | RepositoryName: Name 21 | ImageScanningConfiguration: ScanConfig 22 | exceptions: 23 | errors: 24 | 404: 25 | code: RepositoryNotFoundException 26 | list_operation: 27 | match_fields: 28 | - Name 29 | update_operation: 30 | custom_method_name: customUpdateRepository -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-with-field-config.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | fields: 4 | Name: 5 | is_primary_key: true 6 | exceptions: 7 | errors: 8 | 404: 9 | code: RepositoryNotFoundException 10 | list_operation: 11 | match_fields: 12 | - RepositoryName 13 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-with-late-initialize.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | fields: 4 | Name: 5 | late_initialize: {} 6 | ImageTagMutability: 7 | late_initialize: 8 | min_backoff_seconds: 5 9 | exceptions: 10 | errors: 11 | 404: 12 | code: RepositoryNotFoundException 13 | list_operation: 14 | match_fields: 15 | - RepositoryName 16 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator-with-nested-path-late-initialize.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | fields: 4 | Name: 5 | late_initialize: {} 6 | ImageScanningConfiguration.ScanOnPush: 7 | late_initialize: 8 | min_backoff_seconds: 5 9 | max_backoff_seconds: 15 10 | map..subfield.x: 11 | late_initialize: 12 | min_backoff_seconds: 5 13 | another.map..lastfield: 14 | late_initialize: 15 | min_backoff_seconds: 5 16 | some.list: 17 | late_initialize: 18 | min_backoff_seconds: 10 19 | structA.mapB..structC.valueD: 20 | late_initialize: 21 | min_backoff_seconds: 20 22 | exceptions: 23 | errors: 24 | 404: 25 | code: RepositoryNotFoundException 26 | list_operation: 27 | match_fields: 28 | - RepositoryName 29 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | exceptions: 4 | errors: 5 | 404: 6 | code: RepositoryNotFoundException 7 | list_operation: 8 | match_fields: 9 | - RepositoryName 10 | ignore: 11 | field_paths: 12 | - CreateRepositoryOutput.Repository.EncryptionConfiguration 13 | - CreateRepositoryInput.EncryptionConfiguration 14 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-01/generator-v1beta1.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | renames: 4 | operations: 5 | CreateRepository: 6 | input_fields: 7 | RepositoryName: Name 8 | ImageScanningConfiguration: ScanConfig 9 | DescribeRepository: 10 | input_fields: 11 | ImageScanningConfiguration: ScanConfig 12 | DeleteRepository: 13 | input_fields: 14 | RepositoryName: Name 15 | DescribeRepositories: 16 | input_fields: 17 | RepositoryName: Name 18 | ImageScanningConfiguration: ScanConfig 19 | exceptions: 20 | errors: 21 | 404: 22 | code: RepositoryNotFoundException 23 | list_operation: 24 | match_fields: 25 | - Name 26 | update_operation: 27 | custom_method_name: customUpdateRepository -------------------------------------------------------------------------------- /pkg/testdata/models/apis/ecr/0000-00-01/generator-v1beta2.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Repository: 3 | fields: 4 | AnotherNameField: 5 | from: 6 | operation: CreateRepository 7 | path: RepositoryName 8 | renames: 9 | operations: 10 | CreateRepository: 11 | input_fields: 12 | RepositoryName: Name 13 | ImageScanningConfiguration: ScanConfig 14 | DescribeRepository: 15 | input_fields: 16 | ImageScanningConfiguration: ScanConfig 17 | DeleteRepository: 18 | input_fields: 19 | RepositoryName: Name 20 | DescribeRepositories: 21 | input_fields: 22 | RepositoryName: Name 23 | ImageScanningConfiguration: ScanConfig 24 | exceptions: 25 | errors: 26 | 404: 27 | code: RepositoryNotFoundException 28 | list_operation: 29 | match_fields: 30 | - Name 31 | update_operation: 32 | custom_method_name: customUpdateRepository -------------------------------------------------------------------------------- /pkg/testdata/models/apis/eks/0000-00-00/documentation.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Cluster: 3 | fields: 4 | RoleARN: 5 | append: | 6 | !!! Hello earthlings! I have come to assume your permissions. 7 | ResourcesVPCConfig.SecurityGroupIDs: 8 | prepend: | 9 | !!! Let's take it from the top 10 | Identity.OIDC.Issuer: 11 | override: | 12 | !!! All your docs has become mine 13 | 14 | That whitespace is entirely on purpose -------------------------------------------------------------------------------- /pkg/testdata/models/apis/eks/0000-00-00/generator-with-gotag.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Cluster: 3 | fields: 4 | Version: 5 | go_tag: json:"myCustomVersionName,omitempty" 6 | Status: 7 | go_tag: json:"clusterState,omitempty" yaml:"some_extra_tags" -------------------------------------------------------------------------------- /pkg/testdata/models/apis/eks/0000-00-00/generator-with-nested-reference.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Cluster: 3 | fields: 4 | ResourcesVpcConfig.SecurityGroupIds: 5 | references: 6 | service_name: ec2 7 | resource: SecurityGroup 8 | path: Status.ID -------------------------------------------------------------------------------- /pkg/testdata/models/apis/eks/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | FargateProfile: 3 | renames: 4 | operations: 5 | CreateFargateProfile: 6 | input_fields: 7 | FargateProfileName: Name 8 | DescribeFargateProfile: 9 | input_fields: 10 | FargateProfileName: Name 11 | DeleteFargateProfile: 12 | input_fields: 13 | FargateProfileName: Name -------------------------------------------------------------------------------- /pkg/testdata/models/apis/emrcontainers/0000-00-00/generator-with-cycle.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | field_paths: 3 | # We would need to ignore the following line to ensure there are no cycles 4 | # in the property graph. 5 | # - Configuration.Configurations 6 | operations: null 7 | resource_names: 8 | - VirtualCluster 9 | # - JobRun 10 | - ManagedEndpoint 11 | shape_names: null 12 | model_name: emr-containers 13 | operations: 14 | StartJobRun: 15 | operation_type: Create 16 | resource_name: JobRun 17 | CancelJobRun: 18 | operation_type: Delete 19 | resource_name: JobRun 20 | DescribeJobRun: 21 | output_wrapper_field_path: JobRun -------------------------------------------------------------------------------- /pkg/testdata/models/apis/eventbridge/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | operations: 2 | PutRule: 3 | operation_type: 4 | - Create 5 | - Update 6 | resource_name: Rule 7 | resources: 8 | Rule: 9 | fields: 10 | Targets: 11 | custom_field: 12 | list_of: Target -------------------------------------------------------------------------------- /pkg/testdata/models/apis/iam/0000-00-00/generator-oidc-url.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - AccessKey 4 | - AccountAlias 5 | - Group 6 | - InstanceProfile 7 | - LoginProfile 8 | # OpenIDConnectProvider 9 | - Policy 10 | - PolicyVersion 11 | - Role 12 | - SAMLProvider 13 | - ServiceLinkedRole 14 | - ServiceSpecificCredential 15 | - User 16 | - VirtualMFADevice 17 | resources: 18 | OpenIDConnectProvider: 19 | fields: 20 | URL: 21 | compare: 22 | is_ignored: true -------------------------------------------------------------------------------- /pkg/testdata/models/apis/iam/0000-00-00/generator-user-newpath.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - AccessKey 4 | - AccountAlias 5 | - Group 6 | - InstanceProfile 7 | - LoginProfile 8 | - OpenIDConnectProvider 9 | - Policy 10 | - PolicyVersion 11 | - Role 12 | - SAMLProvider 13 | - ServiceLinkedRole 14 | - ServiceSpecificCredential 15 | # User 16 | - VirtualMFADevice 17 | resources: 18 | User: 19 | fields: 20 | Path: 21 | set: 22 | - method: Update 23 | to: NewPath -------------------------------------------------------------------------------- /pkg/testdata/models/apis/iam/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - AccessKey 4 | - AccountAlias 5 | - Group 6 | - InstanceProfile 7 | - LoginProfile 8 | - OpenIDConnectProvider 9 | - Policy 10 | - PolicyVersion 11 | #- Role 12 | - SAMLProvider 13 | - ServiceLinkedRole 14 | - ServiceSpecificCredential 15 | #- User 16 | - VirtualMFADevice 17 | resources: 18 | Role: 19 | renames: 20 | operations: 21 | CreateRole: 22 | input_fields: 23 | RoleName: Name 24 | GetRole: 25 | input_fields: 26 | RoleName: Name 27 | UpdateRole: 28 | input_fields: 29 | RoleName: Name 30 | DeleteRole: 31 | input_fields: 32 | RoleName: Name 33 | fields: 34 | PermissionsBoundary: 35 | set: 36 | # The input and output shapes are different... 37 | - from: PermissionsBoundary.PermissionsBoundaryArn 38 | # Test the custom field creation inference for simple scalar, list or map 39 | # fields 40 | Policies: 41 | type: "[]*string" 42 | LoggingConfig: 43 | type: "map[string]*bool" 44 | MyCustomInteger: 45 | type: "*int64" 46 | User: 47 | renames: 48 | operations: 49 | CreateUser: 50 | input_fields: 51 | UserName: Name 52 | fields: 53 | PermissionsBoundary: 54 | references: 55 | resource: Policy 56 | path: Status.ACKResourceMetadata.ARN 57 | set: 58 | # The input and output shapes are different... 59 | - from: PermissionsBoundary.PermissionsBoundaryArn 60 | # In order to support attaching zero or more policies to a user, we use 61 | # custom update code path code that uses the Attach/DetachUserPolicy API 62 | # calls to manage the set of PolicyARNs attached to this User. 63 | Policies: 64 | type: "[]*string" 65 | references: 66 | resource: Policy 67 | path: Status.ACKResourceMetadata.ARN 68 | Tags: 69 | compare: 70 | is_ignored: true -------------------------------------------------------------------------------- /pkg/testdata/models/apis/lambda/0000-00-00/generator-lambda-ignore-code-sha256.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Function: 3 | fields: 4 | Code.S3SHA256: 5 | type: string 6 | set: 7 | - ignore: "to" 8 | method: Create -------------------------------------------------------------------------------- /pkg/testdata/models/apis/lambda/0000-00-00/generator-with-custom-nested-types.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Function: 3 | synced: 4 | when: 5 | - path: Status.State 6 | in: [ "Active" ] 7 | fields: 8 | Code.S3SHA256: 9 | type: string 10 | compare: 11 | is_ignored: true 12 | set: 13 | - ignore: true 14 | method: Create 15 | ImageConfigResponse.Error.New: 16 | is_read_only: true 17 | type: string 18 | EventSourceMapping: 19 | fields: 20 | DestinationConfig.OnSuccess.New: 21 | type: string 22 | compare: 23 | is_ignored: true 24 | 25 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/lambda/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Function: 3 | fields: 4 | CodeLocation: 5 | is_read_only: true 6 | from: 7 | operation: GetFunction 8 | path: Code.Location 9 | CodeRepositoryType: 10 | is_read_only: true 11 | from: 12 | operation: GetFunction 13 | path: Code.RepositoryType 14 | synced: 15 | when: 16 | - path: Status.State 17 | in: 18 | - AVAILABLE 19 | - ACTIVE 20 | - path: Status.LastUpdateStatus 21 | in: 22 | - AVAILABLE 23 | - ACTIVE 24 | - path: Status.CodeSize 25 | in: 26 | - 1 27 | - 2 28 | CodeSigningConfig: 29 | fields: 30 | Tags: 31 | compare: 32 | is_ignored: true 33 | ignore: 34 | field_paths: 35 | - CreateFunctionInput.Architectures 36 | - CreateFunctionInput.LoggingConfig 37 | - CreateFunctionInput.EphemeralStorage 38 | - FunctionCode.SourceKMSKeyArn 39 | - CreateFunctionInput.SnapStart 40 | - CreateFunctionInput.VpcConfig.Ipv6AllowedForDualStack 41 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/memorydb/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - Snapshot 4 | - ACL 5 | - Cluster 6 | - SubnetGroup 7 | - ParameterGroup 8 | resources: 9 | User: 10 | exceptions: 11 | terminal_codes: 12 | - InvalidParameterValueException 13 | - UserAlreadyExistsFault 14 | renames: 15 | operations: 16 | CreateUser: 17 | input_fields: 18 | UserName: Name 19 | UpdateUser: 20 | input_fields: 21 | UserName: Name 22 | DeleteUser: 23 | input_fields: 24 | UserName: Name 25 | DescribeUsers: 26 | input_fields: 27 | UserName: Name 28 | fields: 29 | AuthenticationMode.Passwords: 30 | is_secret: true 31 | compare: 32 | is_ignored: true -------------------------------------------------------------------------------- /pkg/testdata/models/apis/mq/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resources: 3 | - Configuration 4 | - User 5 | field_paths: 6 | - CreateBrokerInput.DataReplicationMode 7 | - CreateBrokerInput.DataReplicationPrimaryBrokerArn 8 | - User.ReplicationUser 9 | resources: 10 | Broker: 11 | hooks: 12 | sdk_update_pre_build_request: 13 | code: if err := rm.requeueIfNotRunning(latest); err != nil { return nil, err } 14 | sdk_delete_pre_build_request: 15 | template_path: sdk_delete_pre_build_request.go.tpl 16 | fields: 17 | Users.Password: 18 | is_secret: true 19 | update_operation: 20 | omit_unchanged_fields: true -------------------------------------------------------------------------------- /pkg/testdata/models/apis/opensearch/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | sdk_names: 2 | model_name: opensearch 3 | package_name: opensearch 4 | ignore: 5 | resource_names: 6 | - Application 7 | - Package 8 | # - Domain 9 | - OutboundConnection 10 | - VpcEndpoint 11 | field_paths: 12 | # SnapshotOptions is irrelevant for OpenSearch 5.3+ 13 | - CreateDomainInput.SnapshotOptions 14 | resources: 15 | Domain: 16 | renames: 17 | operations: 18 | CreateDomain: 19 | input_fields: 20 | DomainName: Name 21 | TagList: Tags 22 | DeleteDomain: 23 | input_fields: 24 | DomainName: Name 25 | DescribeDomain: 26 | input_fields: 27 | DomainName: Name 28 | reconcile: 29 | # Doing this because it takes a LONG time for the Domain's 30 | # endpoint/endpoints field to be populated, even after the Domain's 31 | # Processing field is set to False after creation... 32 | requeue_on_success_seconds: 60 33 | exceptions: 34 | errors: 35 | 404: 36 | code: ResourceNotFoundException 37 | terminal_codes: 38 | - ValidationException 39 | hooks: 40 | sdk_create_post_set_output: 41 | template_path: hooks/domain/sdk_create_post_set_output.go.tpl 42 | sdk_read_one_post_set_output: 43 | template_path: hooks/domain/sdk_read_one_post_set_output.go.tpl 44 | sdk_update_pre_build_request: 45 | template_path: hooks/domain/sdk_update_pre_build_request.go.tpl 46 | sdk_delete_pre_build_request: 47 | template_path: hooks/domain/sdk_delete_pre_build_request.go.tpl 48 | fields: 49 | AdvancedSecurityOptions.MasterUserOptions.MasterUserPassword: 50 | is_secret: true 51 | update_operation: 52 | custom_method_name: customUpdateDomain 53 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/s3/0000-00-00/generator-with-nested-references.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - Object 4 | - MultipartUpload 5 | shape_names: 6 | # These shapes are structs with no members... 7 | - SSES3 8 | field_paths: 9 | # We cannot support MFA, so if it is set we cannot unset 10 | - "VersioningConfiguration.MFADelete" 11 | # This subfield struct has no members... 12 | - "NotificationConfiguration.EventBridgeConfiguration" 13 | resources: 14 | Bucket: 15 | renames: 16 | operations: 17 | CreateBucket: 18 | input_fields: 19 | Bucket: Name 20 | DeleteBucket: 21 | input_fields: 22 | Bucket: Name 23 | list_operation: 24 | match_fields: 25 | - Name 26 | fields: 27 | Logging: 28 | from: 29 | operation: PutBucketLogging 30 | path: BucketLoggingStatus 31 | Logging.LoggingEnabled.TargetBucket: 32 | references: 33 | resource: Bucket 34 | path: Spec.Name 35 | Notification: 36 | from: 37 | operation: PutBucketNotificationConfiguration 38 | path: NotificationConfiguration 39 | Notification.LambdaFunctionConfigurations.Filter.Key.FilterRules.Value: 40 | references: 41 | resource: Bucket 42 | path: Spec.Name # This is a nonsense reference just to test the case of nested slices 43 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/s3/0000-00-00/generator-with-tags.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - Object 4 | - MultipartUpload 5 | shape_names: 6 | # These shapes are structs with no members... 7 | - SSES3 8 | resources: 9 | Bucket: 10 | tags: 11 | path: Tagging.TagSet 12 | renames: 13 | operations: 14 | CreateBucket: 15 | input_fields: 16 | Bucket: Name 17 | DeleteBucket: 18 | input_fields: 19 | Bucket: Name 20 | list_operation: 21 | match_fields: 22 | - Name 23 | fields: 24 | Tagging: 25 | from: 26 | operation: PutBucketTagging 27 | path: Tagging 28 | ACL: 29 | # This is to test the ackcompare field ignore functionality. This 30 | # should NOT be in a production generator.yaml... 31 | compare: 32 | is_ignored: true 33 | Logging: 34 | from: 35 | operation: PutBucketLogging 36 | path: BucketLoggingStatus -------------------------------------------------------------------------------- /pkg/testdata/models/apis/s3/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | resource_names: 3 | - Object 4 | - MultipartUpload 5 | shape_names: 6 | # These shapes are structs with no members... 7 | - SSES3 8 | field_paths: 9 | - CreateBucketInput.ObjectOwnership 10 | - CreateBucketConfiguration.Bucket 11 | - CreateBucketConfiguration.Location 12 | - BucketLoggingStatus.LoggingEnabled.TargetObjectKeyFormat 13 | resources: 14 | Bucket: 15 | renames: 16 | operations: 17 | CreateBucket: 18 | input_fields: 19 | Bucket: Name 20 | DeleteBucket: 21 | input_fields: 22 | Bucket: Name 23 | list_operation: 24 | match_fields: 25 | - Name 26 | tags: 27 | path: Tagging.TagSet 28 | fields: 29 | ACL: 30 | # This is to test the ackcompare field ignore functionality. This 31 | # should NOT be in a production generator.yaml... 32 | compare: 33 | is_ignored: true 34 | Logging: 35 | from: 36 | operation: PutBucketLogging 37 | path: BucketLoggingStatus 38 | Tagging: 39 | from: 40 | operation: PutBucketTagging 41 | path: Tagging -------------------------------------------------------------------------------- /pkg/testdata/models/apis/sns/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Topic: 3 | is_arn_primary_key: true 4 | unpack_attributes_map: 5 | set_attributes_single_attribute: true 6 | fields: 7 | DeliveryPolicy: 8 | is_attribute: true 9 | DisplayName: 10 | is_attribute: true 11 | Policy: 12 | is_attribute: true 13 | KmsMasterKeyId: 14 | is_attribute: true 15 | Owner: 16 | is_attribute: true 17 | is_read_only: true 18 | is_owner_account_id: true 19 | EffectiveDeliveryPolicy: 20 | is_attribute: true 21 | is_read_only: true 22 | TopicArn: 23 | is_attribute: true 24 | is_read_only: true 25 | PlatformApplication: 26 | fields: 27 | PlatformCredential: 28 | is_attribute: true 29 | PlatformPrincipal: 30 | is_attribute: true 31 | EventEndpointCreated: 32 | is_attribute: true 33 | EventEndpointDeleted: 34 | is_attribute: true 35 | EventEndpointUpdated: 36 | is_attribute: true 37 | EventDeliveryFailure: 38 | is_attribute: true 39 | SuccessFeedbackRoleArn: 40 | is_attribute: true 41 | FailureFeedbackRoleArn: 42 | is_attribute: true 43 | SuccessFeedbackSampleRate: 44 | is_attribute: true 45 | Endpoint: 46 | fields: 47 | CustomUserData: 48 | is_attribute: true 49 | Enabled: 50 | is_attribute: true 51 | Token: 52 | is_attribute: true 53 | ignore: 54 | field_paths: 55 | - CreateTopicInput.DataProtectionPolicy 56 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/sqs/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | Queue: 3 | unpack_attributes_map: 4 | get_attributes_input: 5 | overrides: 6 | AttributeNames: 7 | values: 8 | - All 9 | fields: 10 | DelaySeconds: 11 | is_attribute: true 12 | MaximumMessageSize: 13 | is_attribute: true 14 | MessageRetentionPeriod: 15 | is_attribute: true 16 | KmsMasterKeyId: 17 | is_attribute: true 18 | KmsDataKeyReusePeriodSeconds: 19 | is_attribute: true 20 | Policy: 21 | is_attribute: true 22 | ReceiveMessageWaitTimeSeconds: 23 | is_attribute: true 24 | VisibilityTimeout: 25 | is_attribute: true 26 | FifoQueue: 27 | is_attribute: true 28 | ContentBasedDeduplication: 29 | is_attribute: true 30 | RedrivePolicy: 31 | is_attribute: true 32 | CreatedTimestamp: 33 | is_attribute: true 34 | QueueArn: 35 | is_attribute: true 36 | is_read_only: true 37 | QueueUrl: 38 | is_read_only: true 39 | is_primary_key: true 40 | -------------------------------------------------------------------------------- /pkg/testdata/models/apis/wafv2/0000-00-00/generator.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | field_paths: 3 | - RuleGroup.Rules.Statement.AndStatement 4 | - RuleGroup.Rules.Statement.OrStatement 5 | - RuleGroup.Rules.Statement.NotStatement 6 | - RuleGroup.Rules.Statement.ManagedRuleGroupStatement.ScopeDownStatement 7 | - RuleGroup.Rules.Statement.RateBasedStatement.ScopeDownStatement 8 | empty_shapes: 9 | - All 10 | - Method 11 | - UriPath 12 | - QueryString 13 | - AllQueryArguments 14 | - RateLimitIP 15 | - RateLimitForwardedIP 16 | - RateLimitHTTPMethod 17 | - NoneAction 18 | operations: 19 | GetRuleGroup: 20 | output_wrapper_field_path: RuleGroup 21 | resources: 22 | RuleGroup: 23 | fields: 24 | Rules.Statement.AndStatement: 25 | type: string 26 | set: 27 | - ignore: "all" 28 | Rules.Statement.OrStatement: 29 | type: string 30 | set: 31 | - ignore: "all" 32 | Rules.Statement.NotStatement: 33 | type: string 34 | set: 35 | - ignore: "all" 36 | Rules.Statement.ManagedRuleGroupStatement.ScopeDownStatement: 37 | type: string 38 | set: 39 | - ignore: "all" 40 | Rules.Statement.RateBasedStatement.ScopeDownStatement: 41 | type: string 42 | set: 43 | - ignore: "all" 44 | -------------------------------------------------------------------------------- /pkg/testdata/models/metadata.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | full_name: Amazon Test Service 3 | short_name: ATS 4 | link: https://example.com/ 5 | documentation: https://docs.example.com/ 6 | versions: 7 | - api_version: v1alpha1 8 | status: available -------------------------------------------------------------------------------- /pkg/testutil/get.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 testutil 15 | 16 | import ( 17 | "testing" 18 | 19 | "github.com/stretchr/testify/require" 20 | 21 | "github.com/aws-controllers-k8s/code-generator/pkg/model" 22 | ackmodel "github.com/aws-controllers-k8s/code-generator/pkg/model" 23 | ) 24 | 25 | // GetCRDByName returns a CRD model with the supplied name 26 | func GetCRDByName( 27 | t *testing.T, 28 | m *ackmodel.Model, 29 | name string, 30 | ) *model.CRD { 31 | require := require.New(t) 32 | 33 | crds, err := m.GetCRDs() 34 | require.Nil(err) 35 | 36 | for _, c := range crds { 37 | if c.Names.Original == name { 38 | return c 39 | } 40 | } 41 | return nil 42 | } 43 | 44 | // GetTypeDefByName returns a TypeDef model with the supplied name 45 | func GetTypeDefByName( 46 | t *testing.T, 47 | m *ackmodel.Model, 48 | name string, 49 | ) *model.TypeDef { 50 | require := require.New(t) 51 | 52 | tdefs, err := m.GetTypeDefs() 53 | require.Nil(err) 54 | 55 | for _, tdef := range tdefs { 56 | if tdef.Names.Original == name { 57 | return tdef 58 | } 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /pkg/util/file.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 | "io" 18 | "os" 19 | ) 20 | 21 | // FileExists returns True if the supplied file path exists, false otherwise 22 | func FileExists(path string) bool { 23 | _, err := os.Stat(path) 24 | return !os.IsNotExist(err) 25 | } 26 | 27 | // CopyFile copies a file from a source path to a destination path. 28 | func CopyFile(src, dest string) error { 29 | srcFile, err := os.Open(src) 30 | if err != nil { 31 | return err 32 | } 33 | defer srcFile.Close() 34 | 35 | destFile, err := os.Create(dest) 36 | if err != nil { 37 | return err 38 | } 39 | defer destFile.Close() 40 | 41 | _, err = io.Copy(destFile, srcFile) 42 | if err != nil { 43 | return err 44 | } 45 | 46 | err = destFile.Sync() 47 | if err != nil { 48 | return err 49 | } 50 | 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/util/in.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 | // InStrings returns true if the subject string is contained in the supplied 17 | // slice of strings 18 | func InStrings(subject string, collection []string) bool { 19 | for _, item := range collection { 20 | if subject == item { 21 | return true 22 | } 23 | } 24 | return false 25 | } 26 | -------------------------------------------------------------------------------- /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 | package version 15 | 16 | import ( 17 | "fmt" 18 | "runtime" 19 | ) 20 | 21 | var ( 22 | // BuildDate of application at compile time (-X 'main.buildDate=$(BUILDDATE)'). 23 | BuildDate string = "No Build Date Provided." 24 | // Version of application at compile time (-X 'main.version=$(VERSION)'). 25 | Version string = "(Unknown Version)" 26 | // BuildHash is the GIT hash of application at compile time (-X 'main.buildHash=$(GITCOMMIT)'). 27 | BuildHash string = "No Git-hash Provided." 28 | // GoVersion is the Go compiler version used to compile this binary 29 | GoVersion string 30 | ) 31 | 32 | func init() { 33 | GoVersion = fmt.Sprintf("%s %s/%s", runtime.Version(), runtime.GOOS, runtime.GOARCH) 34 | } 35 | -------------------------------------------------------------------------------- /scripts/construct-metadata.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 6 | SCRIPTS_DIR=$DIR 7 | ROOT_DIR=$DIR/.. 8 | 9 | source "$SCRIPTS_DIR/lib/metadata.sh" 10 | 11 | USAGE=" 12 | Usage: 13 | $(basename "$0") 14 | 15 | Constructs a new metadata.yaml file for a fresh service. 16 | 17 | Example: $(basename "$0") ecr 18 | 19 | should be an AWS Service name (ecr, sns, sqs, petstore, bookstore) 20 | 21 | Environment variables: 22 | SERVICE_CONTROLLER_SOURCE_PATH: Directory to find the service controller to build an image for. 23 | Default: ../\$AWS_SERVICE-controller 24 | " 25 | 26 | if [ $# -ne 1 ]; then 27 | echo "AWS_SERVICE is not defined. Script accepts one parameter, the to build a container image of that service" 1>&2 28 | echo "${USAGE}" 29 | exit 1 30 | fi 31 | 32 | AWS_SERVICE=$(echo "$1" | tr '[:upper:]' '[:lower:]') 33 | 34 | # Source code for the controller will be in a separate repo, typically in 35 | # $GOPATH/src/github.com/aws-controllers-k8s/$AWS_SERVICE-controller/ 36 | DEFAULT_SERVICE_CONTROLLER_SOURCE_PATH="$ROOT_DIR/../$AWS_SERVICE-controller" 37 | SERVICE_CONTROLLER_SOURCE_PATH=${SERVICE_CONTROLLER_SOURCE_PATH:-$DEFAULT_SERVICE_CONTROLLER_SOURCE_PATH} 38 | 39 | if [[ ! -d $SERVICE_CONTROLLER_SOURCE_PATH ]]; then 40 | echo "Error evaluating SERVICE_CONTROLLER_SOURCE_PATH environment variable:" 1>&2 41 | echo "$SERVICE_CONTROLLER_SOURCE_PATH is not a directory." 1>&2 42 | echo "${USAGE}" 43 | exit 1 44 | fi 45 | 46 | METADATA_TEMPLATE_PATH="$ROOT_DIR/templates/metadata.yaml" 47 | 48 | DEFAULT_METADATA_OUTPUT_PATH="$SERVICE_CONTROLLER_SOURCE_PATH/metadata.yaml" 49 | METADATA_OUTPUT_PATH="${METADATA_OUTPUT_PATH:-$DEFAULT_METADATA_OUTPUT_PATH}" 50 | 51 | echo "🧙 Welcome to the service metadata setup wizard" 52 | echo "⚠️ WARNING: This script will overwrite the metadata.yaml file in your service controller path" 53 | 54 | echo -n "Enter the service's full name [e.g. Amazon Elastic Kubernetes Service]: " 55 | read -r full_name 56 | 57 | echo -n "Enter the service's acronym [e.g. EKS, S3, EC2]: " 58 | read -r short_name 59 | 60 | echo -n "Enter the URL for the service homepage [e.g. https://aws.amazon.com/eks/]: " 61 | read -r link 62 | 63 | echo -n "Enter the URL for the service's documentation [e.g. https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html]: " 64 | read -r documentation 65 | 66 | echo -n "Generating metadata ... " 67 | write_new_metadata "$METADATA_TEMPLATE_PATH" "$METADATA_OUTPUT_PATH" "$full_name" "$short_name" "$link" "$documentation" 68 | echo "Success!" -------------------------------------------------------------------------------- /scripts/install-controller-gen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ./scripts/install-controller-gen.sh 4 | # 5 | # Checks that the `controller-gen` binary is available on the host system and 6 | # if it is, that it matches the exact version that we require in order to 7 | # standardize the YAML manifests for CRDs and Kubernetes Roles. 8 | # 9 | # If the locally-installed controller-gen does not match the required version, 10 | # prints an error message asking the user to uninstall it. 11 | # 12 | # NOTE: We use this technique of building using `go build` within a temp 13 | # directory because controller-tools does not have a binary release artifact 14 | # for controller-gen. 15 | # 16 | # See: https://github.com/kubernetes-sigs/controller-tools/issues/500 17 | 18 | set -eo pipefail 19 | 20 | SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 21 | 22 | source "$SCRIPTS_DIR/lib/common.sh" 23 | 24 | if ! is_installed controller-gen || ! k8s_controller_gen_version_equals "$CONTROLLER_TOOLS_VERSION"; then 25 | # GOBIN and GOPATH are not always set, so default to GOPATH from `go env` 26 | __GOPATH=$(go env GOPATH) 27 | __install_dir=${GOBIN:-$__GOPATH/bin} 28 | # If __install_dir does not exist, create it 29 | [[ -d $__install_dir ]] || mkdir -p "$__install_dir" 30 | __install_path="$__install_dir/controller-gen" 31 | __work_dir=$(mktemp -d /tmp/controller-gen-XXX) 32 | 33 | echo -n "installing controller-gen ${CONTROLLER_TOOLS_VERSION} ... " 34 | cd "$__work_dir" 35 | 36 | go mod init tmp 1>/dev/null 2>&1 37 | go get -d "sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_TOOLS_VERSION}" 1>/dev/null 2>&1 38 | go build -o "$__work_dir/controller-gen" sigs.k8s.io/controller-tools/cmd/controller-gen 1>/dev/null 2>&1 39 | mv "$__work_dir/controller-gen" "$__install_path" 40 | 41 | rm -rf "$WORK_DIR" 42 | echo "ok." 43 | fi 44 | -------------------------------------------------------------------------------- /scripts/install-helm.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ./scripts/install-helm.sh 4 | # 5 | # Installs the latest version helm if not installed. 6 | # 7 | # NOTE: helm will be installed to /usr/local/bin/helm 8 | 9 | set -eo pipefail 10 | 11 | SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 12 | 13 | source "$SCRIPTS_DIR/lib/common.sh" 14 | 15 | if ! is_installed helm ; then 16 | __helm_url="https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3" 17 | echo -n "installing helm from $__helm_url ... " 18 | curl --silent "$__helm_url" | bash 1>/dev/null 19 | echo "ok." 20 | fi 21 | -------------------------------------------------------------------------------- /scripts/install-kustomize.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ./scripts/install-kustomize.sh 4 | # 5 | # Installs the latest version kustomize if not installed. 6 | # 7 | # NOTE: uses `sudo mv` to relocate a downloaded binary to /usr/local/bin/kustomize 8 | 9 | set -eo pipefail 10 | 11 | SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 12 | 13 | source "$SCRIPTS_DIR/lib/common.sh" 14 | 15 | if ! is_installed kustomize ; then 16 | __kustomize_url="https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" 17 | echo -n "installing kustomize from $__kustomize_url ... " 18 | curl --silent "$__kustomize_url" | bash 1>/dev/null 19 | chmod +x kustomize 20 | sudo mv kustomize /usr/local/bin/kustomize 21 | echo "ok." 22 | fi 23 | -------------------------------------------------------------------------------- /scripts/install-operator-sdk.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # ./scripts/install-operator-sdk.sh 4 | # 5 | # 6 | # Installs Operator SDK if not installed. Optional parameters specifies the 7 | # version of Operator SDK to install. Defaults tot eh value of the environment 8 | # variable OPERATOR_SDK_VERSION and if that is not set, the value of the 9 | # DEFAULT_OPERATOR_SDK_VERSION variable. 10 | # 11 | # NOTE: uses `sudo mv` to relocate a downloaded binary to /code-generator/bin/operator-sdk 12 | 13 | set -eo pipefail 14 | 15 | SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 16 | ROOT_DIR="$SCRIPTS_DIR/.." 17 | DEFAULT_OPERATOR_SDK_BIN_PATH="$ROOT_DIR/../code-generator/bin" 18 | OPERATOR_SDK_BIN_PATH=${OPERATOR_SDK_BIN_PATH:-$DEFAULT_OPERATOR_SDK_BIN_PATH} 19 | DEFAULT_OPERATOR_SDK_VERSION="1.28.0" 20 | 21 | source "${SCRIPTS_DIR}/lib/common.sh" 22 | 23 | __operator_sdk_version="${1}" 24 | if [ "${__operator_sdk_version}" == "" ]; then 25 | __operator_sdk_version=${OPERATOR_SDK_VERSION:-$DEFAULT_OPERATOR_SDK_VERSION} 26 | fi 27 | if ! is_installed "${OPERATOR_SDK_BIN_PATH}/operator-sdk"; then 28 | __platform=$(uname | tr '[:upper:]' '[:lower:]') 29 | __arch=$(go env GOARCH | tr '[:upper:]' '[:lower:]') 30 | __tmp_install_dir=$(mktemp -d -t install-operator-sdk-XXX) 31 | __operator_sdk_url="https://github.com/operator-framework/operator-sdk/releases/download/v${__operator_sdk_version}/operator-sdk_${__platform}_${__arch}" 32 | 33 | __install_dir=${OPERATOR_SDK_BIN_PATH} 34 | # If __install_dir does not exist, create it 35 | [[ -d $__install_dir ]] || mkdir -p "$__install_dir" 36 | __install_path="$__install_dir/operator-sdk" 37 | 38 | echo -n "installing operator-sdk from ${__operator_sdk_url} ... " 39 | curl -sq -L "${__operator_sdk_url}" --output "${__tmp_install_dir}/operator-sdk_${__platform}_${__arch}" 40 | chmod +x "${__tmp_install_dir}/operator-sdk_${__platform}_${__arch}" 41 | sudo mv "${__tmp_install_dir}/operator-sdk_${__platform}_${__arch}" "$__install_path" 42 | echo "ok." 43 | fi 44 | -------------------------------------------------------------------------------- /scripts/lib/aws.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DEFAULT_AWS_CLI_VERSION="2.0.52" 4 | 5 | # daws() executes the AWS Python CLI tool from a Docker container. 6 | # 7 | # Instead of relying on developers having a particular version of the AWS 8 | # Python CLI tool, this method allows a specific version of the CLI tool to be 9 | # executed within a Docker container. 10 | # 11 | # You call the daws function just like you were calling the `aws` CLI tool. 12 | # 13 | # Usage: 14 | # 15 | # daws SERVICE COMMAND [OPTIONS] 16 | # 17 | # Example: 18 | # 19 | # daws ecr describe-repositories --repository-name my-repo 20 | # 21 | # To use a specific version of the AWS CLI, set the ACK_AWS_CLI_IMAGE_VERSION 22 | # environment variable, otherwise the value of DEFAULT_AWS_CLI_VERSION is used. 23 | daws() { 24 | aws_cli_profile_env=() 25 | if [ -n "$AWS_PROFILE" ]; then 26 | aws_cli_profile_env=("--env AWS_PROFILE=$AWS_PROFILE") 27 | fi 28 | aws_cli_img_version=${ACK_AWS_CLI_IMAGE_VERSION:-$DEFAULT_AWS_CLI_VERSION} 29 | aws_cli_img="amazon/aws-cli:$aws_cli_img_version" 30 | docker run --rm -v ~/.aws:/root/.aws:z "${aws_cli_profile_env[@]}" -v "$(pwd)":/aws "$aws_cli_img" "$@" 31 | } 32 | 33 | # aws_check_credentials() calls the STS::GetCallerIdentity API call and 34 | # verifies that there is a local identity for running AWS commands 35 | aws_check_credentials() { 36 | echo -n "checking AWS credentials ... " 37 | daws sts get-caller-identity --query "Account" >/dev/null || 38 | ( printf "\nFATAL: No AWS credentials found. Please run \`aws configure\` to set up the CLI for your credentials." && exit 1) 39 | echo "ok." 40 | } 41 | 42 | aws_account_id() { 43 | JSON=$(daws sts get-caller-identity --output json || exit 1) 44 | echo "${JSON}" | jq --raw-output ".Account" 45 | } 46 | -------------------------------------------------------------------------------- /scripts/olm-publish-bundle-image.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" 6 | SCRIPTS_DIR=$DIR 7 | DEFAULT_DOCKER_REPOSITORY="amazon/aws-controllers-k8s" 8 | DOCKER_REPOSITORY=${DOCKER_REPOSITORY:-$DEFAULT_DOCKER_REPOSITORY} 9 | 10 | source "$SCRIPTS_DIR/lib/common.sh" 11 | 12 | check_is_installed docker 13 | 14 | USAGE=" 15 | Usage: 16 | $(basename "$0") 17 | 18 | Publishes the Docker image for an ACK service OLM bundle. By default, the 19 | repository will be $DEFAULT_DOCKER_REPOSITORY and the image tag for the 20 | specific ACK service controller will be \":\$SERVICE-bundle-\$VERSION\". 21 | 22 | AWS Service name (ecr, sns, sqs) 23 | OLM bundle version in SemVer (0.0.1, 1.0.0) 24 | 25 | Example: 26 | export DOCKER_REPOSITORY=aws-controllers-k8s 27 | $(basename "$0") ecr 0.0.1 28 | 29 | Environment variables: 30 | DOCKER_REPOSITORY: Name for the Docker repository to push to 31 | Default: $DEFAULT_DOCKER_REPOSITORY 32 | BUNDLE_DOCKER_IMG_TAG: Bundle container image tag 33 | Default: \$AWS_SERVICE-bundle-\$BUNDLE_VERSION 34 | BUNDLE_DOCKER_IMG: The bundle container image (including the tag). 35 | Supersedes the use of BUNDLE_DOCKER_IMAGE_TAG 36 | and DOCKER_REPOSITORY if set. 37 | Default: $DEFAULT_DOCKER_REPOSITORY:\$AWS_SERVICE-bundle-\$BUNDLE_VERSION 38 | " 39 | 40 | if [ $# -ne 2 ]; then 41 | echo "AWS_SERVICE or BUNDLE_VERSION is not defined. Script accepts two parameters, the and the to build." 1>&2 42 | echo "${USAGE}" 43 | exit 1 44 | fi 45 | 46 | AWS_SERVICE=$(echo "$1" | tr '[:upper:]' '[:lower:]') 47 | BUNDLE_VERSION="$2" 48 | 49 | DEFAULT_BUNDLE_DOCKER_IMG_TAG="$AWS_SERVICE-bundle-$BUNDLE_VERSION" 50 | BUNDLE_DOCKER_IMG_TAG=${BUNDLE_DOCKER_IMG_TAG:-$DEFAULT_BUNDLE_DOCKER_IMG_TAG} 51 | BUNDLE_DOCKER_IMG=${BUNDLE_DOCKER_IMAGE:-$DOCKER_REPOSITORY:$BUNDLE_DOCKER_IMG_TAG} 52 | 53 | export BUNDLE_DOCKER_IMG 54 | "${SCRIPTS_DIR}"/olm-build-bundle-image.sh "${AWS_SERVICE}" "${BUNDLE_VERSION}" 55 | 56 | echo "Pushing '$AWS_SERVICE' operator lifecycle manager bundle image with tag: ${BUNDLE_DOCKER_IMG_TAG}" 57 | 58 | if ! docker push "${BUNDLE_DOCKER_IMG}"; then 59 | exit 2 60 | fi 61 | -------------------------------------------------------------------------------- /templates/apis/doc.go.tpl: -------------------------------------------------------------------------------- 1 | // +k8s:deepcopy-gen=package 2 | // Package {{ .APIVersion }} is the {{ .APIVersion }} version of the {{ .APIGroup }} API. 3 | // +groupName={{ .APIGroup }} 4 | package {{ .APIVersion }} 5 | -------------------------------------------------------------------------------- /templates/apis/enum_def.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "enum_def" -}} 2 | type {{ .Names.Camel }} string 3 | 4 | const ( 5 | {{- range $val := .Values }} 6 | {{ $.Names.Camel }}_{{ $val.Clean }} {{ $.Names.Camel }} = "{{ $val.Original }}" 7 | {{- end }} 8 | ) 9 | {{- end -}} 10 | -------------------------------------------------------------------------------- /templates/apis/enums.go.tpl: -------------------------------------------------------------------------------- 1 | {{- template "boilerplate" }} 2 | 3 | package {{ .APIVersion }} 4 | {{- range $enumDef := .EnumDefs }} 5 | 6 | {{ template "enum_def" $enumDef }} 7 | {{- end -}} 8 | -------------------------------------------------------------------------------- /templates/apis/groupversion_info.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package {{ .APIVersion }} 4 | 5 | import ( 6 | "k8s.io/apimachinery/pkg/runtime/schema" 7 | "sigs.k8s.io/controller-runtime/pkg/scheme" 8 | ) 9 | 10 | var ( 11 | // GroupVersion is the API Group Version used to register the objects 12 | GroupVersion = schema.GroupVersion{Group: "{{ .APIGroup }}", Version: "{{ .APIVersion }}"} 13 | 14 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 15 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 16 | 17 | // AddToScheme adds the types in this group-version to the given scheme. 18 | AddToScheme = SchemeBuilder.AddToScheme 19 | ) 20 | -------------------------------------------------------------------------------- /templates/apis/type_def.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "type_def" -}} 2 | {{- if .Shape.Documentation }} 3 | {{ .Shape.Documentation }} 4 | {{- end }} 5 | type {{ .Names.Camel }} struct { 6 | {{- range $attrName, $attr := .Attrs }} 7 | {{- if $attr.Shape.Documentation }} 8 | {{ $attr.Shape.Documentation }} 9 | {{- end }} 10 | {{ $attr.Names.Camel }} {{ $attr.GoType }} {{ $attr.GetGoTag }} 11 | {{- end }} 12 | } 13 | {{- end -}} 14 | -------------------------------------------------------------------------------- /templates/apis/types.go.tpl: -------------------------------------------------------------------------------- 1 | {{- template "boilerplate" }} 2 | 3 | package {{ .APIVersion }} 4 | 5 | import ( 6 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 7 | "github.com/aws/aws-sdk-go/aws" 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | // Hack to avoid import errors during build... 12 | var ( 13 | _ = &metav1.Time{} 14 | _ = &aws.JSONValue{} 15 | _ = ackv1alpha1.AWSAccountID("") 16 | ) 17 | {{- range $typeDef := .TypeDefs }} 18 | 19 | {{ template "type_def" $typeDef }} 20 | {{- end -}} 21 | -------------------------------------------------------------------------------- /templates/boilerplate.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "boilerplate" -}} 2 | // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"). You may 5 | // not use this file except in compliance with the License. A copy of the 6 | // License is located at 7 | // 8 | // http://aws.amazon.com/apache2.0/ 9 | // 10 | // or in the "license" file accompanying this file. This file is distributed 11 | // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | // express or implied. See the License for the specific language governing 13 | // permissions and limitations under the License. 14 | 15 | // Code generated by ack-generate. DO NOT EDIT. 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /templates/boilerplate.txt: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /templates/boilerplate_hash.go.tpl: -------------------------------------------------------------------------------- 1 | {{ define "boilerplate_hash" }} 2 | # Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"). You may 5 | # not use this file except in compliance with the License. A copy of the 6 | # License is located at 7 | # 8 | # http://aws.amazon.com/apache2.0/ 9 | # 10 | # or in the "license" file accompanying this file. This file is distributed 11 | # on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 | # express or implied. See the License for the specific language governing 13 | # permissions and limitations under the License. 14 | {{- end -}} 15 | -------------------------------------------------------------------------------- /templates/config/controller/kustomization.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{ template "controller_kustomization" . }} -------------------------------------------------------------------------------- /templates/config/controller/kustomization_def.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{- define "controller_kustomization" -}} 2 | resources: 3 | - deployment.yaml 4 | - service.yaml 5 | apiVersion: kustomize.config.k8s.io/v1beta1 6 | kind: Kustomization 7 | images: 8 | - name: controller 9 | newName: {{ .ImageRepository }} 10 | newTag: {{ .ReleaseVersion }} 11 | {{end}} -------------------------------------------------------------------------------- /templates/config/controller/olm-kustomization.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{ template "controller_kustomization" . }} 2 | 3 | patches: 4 | - patch: |- 5 | - op: replace 6 | path: '/spec/template/spec/containers/0/env' 7 | value: [] 8 | - op: add 9 | path: '/spec/template/spec/containers/0/env/0' 10 | value: 11 | name: ACK_SYSTEM_NAMESPACE 12 | valueFrom: 13 | fieldRef: 14 | fieldPath: metadata.namespace 15 | target: 16 | group: apps 17 | kind: Deployment 18 | name: ack-{{ .ControllerName }}-controller 19 | version: v1 20 | - path: user-env.yaml 21 | -------------------------------------------------------------------------------- /templates/config/controller/service.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: ack-{{ .ControllerName }}-metrics-service 5 | namespace: ack-system 6 | spec: 7 | selector: 8 | app.kubernetes.io/name: ack-{{ .ControllerName }}-controller 9 | ports: 10 | - name: metricsport 11 | port: 8080 12 | targetPort: http 13 | protocol: TCP 14 | type: NodePort 15 | -------------------------------------------------------------------------------- /templates/config/controller/user-env.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: ack-{{.ControllerName}}-controller 5 | namespace: {{.Annotations.SuggestedNamespace}} 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: controller 11 | envFrom: 12 | - configMapRef: 13 | name: ack-{{.ControllerName}}-user-config 14 | optional: false 15 | - secretRef: 16 | name: ack-{{.ControllerName}}-user-secrets 17 | optional: true 18 | -------------------------------------------------------------------------------- /templates/config/crd/kustomization.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - common 5 | {{- range .CRDNames }} 6 | - bases/{{ $.APIGroup }}_{{ . }}.yaml 7 | {{- end }} 8 | -------------------------------------------------------------------------------- /templates/config/default/kustomization.yaml.tpl: -------------------------------------------------------------------------------- 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/config/manifests/bases/clusterserviceversion.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | categories: "Cloud Provider" 6 | alm-examples: '[]' 7 | capabilities: {{.Annotations.CapabilityLevel}} 8 | operatorframework.io/suggested-namespace: "ack-system" 9 | repository: {{.Annotations.Repository}} 10 | containerImage: {{ .ImageRepository }}:{{ .ReleaseVersion }} 11 | description: {{.Annotations.ShortDescription}} 12 | createdAt: {{.CreatedAt}} 13 | support: {{.Annotations.Support}} 14 | certified: {{.Annotations.IsCertified}} 15 | labels: 16 | operatorframework.io/os.linux: supported 17 | operatorframework.io/arch.amd64: supported 18 | operatorframework.io/arch.arm64: supported 19 | name: ack-{{.ControllerName }}-controller.v0.0.0 20 | namespace: placeholder 21 | spec: 22 | apiservicedefinitions: {} 23 | customresourcedefinitions: 24 | owned: 25 | {{- range .CRDs}} 26 | - kind: {{ .Kind}} 27 | name: {{ ToLower .Plural }}.{{$.APIGroup}} 28 | version: {{$.APIVersion}} 29 | displayName: {{.Kind}} 30 | description: {{.Kind}} represents the state of an AWS {{$.ControllerName}} {{.Kind}} resource. 31 | {{- end}} 32 | description: '{{ .Description }}' 33 | displayName: {{ .DisplayName}} 34 | icon: 35 | {{- range .Icon}} 36 | - base64data: {{ .Data }} 37 | mediatype: {{ .MediaType }} 38 | {{- end}} 39 | install: 40 | spec: 41 | deployments: null 42 | strategy: "" 43 | installModes: 44 | {{- range .InstallModes}} 45 | - supported: {{ .Supported }} 46 | type: {{ .Type }} 47 | {{- end}} 48 | keywords: 49 | - {{.ControllerName}} 50 | {{- range .Common.Keywords}} 51 | - {{ . }} 52 | {{- end}} 53 | {{- range .Keywords}} 54 | - {{ . }} 55 | {{- end}} 56 | links: 57 | {{- range .Common.Links}} 58 | - name: {{ .Name }} 59 | url: {{ .URL }} 60 | {{- end}} 61 | {{- range .Links}} 62 | - name: {{ .Name }} 63 | url: {{ .URL }} 64 | {{- end}} 65 | maintainers: 66 | {{- range .Maintainers}} 67 | - email: {{ .Email }} 68 | name: {{ .Name}} 69 | {{- end}} 70 | maturity: {{.Maturity}} 71 | provider: 72 | name: {{ .Provider.Name }} 73 | url: {{ .Provider.URL }} 74 | version: 0.0.0 -------------------------------------------------------------------------------- /templates/config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | - ../samples 4 | - ../scorecard -------------------------------------------------------------------------------- /templates/config/overlays/namespaced/kustomization.yaml.tpl: -------------------------------------------------------------------------------- 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-{{ .ControllerName }}-controller 10 | - path: role-binding.json 11 | target: 12 | group: rbac.authorization.k8s.io 13 | version: v1 14 | kind: ClusterRoleBinding 15 | name: ack-{{ .ControllerName }}-controller-rolebinding -------------------------------------------------------------------------------- /templates/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"}] -------------------------------------------------------------------------------- /templates/config/overlays/namespaced/role.json: -------------------------------------------------------------------------------- 1 | [{"op": "replace", "path": "/kind", "value": "Role"}, 2 | {"op": "add", "path": "/metadata/namespace", "value": "ack-system"}] -------------------------------------------------------------------------------- /templates/config/rbac/cluster-role-binding.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: ack-{{ .ControllerName }}-controller-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: ack-{{ .ControllerName }}-controller 9 | subjects: 10 | - kind: ServiceAccount 11 | name: {{ .ServiceAccountName }} 12 | namespace: ack-system 13 | -------------------------------------------------------------------------------- /templates/config/rbac/kustomization.yaml.tpl: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /templates/config/rbac/leader-election-role-binding.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | namespace: ack-system 6 | name: {{.ControllerName}}-leader-election-rolebinding 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: Role 10 | name: {{.ControllerName}}-leader-election-role 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{.ServiceAccountName}} 14 | namespace: ack-system 15 | -------------------------------------------------------------------------------- /templates/config/rbac/leader-election-role.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: {{.ControllerName}}-leader-election-role 6 | namespace: ack-system 7 | rules: 8 | - apiGroups: 9 | - coordination.k8s.io 10 | resources: 11 | - leases 12 | verbs: 13 | - get 14 | - list 15 | - watch 16 | - create 17 | - update 18 | - patch 19 | - delete 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - events 24 | verbs: 25 | - create 26 | - patch 27 | -------------------------------------------------------------------------------- /templates/config/rbac/role-reader.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-{{ .ControllerName }}-reader 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - {{ .APIGroup }} 11 | resources: 12 | {{- range $crdName := .CRDNames }} 13 | - {{ $crdName }} 14 | {{- end }} 15 | verbs: 16 | - get 17 | - list 18 | - watch 19 | -------------------------------------------------------------------------------- /templates/config/rbac/role-writer.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-{{ .ControllerName }}-writer 7 | namespace: default 8 | rules: 9 | - apiGroups: 10 | - {{ .APIGroup }} 11 | resources: 12 | {{- range $crdName := .CRDNames }} 13 | - {{ $crdName }} 14 | {{- end }} 15 | verbs: 16 | - create 17 | - delete 18 | - get 19 | - list 20 | - patch 21 | - update 22 | - watch 23 | - apiGroups: 24 | - {{ .APIGroup }} 25 | resources: 26 | {{- range $crdName := .CRDNames }} 27 | - {{ $crdName }} 28 | {{- end }} 29 | verbs: 30 | - get 31 | - patch 32 | - update 33 | -------------------------------------------------------------------------------- /templates/config/rbac/service-account.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ .ServiceAccountName }} 6 | namespace: ack-system 7 | -------------------------------------------------------------------------------- /templates/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - sample.yaml -------------------------------------------------------------------------------- /templates/config/samples/sample.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{- range .Samples -}} 2 | --- 3 | apiVersion: {{$.APIGroup}}/{{$.APIVersion}} 4 | kind: {{.Kind}} 5 | metadata: 6 | name: example 7 | spec: 8 | {{.Spec}} 9 | {{ end }} -------------------------------------------------------------------------------- /templates/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /templates/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | patches: 6 | - path: patches/basic.config.yaml 7 | target: 8 | group: scorecard.operatorframework.io 9 | kind: Configuration 10 | name: config 11 | version: v1alpha3 12 | - path: patches/olm.config.yaml 13 | target: 14 | group: scorecard.operatorframework.io 15 | kind: Configuration 16 | name: config 17 | version: v1alpha3 18 | -------------------------------------------------------------------------------- /templates/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.7.1 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /templates/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.7.1 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.7.1 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | ## This test is disabled as the current state of the ACK 22 | ## is such that the controllers themselves don't manage 23 | ## other resources (e.g. pods, deployments) in the cluster 24 | ## where they are deployed. 25 | ## This test is not currently a requirement for certification. 26 | # - op: add 27 | # path: /stages/0/tests/- 28 | # value: 29 | # entrypoint: 30 | # - scorecard-test 31 | # - olm-crds-have-resources 32 | # image: quay.io/operator-framework/scorecard-test:v1.7.1 33 | # labels: 34 | # suite: olm 35 | # test: olm-crds-have-resources-test 36 | - op: add 37 | path: /stages/0/tests/- 38 | value: 39 | entrypoint: 40 | - scorecard-test 41 | - olm-spec-descriptors 42 | image: quay.io/operator-framework/scorecard-test:v1.7.1 43 | labels: 44 | suite: olm 45 | test: olm-spec-descriptors-test 46 | ## This test is disabled as the status descriptor annotations are 47 | ## derived from API markers on the *Status type definitions, or scaffolded 48 | ## by the olm generator which cannot currently be done with the 49 | ## input data provided to the olm generator. 50 | ## This test is not currently a requirement for certification. 51 | # - op: add 52 | # path: /stages/0/tests/- 53 | # value: 54 | # entrypoint: 55 | # - scorecard-test 56 | # - olm-status-descriptors 57 | # image: quay.io/operator-framework/scorecard-test:v1.7.1 58 | # labels: 59 | # suite: olm 60 | # test: olm-status-descriptors-test 61 | -------------------------------------------------------------------------------- /templates/crossplane/README.md: -------------------------------------------------------------------------------- 1 | # Crossplane Provider Generation 2 | 3 | This folder includes the templates to generate AWS Crossplane Provider. Run the 4 | following to generate: 5 | 6 | ```console 7 | go run -tags codegen cmd/ack-generate/main.go crossplane \ 8 | --output 9 | ``` 10 | 11 | See [Contributing New Resource Using ACK](https://github.com/crossplane-contrib/provider-aws/blob/master/CODE_GENERATION.md) 12 | for details. 13 | -------------------------------------------------------------------------------- /templates/crossplane/apis/doc.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | // Code generated by ack-generate. DO NOT EDIT. 4 | 5 | // +kubebuilder:object:generate=true 6 | // Package {{ .APIVersion }} is the {{ .APIVersion }} version of the {{ .APIGroup }} API. 7 | // +groupName={{ .APIGroup }} 8 | // +versionName={{ .APIVersion }} 9 | 10 | package {{ .APIVersion }} 11 | -------------------------------------------------------------------------------- /templates/crossplane/apis/enum_def.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "enum_def" -}} 2 | type {{ .Names.Camel }} string 3 | 4 | const ( 5 | {{- range $val := .Values }} 6 | {{ $.Names.Camel }}_{{ $val.Clean }} {{ $.Names.Camel }} = "{{ $val.Original }}" 7 | {{- end }} 8 | ) 9 | {{- end -}} 10 | -------------------------------------------------------------------------------- /templates/crossplane/apis/enums.go.tpl: -------------------------------------------------------------------------------- 1 | {{- template "boilerplate" }} 2 | 3 | // Code generated by ack-generate. DO NOT EDIT. 4 | 5 | package {{ .APIVersion }} 6 | {{- range $enumDef := .EnumDefs }} 7 | 8 | {{ template "enum_def" $enumDef }} 9 | {{- end -}} 10 | -------------------------------------------------------------------------------- /templates/crossplane/apis/groupversion_info.go.tpl: -------------------------------------------------------------------------------- 1 | {{- template "boilerplate" }} 2 | 3 | // Code generated by ack-generate. DO NOT EDIT. 4 | 5 | package {{ .APIVersion }} 6 | 7 | import ( 8 | "k8s.io/apimachinery/pkg/runtime/schema" 9 | "sigs.k8s.io/controller-runtime/pkg/scheme" 10 | ) 11 | 12 | // Package type metadata. 13 | const ( 14 | CRDGroup = "{{ .APIGroup }}" 15 | CRDVersion = "{{ .APIVersion }}" 16 | ) 17 | 18 | var ( 19 | // GroupVersion is the API Group Version used to register the objects 20 | GroupVersion = schema.GroupVersion{Group: CRDGroup, Version: CRDVersion} 21 | 22 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 23 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 24 | 25 | // AddToScheme adds the types in this group-version to the given scheme. 26 | AddToScheme = SchemeBuilder.AddToScheme 27 | ) 28 | -------------------------------------------------------------------------------- /templates/crossplane/apis/type_def.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "type_def" -}} 2 | // +kubebuilder:skipversion 3 | type {{ .Names.Camel }} struct { 4 | {{- range $attrName, $attr := .Attrs }} 5 | {{- if $attr.Shape }} 6 | {{ $attr.Shape.Documentation }} 7 | {{- end }} 8 | {{ $attr.Names.Camel }} {{ $attr.GoType }} `json:"{{ $attr.Names.CamelLower }},omitempty"` 9 | {{- end }} 10 | } 11 | {{- end -}} 12 | -------------------------------------------------------------------------------- /templates/crossplane/apis/types.go.tpl: -------------------------------------------------------------------------------- 1 | {{- template "boilerplate" }} 2 | 3 | // Code generated by ack-generate. DO NOT EDIT. 4 | 5 | package {{ .APIVersion }} 6 | 7 | import ( 8 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 9 | ) 10 | 11 | // Hack to avoid import errors during build... 12 | var ( 13 | _ = &metav1.Time{} 14 | ) 15 | 16 | {{ range $typeDef := .TypeDefs }} 17 | 18 | {{ template "type_def" $typeDef }} 19 | {{- end -}} 20 | -------------------------------------------------------------------------------- /templates/crossplane/boilerplate.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "boilerplate" -}} 2 | /* 3 | Copyright 2021 The Crossplane Authors. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | {{- end -}} 18 | -------------------------------------------------------------------------------- /templates/crossplane/pkg/conversions.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | // Code generated by ack-generate. DO NOT EDIT. 4 | 5 | package {{ .CRD.Names.Lower }} 6 | 7 | import ( 8 | {{- if .CRD.TypeImports }} 9 | {{- range $packagePath, $alias := .CRD.TypeImports }} 10 | {{ if $alias }}{{ $alias }} {{ end }}"{{ $packagePath }}" 11 | {{ end }} 12 | {{- end }} 13 | "github.com/aws/aws-sdk-go/aws/awserr" 14 | svcsdk "github.com/aws/aws-sdk-go/service/{{ .ServicePackageName }}" 15 | 16 | svcapitypes "github.com/crossplane-contrib/provider-aws/apis/{{ .ServicePackageName }}/{{ .APIVersion}}" 17 | ) 18 | 19 | // NOTE(muvaf): We return pointers in case the function needs to start with an 20 | // empty object, hence need to return a new pointer. 21 | 22 | {{ if .CRD.Ops.ReadOne }} 23 | {{- template "sdk_find_read_one" . }} 24 | {{- else if .CRD.Ops.GetAttributes }} 25 | {{- template "sdk_find_get_attributes" . }} 26 | {{- else if .CRD.Ops.ReadMany }} 27 | {{- template "sdk_find_read_many" . }} 28 | {{- end }} 29 | 30 | // Generate{{ .CRD.Ops.Create.InputRef.Shape.ShapeName }} returns a create input. 31 | func Generate{{ .CRD.Ops.Create.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.Create.InputRef.Shape.ShapeName }} { 32 | res := &svcsdk.{{ .CRD.Ops.Create.InputRef.Shape.ShapeName }}{} 33 | {{ GoCodeSetCreateInput .CRD "cr" "res" 1 }} 34 | return res 35 | } 36 | {{ if .CRD.Ops.Update -}} 37 | // Generate{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }} returns an update input. 38 | func Generate{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }} { 39 | res := &svcsdk.{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }}{} 40 | {{ GoCodeSetUpdateInput .CRD "cr" "res" 1 }} 41 | return res 42 | } 43 | {{- end}} 44 | 45 | {{ if .CRD.Ops.Delete -}} 46 | // Generate{{ .CRD.Ops.Delete.InputRef.Shape.ShapeName }} returns a deletion input. 47 | func Generate{{ .CRD.Ops.Delete.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.Delete.InputRef.Shape.ShapeName }} { 48 | res := &svcsdk.{{ .CRD.Ops.Delete.InputRef.Shape.ShapeName }}{} 49 | {{ GoCodeSetDeleteInput .CRD "cr" "res" 1 }} 50 | return res 51 | } 52 | {{ end }} 53 | // IsNotFound returns whether the given error is of type NotFound or not. 54 | func IsNotFound(err error) bool { 55 | awsErr, ok := err.(awserr.Error) 56 | return ok && awsErr.Code() == "{{ ResourceExceptionCode .CRD 404 }}" {{ GoCodeSetExceptionMessageCheck .CRD 404 }} 57 | } -------------------------------------------------------------------------------- /templates/crossplane/pkg/sdk_find_get_attributes.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_get_attributes" -}} 2 | // Generate{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }} returns input for read 3 | // operation. 4 | func Generate{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }} { 5 | res := &svcsdk.{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }}{} 6 | {{ GoCodeGetAttributesSetInput .CRD "cr" "res" 1 }} 7 | return res 8 | } 9 | 10 | // Generate{{ .CRD.Names.Camel }} returns the current state in the form of *svcapitypes.{{ .CRD.Names.Camel }}. 11 | func Generate{{ .CRD.Names.Camel }}(resp *svcsdk.{{ .CRD.Ops.GetAttributes.OutputRef.Shape.ShapeName }}) *svcapitypes.{{ .CRD.Names.Camel }} { 12 | cr := &svcapitypes.{{ .CRD.Names.Camel }}{} 13 | {{ GoCodeGetAttributesSetOutput .CRD "resp" "cr" 1 }} 14 | return cr 15 | } 16 | {{- end -}} -------------------------------------------------------------------------------- /templates/crossplane/pkg/sdk_find_read_many.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_read_many" -}} 2 | // Generate{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }} returns input for read 3 | // operation. 4 | func Generate{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }} { 5 | res := &svcsdk.{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }}{} 6 | {{ GoCodeSetReadManyInput .CRD "cr" "res" 1 }} 7 | return res 8 | } 9 | 10 | // Generate{{ .CRD.Names.Camel }} returns the current state in the form of *svcapitypes.{{ .CRD.Names.Camel }}. 11 | func Generate{{ .CRD.Names.Camel }}(resp *svcsdk.{{ .CRD.Ops.ReadMany.OutputRef.Shape.ShapeName }}) *svcapitypes.{{ .CRD.Names.Camel }} { 12 | cr := &svcapitypes.{{ .CRD.Names.Camel }}{} 13 | {{ GoCodeSetReadManyOutput .CRD "resp" "cr" 1 }} 14 | return cr 15 | } 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /templates/crossplane/pkg/sdk_find_read_one.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_read_one" -}} 2 | // Generate{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }} returns input for read 3 | // operation. 4 | func Generate{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }}(cr *svcapitypes.{{ .CRD.Names.Camel }}) *svcsdk.{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }} { 5 | res := &svcsdk.{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }}{} 6 | {{ GoCodeSetReadOneInput .CRD "cr" "res" 1 }} 7 | return res 8 | } 9 | 10 | // Generate{{ .CRD.Names.Camel }} returns the current state in the form of *svcapitypes.{{ .CRD.Names.Camel }}. 11 | func Generate{{ .CRD.Names.Camel }}(resp *svcsdk.{{ .CRD.Ops.ReadOne.OutputRef.Shape.ShapeName }}) *svcapitypes.{{ .CRD.Names.Camel }} { 12 | cr := &svcapitypes.{{ .CRD.Names.Camel }}{} 13 | {{ GoCodeSetReadOneOutput .CRD "resp" "cr" 1 }} 14 | return cr 15 | } 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /templates/helm/Chart.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | name: {{ .ControllerName }}-chart 3 | description: A Helm chart for the ACK service controller for {{ .Metadata.Service.FullName }} ({{ .Metadata.Service.ShortName }}) 4 | version: {{ .ReleaseVersion }} 5 | appVersion: {{ .ReleaseVersion }} 6 | home: https://github.com/aws-controllers-k8s/{{ .ControllerName }}-controller 7 | icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png 8 | sources: 9 | - https://github.com/aws-controllers-k8s/{{ .ControllerName }}-controller 10 | maintainers: 11 | - name: ACK Admins 12 | url: https://github.com/orgs/aws-controllers-k8s/teams/ack-admin 13 | - name: {{ .Metadata.Service.ShortName }} Admins 14 | url: https://github.com/orgs/aws-controllers-k8s/teams/{{ .ControllerName }}-maintainer 15 | keywords: 16 | - aws 17 | - kubernetes 18 | - {{ .ControllerName }} 19 | -------------------------------------------------------------------------------- /templates/helm/templates/NOTES.txt.tpl: -------------------------------------------------------------------------------- 1 | {{ "{{ .Chart.Name }}" }} has been installed. 2 | This chart deploys "{{ .ImageRepository }}:{{ .ReleaseVersion }}". 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 {{ .Metadata.Service.FullName }} ({{ .Metadata.Service.ShortName }}) resources! 8 | 9 | The controller is running in "{{ "{{ .Values.installScope }}" }}" mode. 10 | The controller is configured to manage AWS resources in region: "{{ "{{ .Values.aws.region }}" }}" 11 | 12 | Visit https://aws-controllers-k8s.github.io/community/reference/ for an API 13 | reference of all the resources that can be created using this controller. 14 | 15 | For more information on the AWS Controllers for Kubernetes (ACK) project, visit: 16 | https://aws-controllers-k8s.github.io/community/ 17 | -------------------------------------------------------------------------------- /templates/helm/templates/_helpers.tpl.tpl: -------------------------------------------------------------------------------- 1 | {{ "{{/* The name of the application this chart installs */}}" }} 2 | {{ DefineTemplate "app.name" }} 3 | {{ "{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix \"-\" -}}" }} 4 | {{ "{{- end -}}" }} 5 | 6 | {{ "{{/*" }} 7 | {{ "Create a default fully qualified app name." }} 8 | {{ "We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec)." }} 9 | {{ "If release name contains chart name it will be used as a full name." }} 10 | {{ "*/}}" }} 11 | {{ DefineTemplate "app.fullname" }} 12 | {{ "{{- if .Values.fullnameOverride -}}" }} 13 | {{ "{{- .Values.fullnameOverride | trunc 63 | trimSuffix \"-\" -}}" }} 14 | {{ "{{- else -}}" }} 15 | {{ "{{- $name := default .Chart.Name .Values.nameOverride -}}" }} 16 | {{ "{{- if contains $name .Release.Name -}}" }} 17 | {{ "{{- .Release.Name | trunc 63 | trimSuffix \"-\" -}}" }} 18 | {{ "{{- else -}}" }} 19 | {{ "{{- printf \"%s-%s\" .Release.Name $name | trunc 63 | trimSuffix \"-\" -}}" }} 20 | {{ "{{- end -}}" }} 21 | {{ "{{- end -}}" }} 22 | {{ "{{- end -}}" }} 23 | 24 | {{ "{{/* The name and version as used by the chart label */}}" }} 25 | {{ DefineTemplate "chart.name-version" }} 26 | {{ "{{- printf \"%s-%s\" .Chart.Name .Chart.Version | replace \"+\" \"_\" | trunc 63 | trimSuffix \"-\" -}}" }} 27 | {{ "{{- end -}}" }} 28 | 29 | {{ "{{/* The name of the service account to use */}}" }} 30 | {{ DefineTemplate "service-account.name" }} 31 | {{ "{{ default \"default\" .Values.serviceAccount.name }}" }} 32 | {{ "{{- end -}}" }} 33 | 34 | {{ DefineTemplate "watch-namespace" }} 35 | {{ "{{- if eq .Values.installScope \"namespace\" -}}" }} 36 | {{ "{{ .Values.watchNamespace | default .Release.Namespace }}" }} 37 | {{ "{{- end -}}" }} 38 | {{ "{{- end -}}" }} 39 | 40 | {{ "{{/* The mount path for the shared credentials file */}}" }} 41 | {{ DefineTemplate "aws.credentials.secret_mount_path" }} 42 | {{ "{{- \"/var/run/secrets/aws\" -}}" }} 43 | {{ "{{- end -}}" }} 44 | 45 | {{ "{{/* The path the shared credentials file is mounted */}}" }} 46 | {{ DefineTemplate "aws.credentials.path" }} 47 | {{ VarIncludeTemplate "secret_mount_path" "aws.credentials.secret_mount_path" }} 48 | {{ "{{- printf \"%s/%s\" $secret_mount_path .Values.aws.credentials.secretKey -}}" }} 49 | {{ "{{- end -}}" }} 50 | 51 | {{ "{{/* The rules a of ClusterRole or Role */}}" }} 52 | {{ DefineTemplate "rbac-rules" }} 53 | SEDREPLACERULES 54 | {{ "{{- end }}" }} 55 | 56 | {{ "{{/* Convert k/v map to string like: \"key1=value1,key2=value2,...\" */}}" }} 57 | {{ DefineTemplate "feature-gates" }} 58 | {{ "{{- $list := list -}}" }} 59 | {{ "{{- range $k, $v := .Values.featureGates -}}" }} 60 | {{ "{{- $list = append $list (printf \"%s=%s\" $k ( $v | toString)) -}}" }} 61 | {{ "{{- end -}}" }} 62 | {{ "{{ join \",\" $list }}" }} 63 | {{ "{{- end -}}" }} 64 | -------------------------------------------------------------------------------- /templates/helm/templates/caches-role-binding.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: ack-namespaces-cache-{{ .ControllerName }}-controller 5 | roleRef: 6 | kind: ClusterRole 7 | apiGroup: rbac.authorization.k8s.io 8 | name: ack-namespaces-cache-{{ .ControllerName }}-controller 9 | subjects: 10 | - kind: ServiceAccount 11 | name: {{ IncludeTemplate "service-account.name" }} 12 | namespace: {{ "{{ .Release.Namespace }}" }} 13 | --- 14 | apiVersion: rbac.authorization.k8s.io/v1 15 | kind: RoleBinding 16 | metadata: 17 | name: ack-configmaps-cache-{{ .ControllerName }}-controller 18 | namespace: {{ "{{ .Release.Namespace }}" }} 19 | roleRef: 20 | kind: Role 21 | apiGroup: rbac.authorization.k8s.io 22 | name: ack-configmaps-cache-{{ .ControllerName }}-controller 23 | subjects: 24 | - kind: ServiceAccount 25 | name: {{ IncludeTemplate "service-account.name" }} 26 | namespace: {{ "{{ .Release.Namespace }}" }} 27 | -------------------------------------------------------------------------------- /templates/helm/templates/caches-role.yaml.tpl: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: ack-namespaces-cache-{{ .ControllerName }}-controller 5 | rules: 6 | - apiGroups: 7 | - "" 8 | resources: 9 | - namespaces 10 | verbs: 11 | - get 12 | - list 13 | - watch 14 | --- 15 | apiVersion: rbac.authorization.k8s.io/v1 16 | kind: Role 17 | metadata: 18 | name: ack-configmaps-cache-{{ .ControllerName }}-controller 19 | namespace: {{ "{{ .Release.Namespace }}" }} 20 | rules: 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - configmaps 25 | verbs: 26 | - get 27 | - list 28 | - watch -------------------------------------------------------------------------------- /templates/helm/templates/cluster-role-binding.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{ "{{ if eq .Values.installScope \"cluster\" }}" }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: {{ IncludeTemplate "app.fullname" }} 6 | roleRef: 7 | kind: ClusterRole 8 | apiGroup: rbac.authorization.k8s.io 9 | name: ack-{{ .ControllerName }}-controller 10 | subjects: 11 | - kind: ServiceAccount 12 | name: {{ IncludeTemplate "service-account.name" }} 13 | namespace: {{ "{{ .Release.Namespace }}" }} 14 | {{ "{{ else if eq .Values.installScope \"namespace\" }}" }} 15 | {{ VarIncludeTemplate "wn" "watch-namespace" }} 16 | {{ "{{ $namespaces := split \",\" $wn }}" }} 17 | {{ VarIncludeTemplate "fullname" "app.fullname" }} 18 | {{ "{{ $releaseNamespace := .Release.Namespace }}" }} 19 | {{ VarIncludeTemplate "serviceAccountName" "service-account.name" }} 20 | {{ "{{ range $namespaces }}" }} 21 | --- 22 | apiVersion: rbac.authorization.k8s.io/v1 23 | kind: RoleBinding 24 | metadata: 25 | name: {{ "{{ $fullname }}" }} 26 | namespace: {{ "{{ . }}" }} 27 | roleRef: 28 | kind: Role 29 | apiGroup: rbac.authorization.k8s.io 30 | name: ack-{{ .ControllerName }}-controller 31 | subjects: 32 | - kind: ServiceAccount 33 | name: {{ "{{ $serviceAccountName }}" }} 34 | namespace: {{ "{{ $releaseNamespace }}" }} 35 | {{ "{{ end }}" }} 36 | {{ "{{ end }}" }} -------------------------------------------------------------------------------- /templates/helm/templates/cluster-role-controller.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{ "{{ $labels := .Values.role.labels }}" }} 2 | {{ VarIncludeTemplate "rbacRules" "rbac-rules" }} 3 | {{ "{{ if eq .Values.installScope \"cluster\" }}" }} 4 | apiVersion: rbac.authorization.k8s.io/v1 5 | kind: ClusterRole 6 | metadata: 7 | name: ack-{{ .ControllerName }}-controller 8 | labels: 9 | {{ "{{- range $key, $value := $labels }}" }} 10 | {{ "{{ $key }}: {{ $value | quote }}" }} 11 | {{ "{{- end }}" }} 12 | {{ "{{$rbacRules }}" }} 13 | {{ "{{ else if eq .Values.installScope \"namespace\" }}" }} 14 | {{ VarIncludeTemplate "wn" "watch-namespace" }} 15 | {{ "{{ $namespaces := split \",\" $wn }}" }} 16 | {{ "{{ range $namespaces }}" }} 17 | --- 18 | apiVersion: rbac.authorization.k8s.io/v1 19 | kind: Role 20 | metadata: 21 | name: ack-{{ .ControllerName }}-controller 22 | namespace: {{ "{{ . }}" }} 23 | labels: 24 | {{ "{{- range $key, $value := $labels }}" }} 25 | {{ "{{ $key }}: {{ $value | quote }}" }} 26 | {{ "{{- end }}" }} 27 | {{ "{{ $rbacRules }}" }} 28 | {{ "{{ end }}" }} 29 | {{ "{{ end }}" }} -------------------------------------------------------------------------------- /templates/helm/templates/leader-election-role-binding.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{- "{{ if .Values.leaderElection.enabled }}" }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: {{.ControllerName}}-leader-election-rolebinding 6 | {{ "{{ if .Values.leaderElection.namespace }}" }} 7 | namespace: {{ "{{ .Values.leaderElection.namespace }}" }} 8 | {{ "{{ else }}" }} 9 | namespace: {{ "{{ .Release.Namespace }}" }} 10 | {{ "{{ end }}" }} 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: Role 14 | name: {{.ControllerName}}-leader-election-role 15 | subjects: 16 | - kind: ServiceAccount 17 | name: {{ IncludeTemplate "service-account.name" }} 18 | namespace: {{ "{{ .Release.Namespace }}" }} 19 | {{- "{{- end }}" }} 20 | -------------------------------------------------------------------------------- /templates/helm/templates/leader-election-role.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{- "{{ if .Values.leaderElection.enabled }}" }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: {{.ControllerName}}-leader-election-role 6 | {{ "{{ if .Values.leaderElection.namespace }}" }} 7 | namespace: {{ "{{ .Values.leaderElection.namespace }}" }} 8 | {{ "{{ else }}" }} 9 | namespace: {{ "{{ .Release.Namespace }}" }} 10 | {{ "{{ end }}" }} 11 | rules: 12 | - apiGroups: 13 | - coordination.k8s.io 14 | resources: 15 | - leases 16 | verbs: 17 | - get 18 | - list 19 | - watch 20 | - create 21 | - update 22 | - patch 23 | - delete 24 | - apiGroups: 25 | - "" 26 | resources: 27 | - events 28 | verbs: 29 | - create 30 | - patch 31 | {{- "{{- end }}" }} 32 | -------------------------------------------------------------------------------- /templates/helm/templates/metrics-service.yaml.tpl: -------------------------------------------------------------------------------- 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: {{ IncludeTemplate "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: {{ IncludeTemplate "app.name" }} 13 | helm.sh/chart: {{ IncludeTemplate "chart.name-version" }} 14 | spec: 15 | selector: 16 | app.kubernetes.io/name: {{ IncludeTemplate "app.name" }} 17 | app.kubernetes.io/instance: {{ "{{ .Release.Name }}" }} 18 | app.kubernetes.io/managed-by: Helm 19 | k8s-app: {{ IncludeTemplate "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/helm/templates/role-reader.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-{{ .ControllerName }}-reader 7 | namespace: {{ "{{ .Release.Namespace }}" }} 8 | rules: 9 | - apiGroups: 10 | - {{ .APIGroup }} 11 | resources: 12 | {{- range $crdName := .CRDNames }} 13 | - {{ $crdName }} 14 | {{- end }} 15 | verbs: 16 | - get 17 | - list 18 | - watch 19 | -------------------------------------------------------------------------------- /templates/helm/templates/role-writer.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | creationTimestamp: null 6 | name: ack-{{ .ControllerName }}-writer 7 | namespace: {{ "{{ .Release.Namespace }}" }} 8 | rules: 9 | - apiGroups: 10 | - {{ .APIGroup }} 11 | resources: 12 | {{- range $crdName := .CRDNames }} 13 | - {{ $crdName }} 14 | {{- end }} 15 | verbs: 16 | - create 17 | - delete 18 | - get 19 | - list 20 | - patch 21 | - update 22 | - watch 23 | - apiGroups: 24 | - {{ .APIGroup }} 25 | resources: 26 | {{- range $crdName := .CRDNames }} 27 | - {{ $crdName }} 28 | {{- end }} 29 | verbs: 30 | - get 31 | - patch 32 | - update 33 | -------------------------------------------------------------------------------- /templates/helm/templates/service-account.yaml.tpl: -------------------------------------------------------------------------------- 1 | {{ "{{- if .Values.serviceAccount.create }}" }} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: {{ IncludeTemplate "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: {{ IncludeTemplate "app.name" }} 11 | helm.sh/chart: {{ IncludeTemplate "chart.name-version" }} 12 | name: {{ IncludeTemplate "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 | -------------------------------------------------------------------------------- /templates/metadata.yaml: -------------------------------------------------------------------------------- 1 | service: 2 | full_name: "" 3 | short_name: "" 4 | link: "" 5 | documentation: "" 6 | api_versions: 7 | - api_version: v1alpha1 8 | status: available -------------------------------------------------------------------------------- /templates/pkg/resource/delta.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package {{ .CRD.Names.Snake }} 4 | 5 | import ( 6 | "bytes" 7 | "reflect" 8 | 9 | ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare" 10 | acktags "github.com/aws-controllers-k8s/runtime/pkg/tags" 11 | ) 12 | 13 | // Hack to avoid import errors during build... 14 | var ( 15 | _ = &bytes.Buffer{} 16 | _ = &reflect.Method{} 17 | _ = &acktags.Tags{} 18 | ) 19 | 20 | // newResourceDelta returns a new `ackcompare.Delta` used to compare two 21 | // resources 22 | func newResourceDelta( 23 | a *resource, 24 | b *resource, 25 | ) *ackcompare.Delta { 26 | delta := ackcompare.NewDelta() 27 | if ((a == nil && b != nil) || 28 | (a != nil && b == nil)) { 29 | delta.Add("", a, b) 30 | return delta 31 | } 32 | 33 | {{- if $hookCode := Hook .CRD "delta_pre_compare" }} 34 | {{ $hookCode }} 35 | {{- end }} 36 | {{ GoCodeCompare .CRD "delta" "a.ko" "b.ko" 1}} 37 | {{- if $hookCode := Hook .CRD "delta_post_compare" }} 38 | {{ $hookCode }} 39 | {{- end }} 40 | return delta 41 | } 42 | -------------------------------------------------------------------------------- /templates/pkg/resource/identifiers.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package {{ .CRD.Names.Snake }} 4 | 5 | import ( 6 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 7 | ) 8 | 9 | // resourceIdentifiers implements the 10 | // `aws-service-operator-k8s/pkg/types.AWSResourceIdentifiers` interface 11 | type resourceIdentifiers struct { 12 | meta *ackv1alpha1.ResourceMetadata 13 | } 14 | 15 | // ARN returns the AWS Resource Name for the backend AWS resource. If nil, 16 | // this means the resource has not yet been created in the backend AWS 17 | // service. 18 | func (ri *resourceIdentifiers) ARN() *ackv1alpha1.AWSResourceName { 19 | if ri.meta != nil { 20 | return ri.meta.ARN 21 | } 22 | return nil 23 | } 24 | 25 | // OwnerAccountID returns the AWS account identifier in which the 26 | // backend AWS resource resides, or nil if this information is not known 27 | // for the resource 28 | func (ri *resourceIdentifiers) OwnerAccountID() *ackv1alpha1.AWSAccountID { 29 | if ri.meta != nil { 30 | return ri.meta.OwnerAccountID 31 | } 32 | return nil 33 | } 34 | 35 | // Region returns the AWS region in which the resource exists, or 36 | // nil if this information is not known. 37 | func (ri *resourceIdentifiers) Region() *ackv1alpha1.AWSRegion { 38 | if ri.meta != nil { 39 | return ri.meta.Region 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /templates/pkg/resource/manager_factory.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package {{ .CRD.Names.Snake }} 4 | 5 | import ( 6 | "fmt" 7 | "sync" 8 | 9 | ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" 10 | ackcfg "github.com/aws-controllers-k8s/runtime/pkg/config" 11 | ackmetrics "github.com/aws-controllers-k8s/runtime/pkg/metrics" 12 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 13 | "github.com/aws/aws-sdk-go-v2/aws" 14 | "github.com/go-logr/logr" 15 | 16 | svcresource "github.com/aws-controllers-k8s/{{ .ControllerName }}-controller/pkg/resource" 17 | ) 18 | 19 | // resourceManagerFactory produces resourceManager objects. It implements the 20 | // `types.AWSResourceManagerFactory` interface. 21 | type resourceManagerFactory struct { 22 | sync.RWMutex 23 | // rmCache contains resource managers for a particular AWS account ID 24 | rmCache map[string]*resourceManager 25 | } 26 | 27 | // ResourcePrototype returns an AWSResource that resource managers produced by 28 | // this factory will handle 29 | func (f *resourceManagerFactory) ResourceDescriptor() acktypes.AWSResourceDescriptor { 30 | return &resourceDescriptor{} 31 | } 32 | 33 | // ManagerFor returns a resource manager object that can manage resources for a 34 | // supplied AWS account 35 | func (f *resourceManagerFactory) ManagerFor( 36 | cfg ackcfg.Config, 37 | clientcfg aws.Config, 38 | log logr.Logger, 39 | metrics *ackmetrics.Metrics, 40 | rr acktypes.Reconciler, 41 | id ackv1alpha1.AWSAccountID, 42 | region ackv1alpha1.AWSRegion, 43 | roleARN ackv1alpha1.AWSResourceName, 44 | ) (acktypes.AWSResourceManager, error) { 45 | // We use the account ID, region, and role ARN to uniquely identify a 46 | // resource manager. This helps us to avoid creating multiple resource 47 | // managers for the same account/region/roleARN combination. 48 | rmId := fmt.Sprintf("%s/%s/%s", id, region, roleARN) 49 | f.RLock() 50 | rm, found := f.rmCache[rmId] 51 | f.RUnlock() 52 | 53 | if found { 54 | return rm, nil 55 | } 56 | 57 | f.Lock() 58 | defer f.Unlock() 59 | 60 | rm, err := newResourceManager(cfg, clientcfg, log, metrics, rr, id, region) 61 | if err != nil { 62 | return nil, err 63 | } 64 | f.rmCache[rmId] = rm 65 | return rm, nil 66 | } 67 | 68 | // IsAdoptable returns true if the resource is able to be adopted 69 | func (f *resourceManagerFactory) IsAdoptable() bool { 70 | return {{ .CRD.IsAdoptable }} 71 | } 72 | 73 | // RequeueOnSuccessSeconds returns true if the resource should be requeued after specified seconds 74 | // Default is false which means resource will not be requeued after success. 75 | func (f *resourceManagerFactory) RequeueOnSuccessSeconds() int { 76 | {{- if $reconcileRequeuOnSuccessSeconds := .CRD.ReconcileRequeuOnSuccessSeconds }} 77 | return {{ $reconcileRequeuOnSuccessSeconds }} 78 | {{- else }} 79 | return 0 80 | {{- end }} 81 | } 82 | 83 | func newResourceManagerFactory() *resourceManagerFactory { 84 | return &resourceManagerFactory{ 85 | rmCache: map[string]*resourceManager{}, 86 | } 87 | } 88 | 89 | func init() { 90 | svcresource.RegisterManagerFactory(newResourceManagerFactory()) 91 | } 92 | -------------------------------------------------------------------------------- /templates/pkg/resource/references_read_referenced_resource.go.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | "read_referenced_resource_and_validate" template should be invoked with a field as 3 | parameter 4 | Ex: {{ template "read_referenced_resource_and_validate" $field }} 5 | Where field is of type 'Field' from aws-controllers-k8s/code-generator/pkg/model 6 | */}} 7 | {{- define "read_referenced_resource_and_validate" -}} 8 | {{- $objType := ( printf "%sapitypes.%s" .ReferencedServiceName .FieldConfig.References.Resource ) -}} 9 | {{- if eq .FieldConfig.References.ServiceName "" -}} 10 | {{- $objType = ( printf "svcapitypes.%s" .FieldConfig.References.Resource) -}} 11 | {{ end -}} 12 | // getReferencedResourceState_{{ .FieldConfig.References.Resource }} looks up whether a referenced resource 13 | // exists and is in a ACK.ResourceSynced=True state. If the referenced resource does exist and is 14 | // in a Synced state, returns nil, otherwise returns `ackerr.ResourceReferenceTerminalFor` or 15 | // `ResourceReferenceNotSyncedFor` depending on if the resource is in a Terminal state. 16 | func getReferencedResourceState_{{ .FieldConfig.References.Resource }}( 17 | ctx context.Context, 18 | apiReader client.Reader, 19 | obj *{{ $objType }}, 20 | name string, // the Kubernetes name of the referenced resource 21 | namespace string, // the Kubernetes namespace of the referenced resource 22 | ) error { 23 | namespacedName := types.NamespacedName{ 24 | Namespace: namespace, 25 | Name: name, 26 | } 27 | err := apiReader.Get(ctx, namespacedName, obj) 28 | if err != nil { 29 | return err 30 | } 31 | var refResourceTerminal bool 32 | for _, cond := range obj.Status.Conditions { 33 | if cond.Type == ackv1alpha1.ConditionTypeTerminal && 34 | cond.Status == corev1.ConditionTrue { 35 | return ackerr.ResourceReferenceTerminalFor( 36 | "{{ .FieldConfig.References.Resource }}", 37 | namespace, name) 38 | } 39 | } 40 | if refResourceTerminal { 41 | return ackerr.ResourceReferenceTerminalFor( 42 | "{{ .FieldConfig.References.Resource }}", 43 | namespace, name) 44 | } 45 | {{if not .FieldConfig.References.SkipResourceStateValidations -}} 46 | var refResourceSynced bool 47 | for _, cond := range obj.Status.Conditions { 48 | if cond.Type == ackv1alpha1.ConditionTypeResourceSynced && 49 | cond.Status == corev1.ConditionTrue { 50 | refResourceSynced = true 51 | } 52 | } 53 | if !refResourceSynced { 54 | return ackerr.ResourceReferenceNotSyncedFor( 55 | "{{ .FieldConfig.References.Resource }}", 56 | namespace, name) 57 | } 58 | if {{ CheckNilReferencesPath . "obj" }} { 59 | return ackerr.ResourceReferenceMissingTargetFieldFor( 60 | "{{ .FieldConfig.References.Resource }}", 61 | namespace, name, 62 | "{{ .FieldConfig.References.Path }}") 63 | } 64 | {{- end}} 65 | return nil 66 | } 67 | {{- end -}} 68 | -------------------------------------------------------------------------------- /templates/pkg/resource/registry.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package resource 4 | 5 | import ( 6 | ackrt "github.com/aws-controllers-k8s/runtime/pkg/runtime" 7 | acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" 8 | ) 9 | 10 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=adoptedresources,verbs=get;list;watch;create;update;patch;delete 11 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=adoptedresources/status,verbs=get;update;patch 12 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=fieldexports,verbs=get;list;watch;create;update;patch;delete 13 | // +kubebuilder:rbac:groups=services.k8s.aws,resources=fieldexports/status,verbs=get;update;patch 14 | // +kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch 15 | // +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;patch 16 | // +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;patch 17 | 18 | var ( 19 | reg = ackrt.NewRegistry() 20 | ) 21 | 22 | // GetManagerFactories returns a slice of resource manager factories that are 23 | // registered with this package 24 | func GetManagerFactories() []acktypes.AWSResourceManagerFactory { 25 | return reg.GetResourceManagerFactories() 26 | } 27 | 28 | // RegisterManagerFactory registers a resource manager factory with the 29 | // package's registry 30 | func RegisterManagerFactory(f acktypes.AWSResourceManagerFactory) { 31 | reg.RegisterResourceManagerFactory(f) 32 | } 33 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_delete_custom.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_delete_custom" }} 2 | return rm.{{ .CRD.CustomDeleteMethodName }}(ctx, r) 3 | {{- end }} -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_find_custom.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_custom" -}} 2 | func (rm *resourceManager) sdkFind( 3 | ctx context.Context, 4 | r *resource, 5 | ) (*resource, error) { 6 | return rm.{{ .CRD.CustomFindMethodName }}(ctx, r) 7 | } 8 | {{- end -}} 9 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_find_get_attributes.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_get_attributes" -}} 2 | func (rm *resourceManager) sdkFind( 3 | ctx context.Context, 4 | r *resource, 5 | ) (latest *resource, err error) { 6 | rlog := ackrtlog.FromContext(ctx) 7 | exit := rlog.Trace("rm.sdkFind") 8 | defer func() { 9 | exit(err) 10 | }() 11 | 12 | {{- if $hookCode := Hook .CRD "sdk_get_attributes_pre_build_request" }} 13 | {{ $hookCode }} 14 | {{- end }} 15 | // If any required fields in the input shape are missing, AWS resource is 16 | // not created yet. Return NotFound here to indicate to callers that the 17 | // resource isn't yet created. 18 | if rm.requiredFieldsMissingFromGetAttributesInput(r) { 19 | return nil, ackerr.NotFound 20 | } 21 | 22 | input, err := rm.newGetAttributesRequestPayload(r) 23 | if err != nil { 24 | return nil, err 25 | } 26 | {{- if $hookCode := Hook .CRD "sdk_get_attributes_post_build_request" }} 27 | {{ $hookCode }} 28 | {{- end }} 29 | var resp {{ .CRD.GetOutputShapeGoType .CRD.Ops.GetAttributes }} 30 | resp, err = rm.sdkapi.{{ .CRD.Ops.GetAttributes.ExportedName }}(ctx, input) 31 | {{- if $hookCode := Hook .CRD "sdk_get_attributes_post_request" }} 32 | {{ $hookCode }} 33 | {{- end }} 34 | rm.metrics.RecordAPICall("GET_ATTRIBUTES", "{{ .CRD.Ops.GetAttributes.ExportedName }}", err) 35 | if err != nil { 36 | var awsErr smithy.APIError 37 | if errors.As(err, &awsErr) && awsErr.ErrorCode() == "{{ ResourceExceptionCode .CRD 404 }}" {{ GoCodeSetExceptionMessageCheck .CRD 404 }} { 38 | return nil, ackerr.NotFound 39 | } 40 | return nil, err 41 | } 42 | 43 | // Merge in the information we read from the API call above to the copy of 44 | // the original Kubernetes object we passed to the function 45 | ko := r.ko.DeepCopy() 46 | {{ GoCodeGetAttributesSetOutput .CRD "resp" "ko" 1 }} 47 | {{- if $hookCode := Hook .CRD "sdk_get_attributes_pre_set_output" }} 48 | {{ $hookCode }} 49 | {{- end }} 50 | rm.setStatusDefaults(ko) 51 | {{- if $hookCode := Hook .CRD "sdk_get_attributes_post_set_output" }} 52 | {{ $hookCode }} 53 | {{- end }} 54 | return &resource{ko}, nil 55 | } 56 | 57 | // requiredFieldsMissingFromGetAtttributesInput returns true if there are any 58 | // fields for the GetAttributes Input shape that are required by not present in 59 | // the resource's Spec or Status 60 | func (rm *resourceManager) requiredFieldsMissingFromGetAttributesInput( 61 | r *resource, 62 | ) bool { 63 | {{- if $customCheckMethod := .CRD.GetCustomCheckRequiredFieldsMissingMethod .CRD.Ops.GetAttributes }} 64 | return rm.{{ $customCheckMethod }}(r) 65 | {{- else }} 66 | {{ GoCodeRequiredFieldsMissingFromGetAttributesInput .CRD "r.ko" 1 }} 67 | {{- end }} 68 | } 69 | 70 | // newGetAttributesRequestPayload returns SDK-specific struct for the HTTP 71 | // request payload of the GetAttributes API call for the resource 72 | func (rm *resourceManager) newGetAttributesRequestPayload( 73 | r *resource, 74 | ) (*svcsdk.{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }}, error) { 75 | res := &svcsdk.{{ .CRD.Ops.GetAttributes.InputRef.Shape.ShapeName }}{} 76 | {{ GoCodeGetAttributesSetInput .CRD "r.ko" "res" 1 }} 77 | return res, nil 78 | } 79 | {{- end -}} 80 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_find_not_implemented.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_not_implemented" -}} 2 | func (rm *resourceManager) sdkFind( 3 | ctx context.Context, 4 | r *resource, 5 | ) (*resource, error) { 6 | // Believe it or not, there are API resources that can be created but there 7 | // is no read operation. Point in case: RDS' CreateDBInstanceReadReplica 8 | // has no corresponding read operation that I know of... 9 | return nil, ackerr.NotImplemented 10 | } 11 | {{- end -}} 12 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_find_read_many.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_read_many" -}} 2 | func (rm *resourceManager) sdkFind( 3 | ctx context.Context, 4 | r *resource, 5 | ) (latest *resource, err error) { 6 | rlog := ackrtlog.FromContext(ctx) 7 | exit := rlog.Trace("rm.sdkFind") 8 | defer func() { 9 | exit(err) 10 | }() 11 | 12 | {{- if $hookCode := Hook .CRD "sdk_read_many_pre_build_request" }} 13 | {{ $hookCode }} 14 | {{- end }} 15 | // If any required fields in the input shape are missing, AWS resource is 16 | // not created yet. Return NotFound here to indicate to callers that the 17 | // resource isn't yet created. 18 | if rm.requiredFieldsMissingFromReadManyInput(r) { 19 | return nil, ackerr.NotFound 20 | } 21 | 22 | input, err := rm.newListRequestPayload(r) 23 | if err != nil { 24 | return nil, err 25 | } 26 | {{- if $hookCode := Hook .CRD "sdk_read_many_post_build_request" }} 27 | {{ $hookCode }} 28 | {{- end }} 29 | var resp {{ .CRD.GetOutputShapeGoType .CRD.Ops.ReadMany }} 30 | resp, err = rm.sdkapi.{{ .CRD.Ops.ReadMany.ExportedName }}(ctx, input) 31 | {{- if $hookCode := Hook .CRD "sdk_read_many_post_request" }} 32 | {{ $hookCode }} 33 | {{- end }} 34 | rm.metrics.RecordAPICall("READ_MANY", "{{ .CRD.Ops.ReadMany.ExportedName }}", err) 35 | if err != nil { 36 | var awsErr smithy.APIError 37 | if errors.As(err, &awsErr) && awsErr.ErrorCode() == "{{ ResourceExceptionCode .CRD 404 }}" {{ GoCodeSetExceptionMessageCheck .CRD 404 }} { 38 | return nil, ackerr.NotFound 39 | } 40 | return nil, err 41 | } 42 | 43 | // Merge in the information we read from the API call above to the copy of 44 | // the original Kubernetes object we passed to the function 45 | ko := r.ko.DeepCopy() 46 | {{- if $hookCode := Hook .CRD "sdk_read_many_pre_set_output" }} 47 | {{ $hookCode }} 48 | {{- end }} 49 | {{ GoCodeSetReadManyOutput .CRD "resp" "ko" 1 }} 50 | rm.setStatusDefaults(ko) 51 | {{- if $setOutputCustomMethodName := .CRD.SetOutputCustomMethodName .CRD.Ops.ReadMany }} 52 | // custom set output from response 53 | ko, err = rm.{{ $setOutputCustomMethodName }}(ctx, r, resp, ko) 54 | if err != nil { 55 | return nil, err 56 | } 57 | {{- end }} 58 | {{- if $hookCode := Hook .CRD "sdk_read_many_post_set_output" }} 59 | {{ $hookCode }} 60 | {{- end }} 61 | return &resource{ko}, nil 62 | } 63 | 64 | // requiredFieldsMissingFromReadManyInput returns true if there are any fields 65 | // for the ReadMany Input shape that are required but not present in the 66 | // resource's Spec or Status 67 | func (rm *resourceManager) requiredFieldsMissingFromReadManyInput( 68 | r *resource, 69 | ) bool { 70 | {{- if $customCheckMethod := .CRD.GetCustomCheckRequiredFieldsMissingMethod .CRD.Ops.ReadMany }} 71 | return rm.{{ $customCheckMethod }}(r) 72 | {{- else }} 73 | {{ GoCodeRequiredFieldsMissingFromReadManyInput .CRD "r.ko" 1 }} 74 | {{- end }} 75 | } 76 | 77 | // newListRequestPayload returns SDK-specific struct for the HTTP request 78 | // payload of the List API call for the resource 79 | func (rm *resourceManager) newListRequestPayload( 80 | r *resource, 81 | ) (*svcsdk.{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }}, error) { 82 | res := &svcsdk.{{ .CRD.Ops.ReadMany.InputRef.Shape.ShapeName }}{} 83 | {{ GoCodeSetReadManyInput .CRD "r.ko" "res" 1 }} 84 | return res, nil 85 | } 86 | {{- end -}} 87 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_find_read_one.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_find_read_one" -}} 2 | func (rm *resourceManager) sdkFind( 3 | ctx context.Context, 4 | r *resource, 5 | ) (latest *resource, err error) { 6 | rlog := ackrtlog.FromContext(ctx) 7 | exit := rlog.Trace("rm.sdkFind") 8 | defer func() { 9 | exit(err) 10 | }() 11 | 12 | {{- if $hookCode := Hook .CRD "sdk_read_one_pre_build_request" }} 13 | {{ $hookCode }} 14 | {{- end }} 15 | // If any required fields in the input shape are missing, AWS resource is 16 | // not created yet. Return NotFound here to indicate to callers that the 17 | // resource isn't yet created. 18 | if rm.requiredFieldsMissingFromReadOneInput(r) { 19 | return nil, ackerr.NotFound 20 | } 21 | 22 | input, err := rm.newDescribeRequestPayload(r) 23 | if err != nil { 24 | return nil, err 25 | } 26 | {{- if $hookCode := Hook .CRD "sdk_read_one_post_build_request" }} 27 | {{ $hookCode }} 28 | {{- end }} 29 | 30 | var resp {{ .CRD.GetOutputShapeGoType .CRD.Ops.ReadOne }} 31 | resp, err = rm.sdkapi.{{ .CRD.Ops.ReadOne.ExportedName }}(ctx, input) 32 | {{- if $hookCode := Hook .CRD "sdk_read_one_post_request" }} 33 | {{ $hookCode }} 34 | {{- end }} 35 | rm.metrics.RecordAPICall("READ_ONE", "{{ .CRD.Ops.ReadOne.ExportedName }}", err) 36 | if err != nil { 37 | var awsErr smithy.APIError 38 | if errors.As(err, &awsErr) && awsErr.ErrorCode() == "{{ ResourceExceptionCode .CRD 404 }}" {{ GoCodeSetExceptionMessageCheck .CRD 404 }} { 39 | return nil, ackerr.NotFound 40 | } 41 | return nil, err 42 | } 43 | 44 | // Merge in the information we read from the API call above to the copy of 45 | // the original Kubernetes object we passed to the function 46 | ko := r.ko.DeepCopy() 47 | {{- if $hookCode := Hook .CRD "sdk_read_one_pre_set_output" }} 48 | {{ $hookCode }} 49 | {{- end }} 50 | {{ GoCodeSetReadOneOutput .CRD "resp" "ko" 1 }} 51 | rm.setStatusDefaults(ko) 52 | {{- if $setOutputCustomMethodName := .CRD.SetOutputCustomMethodName .CRD.Ops.ReadOne }} 53 | // custom set output from response 54 | ko, err = rm.{{ $setOutputCustomMethodName }}(ctx, r, resp, ko) 55 | if err != nil { 56 | return nil, err 57 | } 58 | {{- end }} 59 | {{- if $hookCode := Hook .CRD "sdk_read_one_post_set_output" }} 60 | {{ $hookCode }} 61 | {{- end }} 62 | return &resource{ko}, nil 63 | } 64 | 65 | // requiredFieldsMissingFromReadOneInput returns true if there are any fields 66 | // for the ReadOne Input shape that are required but not present in the 67 | // resource's Spec or Status 68 | func (rm *resourceManager) requiredFieldsMissingFromReadOneInput( 69 | r *resource, 70 | ) bool { 71 | {{- if $customCheckMethod := .CRD.GetCustomCheckRequiredFieldsMissingMethod .CRD.Ops.ReadOne }} 72 | return rm.{{ $customCheckMethod }}(r) 73 | {{- else }} 74 | {{ GoCodeRequiredFieldsMissingFromReadOneInput .CRD "r.ko" 1 }} 75 | {{- end }} 76 | } 77 | 78 | // newDescribeRequestPayload returns SDK-specific struct for the HTTP request 79 | // payload of the Describe API call for the resource 80 | func (rm *resourceManager) newDescribeRequestPayload( 81 | r *resource, 82 | ) (*svcsdk.{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }}, error) { 83 | res := &svcsdk.{{ .CRD.Ops.ReadOne.InputRef.Shape.ShapeName }}{} 84 | {{ GoCodeSetReadOneInput .CRD "r.ko" "res" 1 }} 85 | return res, nil 86 | } 87 | {{- end -}} 88 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_update.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_update" -}} 2 | func (rm *resourceManager) sdkUpdate( 3 | ctx context.Context, 4 | desired *resource, 5 | latest *resource, 6 | delta *ackcompare.Delta, 7 | ) (updated *resource, err error) { 8 | rlog := ackrtlog.FromContext(ctx) 9 | exit := rlog.Trace("rm.sdkUpdate") 10 | defer func() { 11 | exit(err) 12 | }() 13 | {{- if $hookCode := Hook .CRD "sdk_update_pre_build_request" }} 14 | {{ $hookCode }} 15 | {{- end }} 16 | {{- if $customMethod := .CRD.GetCustomImplementation .CRD.Ops.Update }} 17 | updated, err = rm.{{ $customMethod }}(ctx, desired, latest, delta) 18 | if updated != nil || err != nil { 19 | return updated, err 20 | } 21 | {{- end }} 22 | input, err := rm.newUpdateRequestPayload(ctx, desired, delta) 23 | if err != nil { 24 | return nil, err 25 | } 26 | {{- if $hookCode := Hook .CRD "sdk_update_post_build_request" }} 27 | {{ $hookCode }} 28 | {{- end }} 29 | 30 | var resp {{ .CRD.GetOutputShapeGoType .CRD.Ops.Update }}; _ = resp; 31 | resp, err = rm.sdkapi.{{ .CRD.Ops.Update.ExportedName }}(ctx, input) 32 | {{- if $hookCode := Hook .CRD "sdk_update_post_request" }} 33 | {{ $hookCode }} 34 | {{- end }} 35 | rm.metrics.RecordAPICall("UPDATE", "{{ .CRD.Ops.Update.ExportedName }}", err) 36 | if err != nil { 37 | return nil, err 38 | } 39 | // Merge in the information we read from the API call above to the copy of 40 | // the original Kubernetes object we passed to the function 41 | ko := desired.ko.DeepCopy() 42 | {{- if $hookCode := Hook .CRD "sdk_update_pre_set_output" }} 43 | {{ $hookCode }} 44 | {{- end }} 45 | {{ GoCodeSetUpdateOutput .CRD "resp" "ko" 1 }} 46 | rm.setStatusDefaults(ko) 47 | {{- if $setOutputCustomMethodName := .CRD.SetOutputCustomMethodName .CRD.Ops.Update }} 48 | // custom set output from response 49 | ko, err = rm.{{ $setOutputCustomMethodName }}(ctx, desired, resp, ko) 50 | if err != nil { 51 | return nil, err 52 | } 53 | {{- end }} 54 | {{- if $hookCode := Hook .CRD "sdk_update_post_set_output" }} 55 | {{ $hookCode }} 56 | {{- end }} 57 | return &resource{ko}, nil 58 | } 59 | 60 | // newUpdateRequestPayload returns an SDK-specific struct for the HTTP request 61 | // payload of the Update API call for the resource 62 | func (rm *resourceManager) newUpdateRequestPayload( 63 | ctx context.Context, 64 | r *resource, 65 | delta *ackcompare.Delta, 66 | ) (*svcsdk.{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }}, error) { 67 | res := &svcsdk.{{ .CRD.Ops.Update.InputRef.Shape.ShapeName }}{} 68 | {{ GoCodeSetUpdateInput .CRD "r.ko" "res" 1 }} 69 | return res, nil 70 | } 71 | {{- end -}} 72 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_update_custom.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_update_custom" -}} 2 | func (rm *resourceManager) sdkUpdate( 3 | ctx context.Context, 4 | desired *resource, 5 | latest *resource, 6 | delta *ackcompare.Delta, 7 | ) (*resource, error) { 8 | return rm.{{ .CRD.CustomUpdateMethodName }}(ctx, desired, latest, delta) 9 | } 10 | {{- end -}} 11 | -------------------------------------------------------------------------------- /templates/pkg/resource/sdk_update_not_implemented.go.tpl: -------------------------------------------------------------------------------- 1 | {{- define "sdk_update_not_implemented" -}} 2 | func (rm *resourceManager) sdkUpdate( 3 | ctx context.Context, 4 | desired *resource, 5 | latest *resource, 6 | delta *ackcompare.Delta, 7 | ) (*resource, error) { 8 | return nil, ackerr.NewTerminalError(ackerr.NotImplemented) 9 | } 10 | {{- end -}} 11 | -------------------------------------------------------------------------------- /templates/pkg/version/version.go.tpl: -------------------------------------------------------------------------------- 1 | {{ template "boilerplate" }} 2 | 3 | package version 4 | 5 | var ( 6 | GitVersion string 7 | GitCommit string 8 | BuildDate string 9 | ) --------------------------------------------------------------------------------