From 9b399a3b25a87e3a67a70b936c79508640daf9b5 Mon Sep 17 00:00:00 2001 From: teeverr Date: Fri, 14 Jul 2023 15:39:27 +0200 Subject: [PATCH] add service catalog - provisioned product Signed-off-by: teeverr empty commit, try to unstuck --- apis/servicecatalog/generator-config.yaml | 84 + apis/servicecatalog/v1alpha1/custom_types.go | 4 + apis/servicecatalog/v1alpha1/zz_doc.go | 24 + apis/servicecatalog/v1alpha1/zz_enums.go | 303 ++++ .../v1alpha1/zz_generated.deepcopy.go | 1368 +++++++++++++++++ .../v1alpha1/zz_generated.managed.go | 87 ++ .../v1alpha1/zz_generated.managedlist.go | 30 + .../v1alpha1/zz_groupversion_info.go | 41 + .../v1alpha1/zz_provisioned_product.go | 191 +++ apis/servicecatalog/v1alpha1/zz_types.go | 330 ++++ .../servicecatalog/provisionedproduct.yaml | 46 + go.mod | 9 +- go.sum | 14 +- ...aws.crossplane.io_provisionedproducts.yaml | 472 ++++++ pkg/clients/servicecatalog/fake/fake.go | 48 + pkg/clients/servicecatalog/servicecatalog.go | 82 + pkg/controller/aws.go | 2 + .../provisionedproduct/setup.go | 265 ++++ .../provisionedproduct/setup_test.go | 522 +++++++ .../provisionedproduct/zz_controller.go | 314 ++++ .../provisionedproduct/zz_conversions.go | 262 ++++ 21 files changed, 4490 insertions(+), 8 deletions(-) create mode 100644 apis/servicecatalog/generator-config.yaml create mode 100644 apis/servicecatalog/v1alpha1/custom_types.go create mode 100644 apis/servicecatalog/v1alpha1/zz_doc.go create mode 100644 apis/servicecatalog/v1alpha1/zz_enums.go create mode 100644 apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go create mode 100644 apis/servicecatalog/v1alpha1/zz_generated.managed.go create mode 100644 apis/servicecatalog/v1alpha1/zz_generated.managedlist.go create mode 100644 apis/servicecatalog/v1alpha1/zz_groupversion_info.go create mode 100644 apis/servicecatalog/v1alpha1/zz_provisioned_product.go create mode 100644 apis/servicecatalog/v1alpha1/zz_types.go create mode 100644 examples/servicecatalog/provisionedproduct.yaml create mode 100644 package/crds/servicecatalog.aws.crossplane.io_provisionedproducts.yaml create mode 100644 pkg/clients/servicecatalog/fake/fake.go create mode 100644 pkg/clients/servicecatalog/servicecatalog.go create mode 100644 pkg/controller/servicecatalog/provisionedproduct/setup.go create mode 100644 pkg/controller/servicecatalog/provisionedproduct/setup_test.go create mode 100644 pkg/controller/servicecatalog/provisionedproduct/zz_controller.go create mode 100644 pkg/controller/servicecatalog/provisionedproduct/zz_conversions.go diff --git a/apis/servicecatalog/generator-config.yaml b/apis/servicecatalog/generator-config.yaml new file mode 100644 index 0000000000..85a3937d91 --- /dev/null +++ b/apis/servicecatalog/generator-config.yaml @@ -0,0 +1,84 @@ +--- +ignore: + resource_names: + - Constraint + - PortfolioShare + - Portfolio + - Cluster + - Product + - ProvisionedProductPlan + - ProvisioningArtifact + - ServiceAction + - TagOption + field_paths: + - ProvisionProductInput.ProvisionToken + - UpdateProvisioningParameter.UsePreviousValue + - UpdateProvisioningPreferences.StackSetOperationType + - UpdateProvisionedProductInput.ProvisionedProductId + - TerminateProvisionedProductInput.ProvisionedProductId + shape_names: + - ProvisionedProductPlanSummary + - ProvisionedProductPlanDetails +operations: + ProvisionProduct: + operation_type: + - Create + resource_name: ProvisionedProduct + UpdateProvisionedProduct: + operation_type: + - Update + resource_name: ProvisionedProduct + DescribeProvisionedProduct: + operation_type: + - Read + resource_name: ProvisionedProduct + TerminateProvisionedProduct: + operation_type: + - Delete + resource_name: ProvisionedProduct +resources: + ProvisionedProduct: + exceptions: + errors: + 404: + code: ResourceNotFoundException + fields: + Outputs: + is_read_only: true + custom_field: + map_of: RecordOutput + Arn: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.Arn + CreatedTime: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.CreatedTime + LastProvisioningRecordId: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.LastProvisioningRecordId + LaunchRoleArn: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.LaunchRoleArn + Status: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.Status + StatusMessage: + is_read_only: true + from: + operation: DescribeProvisionedProduct + path: ProvisionedProductDetail.StatusMessage + renames: + operations: + ProvisionProduct: + input_fields: + ProvisionedProductName: Name \ No newline at end of file diff --git a/apis/servicecatalog/v1alpha1/custom_types.go b/apis/servicecatalog/v1alpha1/custom_types.go new file mode 100644 index 0000000000..0f579cb91e --- /dev/null +++ b/apis/servicecatalog/v1alpha1/custom_types.go @@ -0,0 +1,4 @@ +package v1alpha1 + +// CustomProvisionedProductParameters includes the custom fields. +type CustomProvisionedProductParameters struct{} diff --git a/apis/servicecatalog/v1alpha1/zz_doc.go b/apis/servicecatalog/v1alpha1/zz_doc.go new file mode 100644 index 0000000000..1aa26ff243 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +// +kubebuilder:object:generate=true +// Package v1alpha1 is the v1alpha1 version of the servicecatalog.aws.crossplane.io API. +// +groupName=servicecatalog.aws.crossplane.io +// +versionName=v1alpha1 + +package v1alpha1 diff --git a/apis/servicecatalog/v1alpha1/zz_enums.go b/apis/servicecatalog/v1alpha1/zz_enums.go new file mode 100644 index 0000000000..8a7dfaee42 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_enums.go @@ -0,0 +1,303 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package v1alpha1 + +type AccessLevelFilterKey string + +const ( + AccessLevelFilterKey_Account AccessLevelFilterKey = "Account" + AccessLevelFilterKey_Role AccessLevelFilterKey = "Role" + AccessLevelFilterKey_User AccessLevelFilterKey = "User" +) + +type AccessStatus string + +const ( + AccessStatus_ENABLED AccessStatus = "ENABLED" + AccessStatus_UNDER_CHANGE AccessStatus = "UNDER_CHANGE" + AccessStatus_DISABLED AccessStatus = "DISABLED" +) + +type ChangeAction string + +const ( + ChangeAction_ADD ChangeAction = "ADD" + ChangeAction_MODIFY ChangeAction = "MODIFY" + ChangeAction_REMOVE ChangeAction = "REMOVE" +) + +type CopyOption string + +const ( + CopyOption_CopyTags CopyOption = "CopyTags" +) + +type CopyProductStatus string + +const ( + CopyProductStatus_SUCCEEDED CopyProductStatus = "SUCCEEDED" + CopyProductStatus_IN_PROGRESS CopyProductStatus = "IN_PROGRESS" + CopyProductStatus_FAILED CopyProductStatus = "FAILED" +) + +type DescribePortfolioShareType string + +const ( + DescribePortfolioShareType_ACCOUNT DescribePortfolioShareType = "ACCOUNT" + DescribePortfolioShareType_ORGANIZATION DescribePortfolioShareType = "ORGANIZATION" + DescribePortfolioShareType_ORGANIZATIONAL_UNIT DescribePortfolioShareType = "ORGANIZATIONAL_UNIT" + DescribePortfolioShareType_ORGANIZATION_MEMBER_ACCOUNT DescribePortfolioShareType = "ORGANIZATION_MEMBER_ACCOUNT" +) + +type EvaluationType string + +const ( + EvaluationType_STATIC EvaluationType = "STATIC" + EvaluationType_DYNAMIC EvaluationType = "DYNAMIC" +) + +type LastSyncStatus string + +const ( + LastSyncStatus_SUCCEEDED LastSyncStatus = "SUCCEEDED" + LastSyncStatus_FAILED LastSyncStatus = "FAILED" +) + +type OrganizationNodeType string + +const ( + OrganizationNodeType_ORGANIZATION OrganizationNodeType = "ORGANIZATION" + OrganizationNodeType_ORGANIZATIONAL_UNIT OrganizationNodeType = "ORGANIZATIONAL_UNIT" + OrganizationNodeType_ACCOUNT OrganizationNodeType = "ACCOUNT" +) + +type PortfolioShareType string + +const ( + PortfolioShareType_IMPORTED PortfolioShareType = "IMPORTED" + PortfolioShareType_AWS_SERVICECATALOG PortfolioShareType = "AWS_SERVICECATALOG" + PortfolioShareType_AWS_ORGANIZATIONS PortfolioShareType = "AWS_ORGANIZATIONS" +) + +type PrincipalType string + +const ( + PrincipalType_IAM PrincipalType = "IAM" + PrincipalType_IAM_PATTERN PrincipalType = "IAM_PATTERN" +) + +type ProductSource string + +const ( + ProductSource_ACCOUNT ProductSource = "ACCOUNT" +) + +type ProductType string + +const ( + ProductType_CLOUD_FORMATION_TEMPLATE ProductType = "CLOUD_FORMATION_TEMPLATE" + ProductType_MARKETPLACE ProductType = "MARKETPLACE" +) + +type ProductViewFilterBy string + +const ( + ProductViewFilterBy_FullTextSearch ProductViewFilterBy = "FullTextSearch" + ProductViewFilterBy_Owner ProductViewFilterBy = "Owner" + ProductViewFilterBy_ProductType ProductViewFilterBy = "ProductType" + ProductViewFilterBy_SourceProductId ProductViewFilterBy = "SourceProductId" +) + +type ProductViewSortBy string + +const ( + ProductViewSortBy_Title ProductViewSortBy = "Title" + ProductViewSortBy_VersionCount ProductViewSortBy = "VersionCount" + ProductViewSortBy_CreationDate ProductViewSortBy = "CreationDate" +) + +type PropertyKey string + +const ( + PropertyKey_OWNER PropertyKey = "OWNER" + PropertyKey_LAUNCH_ROLE PropertyKey = "LAUNCH_ROLE" +) + +type ProvisionedProductPlanStatus string + +const ( + ProvisionedProductPlanStatus_CREATE_IN_PROGRESS ProvisionedProductPlanStatus = "CREATE_IN_PROGRESS" + ProvisionedProductPlanStatus_CREATE_SUCCESS ProvisionedProductPlanStatus = "CREATE_SUCCESS" + ProvisionedProductPlanStatus_CREATE_FAILED ProvisionedProductPlanStatus = "CREATE_FAILED" + ProvisionedProductPlanStatus_EXECUTE_IN_PROGRESS ProvisionedProductPlanStatus = "EXECUTE_IN_PROGRESS" + ProvisionedProductPlanStatus_EXECUTE_SUCCESS ProvisionedProductPlanStatus = "EXECUTE_SUCCESS" + ProvisionedProductPlanStatus_EXECUTE_FAILED ProvisionedProductPlanStatus = "EXECUTE_FAILED" +) + +type ProvisionedProductPlanType string + +const ( + ProvisionedProductPlanType_CLOUDFORMATION ProvisionedProductPlanType = "CLOUDFORMATION" +) + +type ProvisionedProductStatus_SDK string + +const ( + ProvisionedProductStatus_SDK_AVAILABLE ProvisionedProductStatus_SDK = "AVAILABLE" + ProvisionedProductStatus_SDK_UNDER_CHANGE ProvisionedProductStatus_SDK = "UNDER_CHANGE" + ProvisionedProductStatus_SDK_TAINTED ProvisionedProductStatus_SDK = "TAINTED" + ProvisionedProductStatus_SDK_ERROR ProvisionedProductStatus_SDK = "ERROR" + ProvisionedProductStatus_SDK_PLAN_IN_PROGRESS ProvisionedProductStatus_SDK = "PLAN_IN_PROGRESS" +) + +type ProvisionedProductViewFilterBy string + +const ( + ProvisionedProductViewFilterBy_SearchQuery ProvisionedProductViewFilterBy = "SearchQuery" +) + +type ProvisioningArtifactGuidance string + +const ( + ProvisioningArtifactGuidance_DEFAULT ProvisioningArtifactGuidance = "DEFAULT" + ProvisioningArtifactGuidance_DEPRECATED ProvisioningArtifactGuidance = "DEPRECATED" +) + +type ProvisioningArtifactPropertyName string + +const ( + ProvisioningArtifactPropertyName_Id ProvisioningArtifactPropertyName = "Id" +) + +type ProvisioningArtifactType string + +const ( + ProvisioningArtifactType_CLOUD_FORMATION_TEMPLATE ProvisioningArtifactType = "CLOUD_FORMATION_TEMPLATE" + ProvisioningArtifactType_MARKETPLACE_AMI ProvisioningArtifactType = "MARKETPLACE_AMI" + ProvisioningArtifactType_MARKETPLACE_CAR ProvisioningArtifactType = "MARKETPLACE_CAR" +) + +type RecordStatus string + +const ( + RecordStatus_CREATED RecordStatus = "CREATED" + RecordStatus_IN_PROGRESS RecordStatus = "IN_PROGRESS" + RecordStatus_IN_PROGRESS_IN_ERROR RecordStatus = "IN_PROGRESS_IN_ERROR" + RecordStatus_SUCCEEDED RecordStatus = "SUCCEEDED" + RecordStatus_FAILED RecordStatus = "FAILED" +) + +type Replacement string + +const ( + Replacement_TRUE Replacement = "TRUE" + Replacement_FALSE Replacement = "FALSE" + Replacement_CONDITIONAL Replacement = "CONDITIONAL" +) + +type RequiresRecreation string + +const ( + RequiresRecreation_NEVER RequiresRecreation = "NEVER" + RequiresRecreation_CONDITIONALLY RequiresRecreation = "CONDITIONALLY" + RequiresRecreation_ALWAYS RequiresRecreation = "ALWAYS" +) + +type ResourceAttribute string + +const ( + ResourceAttribute_PROPERTIES ResourceAttribute = "PROPERTIES" + ResourceAttribute_METADATA ResourceAttribute = "METADATA" + ResourceAttribute_CREATIONPOLICY ResourceAttribute = "CREATIONPOLICY" + ResourceAttribute_UPDATEPOLICY ResourceAttribute = "UPDATEPOLICY" + ResourceAttribute_DELETIONPOLICY ResourceAttribute = "DELETIONPOLICY" + ResourceAttribute_TAGS ResourceAttribute = "TAGS" +) + +type ServiceActionAssociationErrorCode string + +const ( + ServiceActionAssociationErrorCode_DUPLICATE_RESOURCE ServiceActionAssociationErrorCode = "DUPLICATE_RESOURCE" + ServiceActionAssociationErrorCode_INTERNAL_FAILURE ServiceActionAssociationErrorCode = "INTERNAL_FAILURE" + ServiceActionAssociationErrorCode_LIMIT_EXCEEDED ServiceActionAssociationErrorCode = "LIMIT_EXCEEDED" + ServiceActionAssociationErrorCode_RESOURCE_NOT_FOUND ServiceActionAssociationErrorCode = "RESOURCE_NOT_FOUND" + ServiceActionAssociationErrorCode_THROTTLING ServiceActionAssociationErrorCode = "THROTTLING" +) + +type ServiceActionDefinitionKey string + +const ( + ServiceActionDefinitionKey_Name ServiceActionDefinitionKey = "Name" + ServiceActionDefinitionKey_Version ServiceActionDefinitionKey = "Version" + ServiceActionDefinitionKey_AssumeRole ServiceActionDefinitionKey = "AssumeRole" + ServiceActionDefinitionKey_Parameters ServiceActionDefinitionKey = "Parameters" +) + +type ServiceActionDefinitionType string + +const ( + ServiceActionDefinitionType_SSM_AUTOMATION ServiceActionDefinitionType = "SSM_AUTOMATION" +) + +type ShareStatus string + +const ( + ShareStatus_NOT_STARTED ShareStatus = "NOT_STARTED" + ShareStatus_IN_PROGRESS ShareStatus = "IN_PROGRESS" + ShareStatus_COMPLETED ShareStatus = "COMPLETED" + ShareStatus_COMPLETED_WITH_ERRORS ShareStatus = "COMPLETED_WITH_ERRORS" + ShareStatus_ERROR ShareStatus = "ERROR" +) + +type SortOrder string + +const ( + SortOrder_ASCENDING SortOrder = "ASCENDING" + SortOrder_DESCENDING SortOrder = "DESCENDING" +) + +type SourceType string + +const ( + SourceType_CODESTAR SourceType = "CODESTAR" +) + +type StackInstanceStatus string + +const ( + StackInstanceStatus_CURRENT StackInstanceStatus = "CURRENT" + StackInstanceStatus_OUTDATED StackInstanceStatus = "OUTDATED" + StackInstanceStatus_INOPERABLE StackInstanceStatus = "INOPERABLE" +) + +type StackSetOperationType string + +const ( + StackSetOperationType_CREATE StackSetOperationType = "CREATE" + StackSetOperationType_UPDATE StackSetOperationType = "UPDATE" + StackSetOperationType_DELETE StackSetOperationType = "DELETE" +) + +type Status string + +const ( + Status_AVAILABLE Status = "AVAILABLE" + Status_CREATING Status = "CREATING" + Status_FAILED Status = "FAILED" +) diff --git a/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go b/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..37834dc16b --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,1368 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CloudWatchDashboard) DeepCopyInto(out *CloudWatchDashboard) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CloudWatchDashboard. +func (in *CloudWatchDashboard) DeepCopy() *CloudWatchDashboard { + if in == nil { + return nil + } + out := new(CloudWatchDashboard) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConstraintDetail) DeepCopyInto(out *ConstraintDetail) { + *out = *in + if in.ConstraintID != nil { + in, out := &in.ConstraintID, &out.ConstraintID + *out = new(string) + **out = **in + } + if in.Owner != nil { + in, out := &in.Owner, &out.Owner + *out = new(string) + **out = **in + } + if in.PortfolioID != nil { + in, out := &in.PortfolioID, &out.PortfolioID + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConstraintDetail. +func (in *ConstraintDetail) DeepCopy() *ConstraintDetail { + if in == nil { + return nil + } + out := new(ConstraintDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomProvisionedProductParameters) DeepCopyInto(out *CustomProvisionedProductParameters) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomProvisionedProductParameters. +func (in *CustomProvisionedProductParameters) DeepCopy() *CustomProvisionedProductParameters { + if in == nil { + return nil + } + out := new(CustomProvisionedProductParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FailedServiceActionAssociation) DeepCopyInto(out *FailedServiceActionAssociation) { + *out = *in + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.ServiceActionID != nil { + in, out := &in.ServiceActionID, &out.ServiceActionID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailedServiceActionAssociation. +func (in *FailedServiceActionAssociation) DeepCopy() *FailedServiceActionAssociation { + if in == nil { + return nil + } + out := new(FailedServiceActionAssociation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LastSync) DeepCopyInto(out *LastSync) { + *out = *in + if in.LastSuccessfulSyncProvisioningArtifactID != nil { + in, out := &in.LastSuccessfulSyncProvisioningArtifactID, &out.LastSuccessfulSyncProvisioningArtifactID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LastSync. +func (in *LastSync) DeepCopy() *LastSync { + if in == nil { + return nil + } + out := new(LastSync) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LaunchPath) DeepCopyInto(out *LaunchPath) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LaunchPath. +func (in *LaunchPath) DeepCopy() *LaunchPath { + if in == nil { + return nil + } + out := new(LaunchPath) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LaunchPathSummary) DeepCopyInto(out *LaunchPathSummary) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]*Tag, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Tag) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LaunchPathSummary. +func (in *LaunchPathSummary) DeepCopy() *LaunchPathSummary { + if in == nil { + return nil + } + out := new(LaunchPathSummary) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PortfolioDetail) DeepCopyInto(out *PortfolioDetail) { + *out = *in + if in.DisplayName != nil { + in, out := &in.DisplayName, &out.DisplayName + *out = new(string) + **out = **in + } + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortfolioDetail. +func (in *PortfolioDetail) DeepCopy() *PortfolioDetail { + if in == nil { + return nil + } + out := new(PortfolioDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PortfolioShareDetail) DeepCopyInto(out *PortfolioShareDetail) { + *out = *in + if in.PrincipalID != nil { + in, out := &in.PrincipalID, &out.PrincipalID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortfolioShareDetail. +func (in *PortfolioShareDetail) DeepCopy() *PortfolioShareDetail { + if in == nil { + return nil + } + out := new(PortfolioShareDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductViewDetail) DeepCopyInto(out *ProductViewDetail) { + *out = *in + if in.CreatedTime != nil { + in, out := &in.CreatedTime, &out.CreatedTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductViewDetail. +func (in *ProductViewDetail) DeepCopy() *ProductViewDetail { + if in == nil { + return nil + } + out := new(ProductViewDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProductViewSummary) DeepCopyInto(out *ProductViewSummary) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProductViewSummary. +func (in *ProductViewSummary) DeepCopy() *ProductViewSummary { + if in == nil { + return nil + } + out := new(ProductViewSummary) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProduct) DeepCopyInto(out *ProvisionedProduct) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProduct. +func (in *ProvisionedProduct) DeepCopy() *ProvisionedProduct { + if in == nil { + return nil + } + out := new(ProvisionedProduct) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ProvisionedProduct) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductAttribute) DeepCopyInto(out *ProvisionedProductAttribute) { + *out = *in + if in.ARN != nil { + in, out := &in.ARN, &out.ARN + *out = new(string) + **out = **in + } + if in.CreatedTime != nil { + in, out := &in.CreatedTime, &out.CreatedTime + *out = (*in).DeepCopy() + } + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.IdempotencyToken != nil { + in, out := &in.IdempotencyToken, &out.IdempotencyToken + *out = new(string) + **out = **in + } + if in.LastProvisioningRecordID != nil { + in, out := &in.LastProvisioningRecordID, &out.LastProvisioningRecordID + *out = new(string) + **out = **in + } + if in.LastRecordID != nil { + in, out := &in.LastRecordID, &out.LastRecordID + *out = new(string) + **out = **in + } + if in.LastSuccessfulProvisioningRecordID != nil { + in, out := &in.LastSuccessfulProvisioningRecordID, &out.LastSuccessfulProvisioningRecordID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProductName != nil { + in, out := &in.ProductName, &out.ProductName + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactName != nil { + in, out := &in.ProvisioningArtifactName, &out.ProvisioningArtifactName + *out = new(string) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } + if in.StatusMessage != nil { + in, out := &in.StatusMessage, &out.StatusMessage + *out = new(string) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]*Tag, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Tag) + (*in).DeepCopyInto(*out) + } + } + } + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductAttribute. +func (in *ProvisionedProductAttribute) DeepCopy() *ProvisionedProductAttribute { + if in == nil { + return nil + } + out := new(ProvisionedProductAttribute) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductDetail) DeepCopyInto(out *ProvisionedProductDetail) { + *out = *in + if in.ARN != nil { + in, out := &in.ARN, &out.ARN + *out = new(string) + **out = **in + } + if in.CreatedTime != nil { + in, out := &in.CreatedTime, &out.CreatedTime + *out = (*in).DeepCopy() + } + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.IdempotencyToken != nil { + in, out := &in.IdempotencyToken, &out.IdempotencyToken + *out = new(string) + **out = **in + } + if in.LastProvisioningRecordID != nil { + in, out := &in.LastProvisioningRecordID, &out.LastProvisioningRecordID + *out = new(string) + **out = **in + } + if in.LastRecordID != nil { + in, out := &in.LastRecordID, &out.LastRecordID + *out = new(string) + **out = **in + } + if in.LastSuccessfulProvisioningRecordID != nil { + in, out := &in.LastSuccessfulProvisioningRecordID, &out.LastSuccessfulProvisioningRecordID + *out = new(string) + **out = **in + } + if in.LaunchRoleARN != nil { + in, out := &in.LaunchRoleARN, &out.LaunchRoleARN + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } + if in.StatusMessage != nil { + in, out := &in.StatusMessage, &out.StatusMessage + *out = new(string) + **out = **in + } + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductDetail. +func (in *ProvisionedProductDetail) DeepCopy() *ProvisionedProductDetail { + if in == nil { + return nil + } + out := new(ProvisionedProductDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductList) DeepCopyInto(out *ProvisionedProductList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ProvisionedProduct, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductList. +func (in *ProvisionedProductList) DeepCopy() *ProvisionedProductList { + if in == nil { + return nil + } + out := new(ProvisionedProductList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ProvisionedProductList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductObservation) DeepCopyInto(out *ProvisionedProductObservation) { + *out = *in + if in.ARN != nil { + in, out := &in.ARN, &out.ARN + *out = new(string) + **out = **in + } + if in.CreatedTime != nil { + in, out := &in.CreatedTime, &out.CreatedTime + *out = (*in).DeepCopy() + } + if in.LastProvisioningRecordID != nil { + in, out := &in.LastProvisioningRecordID, &out.LastProvisioningRecordID + *out = new(string) + **out = **in + } + if in.LaunchRoleARN != nil { + in, out := &in.LaunchRoleARN, &out.LaunchRoleARN + *out = new(string) + **out = **in + } + if in.Outputs != nil { + in, out := &in.Outputs, &out.Outputs + *out = make(map[string]*RecordOutput, len(*in)) + for key, val := range *in { + var outVal *RecordOutput + if val == nil { + (*out)[key] = nil + } else { + in, out := &val, &outVal + *out = new(RecordOutput) + (*in).DeepCopyInto(*out) + } + (*out)[key] = outVal + } + } + if in.ProvisionedProductID != nil { + in, out := &in.ProvisionedProductID, &out.ProvisionedProductID + *out = new(string) + **out = **in + } + if in.ProvisionedProductType != nil { + in, out := &in.ProvisionedProductType, &out.ProvisionedProductType + *out = new(string) + **out = **in + } + if in.RecordErrors != nil { + in, out := &in.RecordErrors, &out.RecordErrors + *out = make([]*RecordError, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RecordError) + (*in).DeepCopyInto(*out) + } + } + } + if in.RecordID != nil { + in, out := &in.RecordID, &out.RecordID + *out = new(string) + **out = **in + } + if in.RecordTags != nil { + in, out := &in.RecordTags, &out.RecordTags + *out = make([]*RecordTag, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RecordTag) + (*in).DeepCopyInto(*out) + } + } + } + if in.RecordType != nil { + in, out := &in.RecordType, &out.RecordType + *out = new(string) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } + if in.StatusMessage != nil { + in, out := &in.StatusMessage, &out.StatusMessage + *out = new(string) + **out = **in + } + if in.UpdatedTime != nil { + in, out := &in.UpdatedTime, &out.UpdatedTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductObservation. +func (in *ProvisionedProductObservation) DeepCopy() *ProvisionedProductObservation { + if in == nil { + return nil + } + out := new(ProvisionedProductObservation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductParameters) DeepCopyInto(out *ProvisionedProductParameters) { + *out = *in + if in.AcceptLanguage != nil { + in, out := &in.AcceptLanguage, &out.AcceptLanguage + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.NotificationARNs != nil { + in, out := &in.NotificationARNs, &out.NotificationARNs + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } + if in.PathID != nil { + in, out := &in.PathID, &out.PathID + *out = new(string) + **out = **in + } + if in.PathName != nil { + in, out := &in.PathName, &out.PathName + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProductName != nil { + in, out := &in.ProductName, &out.ProductName + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactName != nil { + in, out := &in.ProvisioningArtifactName, &out.ProvisioningArtifactName + *out = new(string) + **out = **in + } + if in.ProvisioningParameters != nil { + in, out := &in.ProvisioningParameters, &out.ProvisioningParameters + *out = make([]*ProvisioningParameter, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(ProvisioningParameter) + (*in).DeepCopyInto(*out) + } + } + } + if in.ProvisioningPreferences != nil { + in, out := &in.ProvisioningPreferences, &out.ProvisioningPreferences + *out = new(ProvisioningPreferences) + (*in).DeepCopyInto(*out) + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]*Tag, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(Tag) + (*in).DeepCopyInto(*out) + } + } + } + out.CustomProvisionedProductParameters = in.CustomProvisionedProductParameters +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductParameters. +func (in *ProvisionedProductParameters) DeepCopy() *ProvisionedProductParameters { + if in == nil { + return nil + } + out := new(ProvisionedProductParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductSpec) DeepCopyInto(out *ProvisionedProductSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) + in.ForProvider.DeepCopyInto(&out.ForProvider) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductSpec. +func (in *ProvisionedProductSpec) DeepCopy() *ProvisionedProductSpec { + if in == nil { + return nil + } + out := new(ProvisionedProductSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisionedProductStatus) DeepCopyInto(out *ProvisionedProductStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) + in.AtProvider.DeepCopyInto(&out.AtProvider) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisionedProductStatus. +func (in *ProvisionedProductStatus) DeepCopy() *ProvisionedProductStatus { + if in == nil { + return nil + } + out := new(ProvisionedProductStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifact) DeepCopyInto(out *ProvisioningArtifact) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifact. +func (in *ProvisioningArtifact) DeepCopy() *ProvisioningArtifact { + if in == nil { + return nil + } + out := new(ProvisioningArtifact) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifactDetail) DeepCopyInto(out *ProvisioningArtifactDetail) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifactDetail. +func (in *ProvisioningArtifactDetail) DeepCopy() *ProvisioningArtifactDetail { + if in == nil { + return nil + } + out := new(ProvisioningArtifactDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifactParameter) DeepCopyInto(out *ProvisioningArtifactParameter) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.ParameterKey != nil { + in, out := &in.ParameterKey, &out.ParameterKey + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifactParameter. +func (in *ProvisioningArtifactParameter) DeepCopy() *ProvisioningArtifactParameter { + if in == nil { + return nil + } + out := new(ProvisioningArtifactParameter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifactPreferences) DeepCopyInto(out *ProvisioningArtifactPreferences) { + *out = *in + if in.StackSetAccounts != nil { + in, out := &in.StackSetAccounts, &out.StackSetAccounts + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } + if in.StackSetRegions != nil { + in, out := &in.StackSetRegions, &out.StackSetRegions + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifactPreferences. +func (in *ProvisioningArtifactPreferences) DeepCopy() *ProvisioningArtifactPreferences { + if in == nil { + return nil + } + out := new(ProvisioningArtifactPreferences) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifactProperties) DeepCopyInto(out *ProvisioningArtifactProperties) { + *out = *in + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifactProperties. +func (in *ProvisioningArtifactProperties) DeepCopy() *ProvisioningArtifactProperties { + if in == nil { + return nil + } + out := new(ProvisioningArtifactProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningArtifactSummary) DeepCopyInto(out *ProvisioningArtifactSummary) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningArtifactSummary. +func (in *ProvisioningArtifactSummary) DeepCopy() *ProvisioningArtifactSummary { + if in == nil { + return nil + } + out := new(ProvisioningArtifactSummary) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningParameter) DeepCopyInto(out *ProvisioningParameter) { + *out = *in + if in.Key != nil { + in, out := &in.Key, &out.Key + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningParameter. +func (in *ProvisioningParameter) DeepCopy() *ProvisioningParameter { + if in == nil { + return nil + } + out := new(ProvisioningParameter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProvisioningPreferences) DeepCopyInto(out *ProvisioningPreferences) { + *out = *in + if in.StackSetAccounts != nil { + in, out := &in.StackSetAccounts, &out.StackSetAccounts + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } + if in.StackSetFailureToleranceCount != nil { + in, out := &in.StackSetFailureToleranceCount, &out.StackSetFailureToleranceCount + *out = new(int64) + **out = **in + } + if in.StackSetFailureTolerancePercentage != nil { + in, out := &in.StackSetFailureTolerancePercentage, &out.StackSetFailureTolerancePercentage + *out = new(int64) + **out = **in + } + if in.StackSetMaxConcurrencyCount != nil { + in, out := &in.StackSetMaxConcurrencyCount, &out.StackSetMaxConcurrencyCount + *out = new(int64) + **out = **in + } + if in.StackSetMaxConcurrencyPercentage != nil { + in, out := &in.StackSetMaxConcurrencyPercentage, &out.StackSetMaxConcurrencyPercentage + *out = new(int64) + **out = **in + } + if in.StackSetRegions != nil { + in, out := &in.StackSetRegions, &out.StackSetRegions + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProvisioningPreferences. +func (in *ProvisioningPreferences) DeepCopy() *ProvisioningPreferences { + if in == nil { + return nil + } + out := new(ProvisioningPreferences) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecordDetail) DeepCopyInto(out *RecordDetail) { + *out = *in + if in.CreatedTime != nil { + in, out := &in.CreatedTime, &out.CreatedTime + *out = (*in).DeepCopy() + } + if in.LaunchRoleARN != nil { + in, out := &in.LaunchRoleARN, &out.LaunchRoleARN + *out = new(string) + **out = **in + } + if in.PathID != nil { + in, out := &in.PathID, &out.PathID + *out = new(string) + **out = **in + } + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProvisionedProductID != nil { + in, out := &in.ProvisionedProductID, &out.ProvisionedProductID + *out = new(string) + **out = **in + } + if in.ProvisionedProductName != nil { + in, out := &in.ProvisionedProductName, &out.ProvisionedProductName + *out = new(string) + **out = **in + } + if in.ProvisionedProductType != nil { + in, out := &in.ProvisionedProductType, &out.ProvisionedProductType + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.RecordErrors != nil { + in, out := &in.RecordErrors, &out.RecordErrors + *out = make([]*RecordError, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RecordError) + (*in).DeepCopyInto(*out) + } + } + } + if in.RecordID != nil { + in, out := &in.RecordID, &out.RecordID + *out = new(string) + **out = **in + } + if in.RecordTags != nil { + in, out := &in.RecordTags, &out.RecordTags + *out = make([]*RecordTag, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(RecordTag) + (*in).DeepCopyInto(*out) + } + } + } + if in.RecordType != nil { + in, out := &in.RecordType, &out.RecordType + *out = new(string) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } + if in.UpdatedTime != nil { + in, out := &in.UpdatedTime, &out.UpdatedTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecordDetail. +func (in *RecordDetail) DeepCopy() *RecordDetail { + if in == nil { + return nil + } + out := new(RecordDetail) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecordError) DeepCopyInto(out *RecordError) { + *out = *in + if in.Code != nil { + in, out := &in.Code, &out.Code + *out = new(string) + **out = **in + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecordError. +func (in *RecordError) DeepCopy() *RecordError { + if in == nil { + return nil + } + out := new(RecordError) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecordOutput) DeepCopyInto(out *RecordOutput) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.OutputKey != nil { + in, out := &in.OutputKey, &out.OutputKey + *out = new(string) + **out = **in + } + if in.OutputValue != nil { + in, out := &in.OutputValue, &out.OutputValue + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecordOutput. +func (in *RecordOutput) DeepCopy() *RecordOutput { + if in == nil { + return nil + } + out := new(RecordOutput) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RecordTag) DeepCopyInto(out *RecordTag) { + *out = *in + if in.Key != nil { + in, out := &in.Key, &out.Key + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RecordTag. +func (in *RecordTag) DeepCopy() *RecordTag { + if in == nil { + return nil + } + out := new(RecordTag) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceActionAssociation) DeepCopyInto(out *ServiceActionAssociation) { + *out = *in + if in.ProductID != nil { + in, out := &in.ProductID, &out.ProductID + *out = new(string) + **out = **in + } + if in.ProvisioningArtifactID != nil { + in, out := &in.ProvisioningArtifactID, &out.ProvisioningArtifactID + *out = new(string) + **out = **in + } + if in.ServiceActionID != nil { + in, out := &in.ServiceActionID, &out.ServiceActionID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceActionAssociation. +func (in *ServiceActionAssociation) DeepCopy() *ServiceActionAssociation { + if in == nil { + return nil + } + out := new(ServiceActionAssociation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceActionSummary) DeepCopyInto(out *ServiceActionSummary) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceActionSummary. +func (in *ServiceActionSummary) DeepCopy() *ServiceActionSummary { + if in == nil { + return nil + } + out := new(ServiceActionSummary) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StackInstance) DeepCopyInto(out *StackInstance) { + *out = *in + if in.Account != nil { + in, out := &in.Account, &out.Account + *out = new(string) + **out = **in + } + if in.Region != nil { + in, out := &in.Region, &out.Region + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackInstance. +func (in *StackInstance) DeepCopy() *StackInstance { + if in == nil { + return nil + } + out := new(StackInstance) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Tag) DeepCopyInto(out *Tag) { + *out = *in + if in.Key != nil { + in, out := &in.Key, &out.Key + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Tag. +func (in *Tag) DeepCopy() *Tag { + if in == nil { + return nil + } + out := new(Tag) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpdateProvisioningParameter) DeepCopyInto(out *UpdateProvisioningParameter) { + *out = *in + if in.Key != nil { + in, out := &in.Key, &out.Key + *out = new(string) + **out = **in + } + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateProvisioningParameter. +func (in *UpdateProvisioningParameter) DeepCopy() *UpdateProvisioningParameter { + if in == nil { + return nil + } + out := new(UpdateProvisioningParameter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpdateProvisioningPreferences) DeepCopyInto(out *UpdateProvisioningPreferences) { + *out = *in + if in.StackSetAccounts != nil { + in, out := &in.StackSetAccounts, &out.StackSetAccounts + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } + if in.StackSetFailureToleranceCount != nil { + in, out := &in.StackSetFailureToleranceCount, &out.StackSetFailureToleranceCount + *out = new(int64) + **out = **in + } + if in.StackSetFailureTolerancePercentage != nil { + in, out := &in.StackSetFailureTolerancePercentage, &out.StackSetFailureTolerancePercentage + *out = new(int64) + **out = **in + } + if in.StackSetMaxConcurrencyCount != nil { + in, out := &in.StackSetMaxConcurrencyCount, &out.StackSetMaxConcurrencyCount + *out = new(int64) + **out = **in + } + if in.StackSetMaxConcurrencyPercentage != nil { + in, out := &in.StackSetMaxConcurrencyPercentage, &out.StackSetMaxConcurrencyPercentage + *out = new(int64) + **out = **in + } + if in.StackSetRegions != nil { + in, out := &in.StackSetRegions, &out.StackSetRegions + *out = make([]*string, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(string) + **out = **in + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateProvisioningPreferences. +func (in *UpdateProvisioningPreferences) DeepCopy() *UpdateProvisioningPreferences { + if in == nil { + return nil + } + out := new(UpdateProvisioningPreferences) + in.DeepCopyInto(out) + return out +} diff --git a/apis/servicecatalog/v1alpha1/zz_generated.managed.go b/apis/servicecatalog/v1alpha1/zz_generated.managed.go new file mode 100644 index 0000000000..d9e2b96a89 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_generated.managed.go @@ -0,0 +1,87 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by angryjet. DO NOT EDIT. + +package v1alpha1 + +import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + +// GetCondition of this ProvisionedProduct. +func (mg *ProvisionedProduct) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this ProvisionedProduct. +func (mg *ProvisionedProduct) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this ProvisionedProduct. +func (mg *ProvisionedProduct) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this ProvisionedProduct. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *ProvisionedProduct) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetPublishConnectionDetailsTo of this ProvisionedProduct. +func (mg *ProvisionedProduct) GetPublishConnectionDetailsTo() *xpv1.PublishConnectionDetailsTo { + return mg.Spec.PublishConnectionDetailsTo +} + +// GetWriteConnectionSecretToReference of this ProvisionedProduct. +func (mg *ProvisionedProduct) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this ProvisionedProduct. +func (mg *ProvisionedProduct) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this ProvisionedProduct. +func (mg *ProvisionedProduct) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this ProvisionedProduct. +func (mg *ProvisionedProduct) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this ProvisionedProduct. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *ProvisionedProduct) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetPublishConnectionDetailsTo of this ProvisionedProduct. +func (mg *ProvisionedProduct) SetPublishConnectionDetailsTo(r *xpv1.PublishConnectionDetailsTo) { + mg.Spec.PublishConnectionDetailsTo = r +} + +// SetWriteConnectionSecretToReference of this ProvisionedProduct. +func (mg *ProvisionedProduct) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} diff --git a/apis/servicecatalog/v1alpha1/zz_generated.managedlist.go b/apis/servicecatalog/v1alpha1/zz_generated.managedlist.go new file mode 100644 index 0000000000..8454d50a75 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_generated.managedlist.go @@ -0,0 +1,30 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by angryjet. DO NOT EDIT. + +package v1alpha1 + +import resource "github.com/crossplane/crossplane-runtime/pkg/resource" + +// GetItems of this ProvisionedProductList. +func (l *ProvisionedProductList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} diff --git a/apis/servicecatalog/v1alpha1/zz_groupversion_info.go b/apis/servicecatalog/v1alpha1/zz_groupversion_info.go new file mode 100644 index 0000000000..bf2b38a88b --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_groupversion_info.go @@ -0,0 +1,41 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +// Package type metadata. +const ( + CRDGroup = "servicecatalog.aws.crossplane.io" + CRDVersion = "v1alpha1" +) + +var ( + // GroupVersion is the API Group Version used to register the objects + GroupVersion = schema.GroupVersion{Group: CRDGroup, Version: CRDVersion} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/servicecatalog/v1alpha1/zz_provisioned_product.go b/apis/servicecatalog/v1alpha1/zz_provisioned_product.go new file mode 100644 index 0000000000..1a38210b62 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_provisioned_product.go @@ -0,0 +1,191 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package v1alpha1 + +import ( + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// ProvisionedProductParameters defines the desired state of ProvisionedProduct +type ProvisionedProductParameters struct { + // Region is which region the ProvisionedProduct will be created. + // +kubebuilder:validation:Required + Region string `json:"region"` + // The language code. + // + // * en - English (default) + // + // * jp - Japanese + // + // * zh - Chinese + AcceptLanguage *string `json:"acceptLanguage,omitempty"` + // A user-friendly name for the provisioned product. This value must be unique + // for the Amazon Web Services account and cannot be updated after the product + // is provisioned. + // +kubebuilder:validation:Required + Name *string `json:"name"` + // Passed to CloudFormation. The SNS topic ARNs to which to publish stack-related + // events. + NotificationARNs []*string `json:"notificationARNs,omitempty"` + // The path identifier of the product. This value is optional if the product + // has a default path, and required if the product has more than one path. To + // list the paths for a product, use ListLaunchPaths. You must provide the name + // or ID, but not both. + PathID *string `json:"pathID,omitempty"` + // The name of the path. You must provide the name or ID, but not both. + PathName *string `json:"pathName,omitempty"` + // The product identifier. You must provide the name or ID, but not both. + ProductID *string `json:"productID,omitempty"` + // The name of the product. You must provide the name or ID, but not both. + ProductName *string `json:"productName,omitempty"` + // The identifier of the provisioning artifact. You must provide the name or + // ID, but not both. + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + // The name of the provisioning artifact. You must provide the name or ID, but + // not both. + ProvisioningArtifactName *string `json:"provisioningArtifactName,omitempty"` + // Parameters specified by the administrator that are required for provisioning + // the product. + ProvisioningParameters []*ProvisioningParameter `json:"provisioningParameters,omitempty"` + // An object that contains information about the provisioning preferences for + // a stack set. + ProvisioningPreferences *ProvisioningPreferences `json:"provisioningPreferences,omitempty"` + // One or more tags. + Tags []*Tag `json:"tags,omitempty"` + CustomProvisionedProductParameters `json:",inline"` +} + +// ProvisionedProductSpec defines the desired state of ProvisionedProduct +type ProvisionedProductSpec struct { + xpv1.ResourceSpec `json:",inline"` + ForProvider ProvisionedProductParameters `json:"forProvider"` +} + +// ProvisionedProductObservation defines the observed state of ProvisionedProduct +type ProvisionedProductObservation struct { + // The ARN of the provisioned product. + ARN *string `json:"arn,omitempty"` + // The UTC time stamp of the creation time. + CreatedTime *metav1.Time `json:"createdTime,omitempty"` + // The record identifier of the last request performed on this provisioned product + // of the following types: + // + // * ProvisionedProduct + // + // * UpdateProvisionedProduct + // + // * ExecuteProvisionedProductPlan + // + // * TerminateProvisionedProduct + LastProvisioningRecordID *string `json:"lastProvisioningRecordID,omitempty"` + // The ARN of the launch role associated with the provisioned product. + LaunchRoleARN *string `json:"launchRoleARN,omitempty"` + + Outputs map[string]*RecordOutput `json:"outputs,omitempty"` + // The identifier of the provisioned product. + ProvisionedProductID *string `json:"provisionedProductID,omitempty"` + // The type of provisioned product. The supported values are CFN_STACK and CFN_STACKSET. + ProvisionedProductType *string `json:"provisionedProductType,omitempty"` + // The errors that occurred. + RecordErrors []*RecordError `json:"recordErrors,omitempty"` + // The identifier of the record. + RecordID *string `json:"recordID,omitempty"` + // One or more tags. + RecordTags []*RecordTag `json:"recordTags,omitempty"` + // The record type. + // + // * PROVISION_PRODUCT + // + // * UPDATE_PROVISIONED_PRODUCT + // + // * TERMINATE_PROVISIONED_PRODUCT + RecordType *string `json:"recordType,omitempty"` + // The current status of the provisioned product. + // + // * AVAILABLE - Stable state, ready to perform any operation. The most recent + // operation succeeded and completed. + // + // * UNDER_CHANGE - Transitive state. Operations performed might not have + // valid results. Wait for an AVAILABLE status before performing operations. + // + // * TAINTED - Stable state, ready to perform any operation. The stack has + // completed the requested operation but is not exactly what was requested. + // For example, a request to update to a new version failed and the stack + // rolled back to the current version. + // + // * ERROR - An unexpected error occurred. The provisioned product exists + // but the stack is not running. For example, CloudFormation received a parameter + // value that was not valid and could not launch the stack. + // + // * PLAN_IN_PROGRESS - Transitive state. The plan operations were performed + // to provision a new product, but resources have not yet been created. After + // reviewing the list of resources to be created, execute the plan. Wait + // for an AVAILABLE status before performing operations. + Status *string `json:"status,omitempty"` + // The current status message of the provisioned product. + StatusMessage *string `json:"statusMessage,omitempty"` + // The time when the record was last updated. + UpdatedTime *metav1.Time `json:"updatedTime,omitempty"` +} + +// ProvisionedProductStatus defines the observed state of ProvisionedProduct. +type ProvisionedProductStatus struct { + xpv1.ResourceStatus `json:",inline"` + AtProvider ProvisionedProductObservation `json:"atProvider,omitempty"` +} + +// +kubebuilder:object:root=true + +// ProvisionedProduct is the Schema for the ProvisionedProducts API +// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" +// +kubebuilder:printcolumn:name="EXTERNAL-NAME",type="string",JSONPath=".metadata.annotations.crossplane\\.io/external-name" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,aws} +type ProvisionedProduct struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec ProvisionedProductSpec `json:"spec"` + Status ProvisionedProductStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ProvisionedProductList contains a list of ProvisionedProducts +type ProvisionedProductList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ProvisionedProduct `json:"items"` +} + +// Repository type metadata. +var ( + ProvisionedProductKind = "ProvisionedProduct" + ProvisionedProductGroupKind = schema.GroupKind{Group: CRDGroup, Kind: ProvisionedProductKind}.String() + ProvisionedProductKindAPIVersion = ProvisionedProductKind + "." + GroupVersion.String() + ProvisionedProductGroupVersionKind = GroupVersion.WithKind(ProvisionedProductKind) +) + +func init() { + SchemeBuilder.Register(&ProvisionedProduct{}, &ProvisionedProductList{}) +} diff --git a/apis/servicecatalog/v1alpha1/zz_types.go b/apis/servicecatalog/v1alpha1/zz_types.go new file mode 100644 index 0000000000..3599661801 --- /dev/null +++ b/apis/servicecatalog/v1alpha1/zz_types.go @@ -0,0 +1,330 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Hack to avoid import errors during build... +var ( + _ = &metav1.Time{} +) + +// +kubebuilder:skipversion +type CloudWatchDashboard struct { + Name *string `json:"name,omitempty"` +} + +// +kubebuilder:skipversion +type ConstraintDetail struct { + ConstraintID *string `json:"constraintID,omitempty"` + + Owner *string `json:"owner,omitempty"` + + PortfolioID *string `json:"portfolioID,omitempty"` + + ProductID *string `json:"productID,omitempty"` +} + +// +kubebuilder:skipversion +type FailedServiceActionAssociation struct { + ProductID *string `json:"productID,omitempty"` + + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + + ServiceActionID *string `json:"serviceActionID,omitempty"` +} + +// +kubebuilder:skipversion +type LastSync struct { + LastSuccessfulSyncProvisioningArtifactID *string `json:"lastSuccessfulSyncProvisioningArtifactID,omitempty"` +} + +// +kubebuilder:skipversion +type LaunchPath struct { + ID *string `json:"id,omitempty"` +} + +// +kubebuilder:skipversion +type LaunchPathSummary struct { + ID *string `json:"id,omitempty"` + + Tags []*Tag `json:"tags,omitempty"` +} + +// +kubebuilder:skipversion +type PortfolioDetail struct { + DisplayName *string `json:"displayName,omitempty"` + + ID *string `json:"id,omitempty"` +} + +// +kubebuilder:skipversion +type PortfolioShareDetail struct { + PrincipalID *string `json:"principalID,omitempty"` +} + +// +kubebuilder:skipversion +type ProductViewDetail struct { + CreatedTime *metav1.Time `json:"createdTime,omitempty"` +} + +// +kubebuilder:skipversion +type ProductViewSummary struct { + ID *string `json:"id,omitempty"` + + Name *string `json:"name,omitempty"` + + ProductID *string `json:"productID,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisionedProductAttribute struct { + ARN *string `json:"arn,omitempty"` + + CreatedTime *metav1.Time `json:"createdTime,omitempty"` + + ID *string `json:"id,omitempty"` + + IdempotencyToken *string `json:"idempotencyToken,omitempty"` + + LastProvisioningRecordID *string `json:"lastProvisioningRecordID,omitempty"` + + LastRecordID *string `json:"lastRecordID,omitempty"` + + LastSuccessfulProvisioningRecordID *string `json:"lastSuccessfulProvisioningRecordID,omitempty"` + + Name *string `json:"name,omitempty"` + + ProductID *string `json:"productID,omitempty"` + + ProductName *string `json:"productName,omitempty"` + + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + + ProvisioningArtifactName *string `json:"provisioningArtifactName,omitempty"` + + Status *string `json:"status,omitempty"` + + StatusMessage *string `json:"statusMessage,omitempty"` + + Tags []*Tag `json:"tags,omitempty"` + + Type *string `json:"type_,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisionedProductDetail struct { + ARN *string `json:"arn,omitempty"` + + CreatedTime *metav1.Time `json:"createdTime,omitempty"` + + ID *string `json:"id,omitempty"` + + IdempotencyToken *string `json:"idempotencyToken,omitempty"` + + LastProvisioningRecordID *string `json:"lastProvisioningRecordID,omitempty"` + + LastRecordID *string `json:"lastRecordID,omitempty"` + + LastSuccessfulProvisioningRecordID *string `json:"lastSuccessfulProvisioningRecordID,omitempty"` + + LaunchRoleARN *string `json:"launchRoleARN,omitempty"` + + Name *string `json:"name,omitempty"` + + ProductID *string `json:"productID,omitempty"` + + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + + Status *string `json:"status,omitempty"` + + StatusMessage *string `json:"statusMessage,omitempty"` + + Type *string `json:"type_,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifact struct { + ID *string `json:"id,omitempty"` + + Name *string `json:"name,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifactDetail struct { + Description *string `json:"description,omitempty"` + + ID *string `json:"id,omitempty"` + + Name *string `json:"name,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifactParameter struct { + Description *string `json:"description,omitempty"` + + ParameterKey *string `json:"parameterKey,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifactPreferences struct { + StackSetAccounts []*string `json:"stackSetAccounts,omitempty"` + + StackSetRegions []*string `json:"stackSetRegions,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifactProperties struct { + Name *string `json:"name,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningArtifactSummary struct { + ID *string `json:"id,omitempty"` + + Name *string `json:"name,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningParameter struct { + Key *string `json:"key,omitempty"` + + Value *string `json:"value,omitempty"` +} + +// +kubebuilder:skipversion +type ProvisioningPreferences struct { + StackSetAccounts []*string `json:"stackSetAccounts,omitempty"` + + StackSetFailureToleranceCount *int64 `json:"stackSetFailureToleranceCount,omitempty"` + + StackSetFailureTolerancePercentage *int64 `json:"stackSetFailureTolerancePercentage,omitempty"` + + StackSetMaxConcurrencyCount *int64 `json:"stackSetMaxConcurrencyCount,omitempty"` + + StackSetMaxConcurrencyPercentage *int64 `json:"stackSetMaxConcurrencyPercentage,omitempty"` + + StackSetRegions []*string `json:"stackSetRegions,omitempty"` +} + +// +kubebuilder:skipversion +type RecordDetail struct { + CreatedTime *metav1.Time `json:"createdTime,omitempty"` + + LaunchRoleARN *string `json:"launchRoleARN,omitempty"` + + PathID *string `json:"pathID,omitempty"` + + ProductID *string `json:"productID,omitempty"` + + ProvisionedProductID *string `json:"provisionedProductID,omitempty"` + + ProvisionedProductName *string `json:"provisionedProductName,omitempty"` + + ProvisionedProductType *string `json:"provisionedProductType,omitempty"` + + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + + RecordErrors []*RecordError `json:"recordErrors,omitempty"` + + RecordID *string `json:"recordID,omitempty"` + + RecordTags []*RecordTag `json:"recordTags,omitempty"` + + RecordType *string `json:"recordType,omitempty"` + + Status *string `json:"status,omitempty"` + + UpdatedTime *metav1.Time `json:"updatedTime,omitempty"` +} + +// +kubebuilder:skipversion +type RecordError struct { + Code *string `json:"code,omitempty"` + + Description *string `json:"description,omitempty"` +} + +// +kubebuilder:skipversion +type RecordOutput struct { + Description *string `json:"description,omitempty"` + + OutputKey *string `json:"outputKey,omitempty"` + + OutputValue *string `json:"outputValue,omitempty"` +} + +// +kubebuilder:skipversion +type RecordTag struct { + Key *string `json:"key,omitempty"` + + Value *string `json:"value,omitempty"` +} + +// +kubebuilder:skipversion +type ServiceActionAssociation struct { + ProductID *string `json:"productID,omitempty"` + + ProvisioningArtifactID *string `json:"provisioningArtifactID,omitempty"` + + ServiceActionID *string `json:"serviceActionID,omitempty"` +} + +// +kubebuilder:skipversion +type ServiceActionSummary struct { + ID *string `json:"id,omitempty"` +} + +// +kubebuilder:skipversion +type StackInstance struct { + Account *string `json:"account,omitempty"` + + Region *string `json:"region,omitempty"` +} + +// +kubebuilder:skipversion +type Tag struct { + Key *string `json:"key,omitempty"` + + Value *string `json:"value,omitempty"` +} + +// +kubebuilder:skipversion +type UpdateProvisioningParameter struct { + Key *string `json:"key,omitempty"` + + Value *string `json:"value,omitempty"` +} + +// +kubebuilder:skipversion +type UpdateProvisioningPreferences struct { + StackSetAccounts []*string `json:"stackSetAccounts,omitempty"` + + StackSetFailureToleranceCount *int64 `json:"stackSetFailureToleranceCount,omitempty"` + + StackSetFailureTolerancePercentage *int64 `json:"stackSetFailureTolerancePercentage,omitempty"` + + StackSetMaxConcurrencyCount *int64 `json:"stackSetMaxConcurrencyCount,omitempty"` + + StackSetMaxConcurrencyPercentage *int64 `json:"stackSetMaxConcurrencyPercentage,omitempty"` + + StackSetRegions []*string `json:"stackSetRegions,omitempty"` +} diff --git a/examples/servicecatalog/provisionedproduct.yaml b/examples/servicecatalog/provisionedproduct.yaml new file mode 100644 index 0000000000..ab1e3bdeec --- /dev/null +++ b/examples/servicecatalog/provisionedproduct.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: servicecatalog.aws.crossplane.io/v1alpha1 +kind: ProvisionedProduct +metadata: + name: awesome-s3-bucket +spec: + forProvider: + name: awesome-s3-bucket + region: eu-central-1 + productID: prod-ebjgywwm4en3a + provisioningArtifactID: pa-kvojrsl2sygly + provisioningParameters: + - key: BucketName + value: "awesome-s3-bucket" + - key: BucketVersioning + value: "enabled" + - key: TransferAcceleration + value: "suspended" + - key: EncryptionType + value: "SSE-KMS" + - key: KMSArn + value: "none" + - key: EventNotificationTarget + value: "none" + - key: EventNotificationEvents + value: "s3:ObjectCreated:Put" + - key: EventNotificationTargetARN + value: "none" + - key: SQSURL + value: "none" + - key: BucketObjectLockEnabled + value: "false" + - key: DefaultRetentionSettings + value: "none" + - key: scBackupPlanDaily + value: "disabled" + - key: scBackupPlanHourly + value: "disabled" + - key: scBackupPlanHourlyContinuous + value: "disabled" + - key: scBackupPlanMonthly + value: "disabled" + - key: scBackupPlanWeekly + value: "disabled" + providerConfigRef: + name: provider-aws diff --git a/go.mod b/go.mod index 82688c612f..734580bbff 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,12 @@ go 1.18 require ( github.com/aws/aws-sdk-go v1.44.174 - github.com/aws/aws-sdk-go-v2 v1.16.16 + github.com/aws/aws-sdk-go-v2 v1.19.0 github.com/aws/aws-sdk-go-v2/config v1.11.1 github.com/aws/aws-sdk-go-v2/credentials v1.6.5 github.com/aws/aws-sdk-go-v2/service/acm v1.10.0 github.com/aws/aws-sdk-go-v2/service/acmpca v1.12.0 + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.30.1 github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.17.3 github.com/aws/aws-sdk-go-v2/service/ec2 v1.26.0 github.com/aws/aws-sdk-go-v2/service/ecr v1.12.0 @@ -26,7 +27,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sns v1.13.0 github.com/aws/aws-sdk-go-v2/service/sqs v1.14.0 github.com/aws/aws-sdk-go-v2/service/sts v1.12.0 - github.com/aws/smithy-go v1.13.3 + github.com/aws/smithy-go v1.13.5 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df github.com/crossplane/crossplane-runtime v0.20.0-rc.0.0.20230320143010-c424c4aca5b0 github.com/crossplane/crossplane-tools v0.0.0-20220310165030-1f43fc12793e @@ -57,8 +58,8 @@ require ( github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 // indirect diff --git a/go.sum b/go.sum index 497ebcb091..f3f1fdebf0 100644 --- a/go.sum +++ b/go.sum @@ -59,8 +59,9 @@ github.com/aws/aws-sdk-go-v2 v1.10.0/go.mod h1:U/EyyVvKtzmFeQQcca7eBotKdlpcP2zzU github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= github.com/aws/aws-sdk-go-v2 v1.16.2/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= github.com/aws/aws-sdk-go-v2 v1.16.7/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw= -github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= +github.com/aws/aws-sdk-go-v2 v1.19.0 h1:klAT+y3pGFBU/qVf1uzwttpBbiuozJYWzNLHioyDJ+k= +github.com/aws/aws-sdk-go-v2 v1.19.0/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= github.com/aws/aws-sdk-go-v2/config v1.11.1 h1:KXSjb7ZMLRtjxClFptukTYibiOqJS9NwBO+9WD3UMto= @@ -72,19 +73,23 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2/go.mod h1:dF2F6tXEOgmW5X1ZF github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.9/go.mod h1:AnVH5pvai0pAF4lXRq0bmhbes1u9R8wTE+g+183bZNM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.14/go.mod h1:kdjrMwHwrC3+FsKhNcCMJ7tUVj/8uSD5CZXeQ4wV6fM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23 h1:s4g/wnzMf+qepSNgTvaQQHNxyMLKSawNhKCPNy++2xY= github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.23/go.mod h1:2DFxAQ9pfIRy0imBCJv+vZ2X6RKxves6fbnEuSry6b4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35 h1:hMUCiE3Zi5AHrRNGf5j985u0WyqI6r2NULhUfo0N/No= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.35/go.mod h1:ipR5PvpSPqIqL5Mi82BxLnfMkHVbmco8kUwO2xrCi0M= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.3/go.mod h1:ssOhaLpRlh88H3UmEcsBoVKq309quMvm3Ds8e9d4eJM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.8/go.mod h1:ZIV8GYoC6WLBW5KGs+o4rsc65/ozd+eQ0L31XF5VDwk= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17 h1:/K482T5A3623WJgWT8w1yRAFK4RzGzEl7y39yhtn9eA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.17/go.mod h1:pRwaTYCJemADaqCbUAxltMoHKata7hmB5PjEXeu0kfg= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29 h1:yOpYx+FTBdpk/g+sBU6Cb1H0U/TLEcYYp66mYqsPpcc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.29/go.mod h1:M/eUABlDbw2uVrdAn+UsI6M727qp2fxkp8K0ejcBDUY= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2 h1:IQup8Q6lorXeiA/rK72PeToWoWK8h7VAPgHNWdSrtgE= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2/go.mod h1:VITe/MdW6EMXPb0o0txu/fsonXbMHUU2OC2Qp7ivU4o= github.com/aws/aws-sdk-go-v2/service/acm v1.10.0 h1:h00NJuGEVi36k1BkVMpJQRRyye2SaPaCv2tQD0rm/uE= github.com/aws/aws-sdk-go-v2/service/acm v1.10.0/go.mod h1:I43heu2RNNVqzR8q069JCllVMVgGRlDfNHRThRD70Kc= github.com/aws/aws-sdk-go-v2/service/acmpca v1.12.0 h1:JL8J0ji+JK0t7JUUNtZg8atEUThdzk0KCgXY4a+7UXE= github.com/aws/aws-sdk-go-v2/service/acmpca v1.12.0/go.mod h1:AcCVrQKCGEWqfC1837nKJW2H5GdYseVfmGwhDjtcX3M= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.30.1 h1:MHKSdt+ECxOWD98MYj/Ocy4GS8GgAjgEDSPaiTaXP6U= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.30.1/go.mod h1:laKFhtn8EH6gcPl7KEQ4kcuSYcQF1tqUm82ENxMwlMk= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.17.3 h1:xtwjqxVDO9tAmoUXVfJyMKFLVJlosjKrFLLuW4V8VO0= github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider v1.17.3/go.mod h1:flSX+qf2r/mLgwTavyT/Gjs4dFtHcBmjMcVp/AqpSgc= github.com/aws/aws-sdk-go-v2/service/ec2 v1.26.0 h1:Q++veaxis1Dg7is9yi+aEPsIBRAgdkUxoIvyud7jOyo= @@ -131,8 +136,9 @@ github.com/aws/smithy-go v1.8.1/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= -github.com/aws/smithy-go v1.13.3 h1:l7LYxGuzK6/K+NzJ2mC+VvLUbae0sL3bXU//04MkmnA= github.com/aws/smithy-go v1.13.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= +github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= diff --git a/package/crds/servicecatalog.aws.crossplane.io_provisionedproducts.yaml b/package/crds/servicecatalog.aws.crossplane.io_provisionedproducts.yaml new file mode 100644 index 0000000000..5aee6ae0d2 --- /dev/null +++ b/package/crds/servicecatalog.aws.crossplane.io_provisionedproducts.yaml @@ -0,0 +1,472 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.1 + creationTimestamp: null + name: provisionedproducts.servicecatalog.aws.crossplane.io +spec: + group: servicecatalog.aws.crossplane.io + names: + categories: + - crossplane + - managed + - aws + kind: ProvisionedProduct + listKind: ProvisionedProductList + plural: provisionedproducts + singular: provisionedproduct + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .metadata.annotations.crossplane\.io/external-name + name: EXTERNAL-NAME + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ProvisionedProduct is the Schema for the ProvisionedProducts + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ProvisionedProductSpec defines the desired state of ProvisionedProduct + properties: + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying + external when this managed resource is deleted - either "Delete" + or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + forProvider: + description: ProvisionedProductParameters defines the desired state + of ProvisionedProduct + properties: + acceptLanguage: + description: "The language code. \n * en - English (default) \n + * jp - Japanese \n * zh - Chinese" + type: string + name: + description: A user-friendly name for the provisioned product. + This value must be unique for the Amazon Web Services account + and cannot be updated after the product is provisioned. + type: string + notificationARNs: + description: Passed to CloudFormation. The SNS topic ARNs to which + to publish stack-related events. + items: + type: string + type: array + pathID: + description: The path identifier of the product. This value is + optional if the product has a default path, and required if + the product has more than one path. To list the paths for a + product, use ListLaunchPaths. You must provide the name or ID, + but not both. + type: string + pathName: + description: The name of the path. You must provide the name or + ID, but not both. + type: string + productID: + description: The product identifier. You must provide the name + or ID, but not both. + type: string + productName: + description: The name of the product. You must provide the name + or ID, but not both. + type: string + provisioningArtifactID: + description: The identifier of the provisioning artifact. You + must provide the name or ID, but not both. + type: string + provisioningArtifactName: + description: The name of the provisioning artifact. You must provide + the name or ID, but not both. + type: string + provisioningParameters: + description: Parameters specified by the administrator that are + required for provisioning the product. + items: + properties: + key: + type: string + value: + type: string + type: object + type: array + provisioningPreferences: + description: An object that contains information about the provisioning + preferences for a stack set. + properties: + stackSetAccounts: + items: + type: string + type: array + stackSetFailureToleranceCount: + format: int64 + type: integer + stackSetFailureTolerancePercentage: + format: int64 + type: integer + stackSetMaxConcurrencyCount: + format: int64 + type: integer + stackSetMaxConcurrencyPercentage: + format: int64 + type: integer + stackSetRegions: + items: + type: string + type: array + type: object + region: + description: Region is which region the ProvisionedProduct will + be created. + type: string + tags: + description: One or more tags. + items: + properties: + key: + type: string + value: + type: string + type: object + type: array + required: + - name + - region + type: object + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that + will be used to create, observe, update, and delete this managed + resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of this + reference is required. The default is 'Required', which + means the reconcile will fail if the reference cannot be + resolved. 'Optional' means this reference will be a no-op + if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will attempt + to resolve the reference only when the corresponding field + is not present. Use 'Always' to resolve the reference on + every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be + used to create, observe, update, and delete this managed resource. + Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of this + reference is required. The default is 'Required', which + means the reconcile will fail if the reference cannot be + resolved. 'Optional' means this reference will be a no-op + if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will attempt + to resolve the reference only when the corresponding field + is not present. Use 'Always' to resolve the reference on + every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + publishConnectionDetailsTo: + description: PublishConnectionDetailsTo specifies the connection secret + config which contains a name, metadata and a reference to secret + store config to which any connection details for this managed resource + should be written. Connection details frequently include the endpoint, + username, and password required to connect to the managed resource. + properties: + configRef: + default: + name: default + description: SecretStoreConfigRef specifies which secret store + config should be used for this ConnectionSecret. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of + this reference is required. The default is 'Required', + which means the reconcile will fail if the reference + cannot be resolved. 'Optional' means this reference + will be a no-op if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will + attempt to resolve the reference only when the corresponding + field is not present. Use 'Always' to resolve the reference + on every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + metadata: + description: Metadata is the metadata for connection secret. + properties: + annotations: + additionalProperties: + type: string + description: Annotations are the annotations to be added to + connection secret. - For Kubernetes secrets, this will be + used as "metadata.annotations". - It is up to Secret Store + implementation for others store types. + type: object + labels: + additionalProperties: + type: string + description: Labels are the labels/tags to be added to connection + secret. - For Kubernetes secrets, this will be used as "metadata.labels". + - It is up to Secret Store implementation for others store + types. + type: object + type: + description: Type is the SecretType for the connection secret. + - Only valid for Kubernetes Secret Stores. + type: string + type: object + name: + description: Name is the name of the connection secret. + type: string + required: + - name + type: object + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace + and name of a Secret to which any connection details for this managed + resource should be written. Connection details frequently include + the endpoint, username, and password required to connect to the + managed resource. This field is planned to be replaced in a future + release in favor of PublishConnectionDetailsTo. Currently, both + could be set independently and connection details would be published + to both without affecting each other. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - forProvider + type: object + status: + description: ProvisionedProductStatus defines the observed state of ProvisionedProduct. + properties: + atProvider: + description: ProvisionedProductObservation defines the observed state + of ProvisionedProduct + properties: + arn: + description: The ARN of the provisioned product. + type: string + createdTime: + description: The UTC time stamp of the creation time. + format: date-time + type: string + lastProvisioningRecordID: + description: "The record identifier of the last request performed + on this provisioned product of the following types: \n * ProvisionedProduct + \n * UpdateProvisionedProduct \n * ExecuteProvisionedProductPlan + \n * TerminateProvisionedProduct" + type: string + launchRoleARN: + description: The ARN of the launch role associated with the provisioned + product. + type: string + outputs: + additionalProperties: + properties: + description: + type: string + outputKey: + type: string + outputValue: + type: string + type: object + type: object + provisionedProductID: + description: The identifier of the provisioned product. + type: string + provisionedProductType: + description: The type of provisioned product. The supported values + are CFN_STACK and CFN_STACKSET. + type: string + recordErrors: + description: The errors that occurred. + items: + properties: + code: + type: string + description: + type: string + type: object + type: array + recordID: + description: The identifier of the record. + type: string + recordTags: + description: One or more tags. + items: + properties: + key: + type: string + value: + type: string + type: object + type: array + recordType: + description: "The record type. \n * PROVISION_PRODUCT \n * UPDATE_PROVISIONED_PRODUCT + \n * TERMINATE_PROVISIONED_PRODUCT" + type: string + status: + description: "The current status of the provisioned product. \n + * AVAILABLE - Stable state, ready to perform any operation. + The most recent operation succeeded and completed. \n * UNDER_CHANGE + - Transitive state. Operations performed might not have valid + results. Wait for an AVAILABLE status before performing operations. + \n * TAINTED - Stable state, ready to perform any operation. + The stack has completed the requested operation but is not exactly + what was requested. For example, a request to update to a new + version failed and the stack rolled back to the current version. + \n * ERROR - An unexpected error occurred. The provisioned product + exists but the stack is not running. For example, CloudFormation + received a parameter value that was not valid and could not + launch the stack. \n * PLAN_IN_PROGRESS - Transitive state. + The plan operations were performed to provision a new product, + but resources have not yet been created. After reviewing the + list of resources to be created, execute the plan. Wait for + an AVAILABLE status before performing operations." + type: string + statusMessage: + description: The current status message of the provisioned product. + type: string + updatedTime: + description: The time when the record was last updated. + format: date-time + type: string + type: object + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/pkg/clients/servicecatalog/fake/fake.go b/pkg/clients/servicecatalog/fake/fake.go new file mode 100644 index 0000000000..52db0af69b --- /dev/null +++ b/pkg/clients/servicecatalog/fake/fake.go @@ -0,0 +1,48 @@ +/* +Copyright 2023 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fake + +import ( + cfsdkv2types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + + clientset "github.com/crossplane-contrib/provider-aws/pkg/clients/servicecatalog" +) + +var _ clientset.Client = (*MockCustomServiceCatalogClient)(nil) + +// MockCustomServiceCatalogClient is a type that implements all the methods for Client interface +type MockCustomServiceCatalogClient struct { + MockGetCloudformationStackParameters func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) + MockGetProvisionedProductOutputs func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) + MockDescribeRecord func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) +} + +// GetCloudformationStackParameters mocks GetCloudformationStackParameters method +func (m *MockCustomServiceCatalogClient) GetCloudformationStackParameters(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return m.MockGetCloudformationStackParameters(provisionedProductOutputs) +} + +// GetProvisionedProductOutputs mock GetProvisionedProductOutputs method +func (m *MockCustomServiceCatalogClient) GetProvisionedProductOutputs(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return m.MockGetProvisionedProductOutputs(getPPInput) +} + +// DescribeRecord mocks DescribeRecord method +func (m *MockCustomServiceCatalogClient) DescribeRecord(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return m.MockDescribeRecord(describeRecordInput) +} diff --git a/pkg/clients/servicecatalog/servicecatalog.go b/pkg/clients/servicecatalog/servicecatalog.go new file mode 100644 index 0000000000..2162f930f8 --- /dev/null +++ b/pkg/clients/servicecatalog/servicecatalog.go @@ -0,0 +1,82 @@ +/* +Copyright 2023 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package servicecatalog + +import ( + "context" + "errors" + + cfsdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudformation" + cfsdkv2types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + svcsdkapi "github.com/aws/aws-sdk-go/service/servicecatalog/servicecatalogiface" +) + +const ( + cloudformationArnOutputName = "CloudformationStackARN" + errCloudformationStackArnNotFound = "provisioned product outputs do not contain cloudformation stack arn" +) + +// Client represents a custom client to retrieve information from AWS related to service catalog or cloud formation as resource behind the provisioned product +type Client interface { + GetCloudformationStackParameters([]*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) + GetProvisionedProductOutputs(*svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) + DescribeRecord(*svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) +} + +// CustomServiceCatalogClient is the implementation of a Client +type CustomServiceCatalogClient struct { + CfClient *cfsdkv2.Client + Client svcsdkapi.ServiceCatalogAPI +} + +// GetCloudformationStackParameters retrieves parameters from cloudformation stack based on outputs from provisioned product +func (c *CustomServiceCatalogClient) GetCloudformationStackParameters(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + describeCfStacksInput := cfsdkv2.DescribeStacksInput{} + for i, output := range provisionedProductOutputs { + if *output.OutputKey == cloudformationArnOutputName { + describeCfStacksInput.StackName = output.OutputValue + break + } + if i+1 == len(provisionedProductOutputs) { + return []cfsdkv2types.Parameter{}, errors.New(errCloudformationStackArnNotFound) + } + } + describeCfStacksOutput, err := c.CfClient.DescribeStacks(context.TODO(), &describeCfStacksInput) + if err != nil { + return []cfsdkv2types.Parameter{}, err + } + return describeCfStacksOutput.Stacks[0].Parameters, nil +} + +// GetProvisionedProductOutputs is wrapped (*ServiceCatalog) GetProvisionedProductOutputs from github.com/aws/aws-sdk-go/service/servicecatalog +func (c *CustomServiceCatalogClient) GetProvisionedProductOutputs(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + getPPOutput, err := c.Client.GetProvisionedProductOutputs(getPPInput) + if err != nil { + return getPPOutput, err + } + return getPPOutput, nil +} + +// DescribeRecord is wrapped (*ServiceCatalog) DescribeRecord from github.com/aws/aws-sdk-go/service/servicecatalog +func (c *CustomServiceCatalogClient) DescribeRecord(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + describeRecordOutput, err := c.Client.DescribeRecord(describeRecordInput) + if err != nil { + return describeRecordOutput, err + } + return describeRecordOutput, nil +} diff --git a/pkg/controller/aws.go b/pkg/controller/aws.go index 0db5fe37a7..1ef47523e7 100644 --- a/pkg/controller/aws.go +++ b/pkg/controller/aws.go @@ -172,6 +172,7 @@ import ( "github.com/crossplane-contrib/provider-aws/pkg/controller/s3" "github.com/crossplane-contrib/provider-aws/pkg/controller/s3/bucketpolicy" "github.com/crossplane-contrib/provider-aws/pkg/controller/secretsmanager/secret" + "github.com/crossplane-contrib/provider-aws/pkg/controller/servicecatalog/provisionedproduct" "github.com/crossplane-contrib/provider-aws/pkg/controller/servicediscovery/httpnamespace" "github.com/crossplane-contrib/provider-aws/pkg/controller/servicediscovery/privatednsnamespace" "github.com/crossplane-contrib/provider-aws/pkg/controller/servicediscovery/publicdnsnamespace" @@ -352,6 +353,7 @@ func Setup(mgr ctrl.Manager, o controller.Options) error { optiongroup.SetupOptionGroup, autoscalinggroup.SetupAutoScalingGroup, servicediscoveryservice.SetupService, + provisionedproduct.SetupProvisionedProduct, } { if err := setup(mgr, o); err != nil { return err diff --git a/pkg/controller/servicecatalog/provisionedproduct/setup.go b/pkg/controller/servicecatalog/provisionedproduct/setup.go new file mode 100644 index 0000000000..393111b172 --- /dev/null +++ b/pkg/controller/servicecatalog/provisionedproduct/setup.go @@ -0,0 +1,265 @@ +/* +Copyright 2023 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provisionedproduct + +import ( + "context" + "errors" + "fmt" + "math/rand" + "reflect" + "strings" + "sync" + "time" + + awsconfig "github.com/aws/aws-sdk-go-v2/config" + cfsdkv2 "github.com/aws/aws-sdk-go-v2/service/cloudformation" + cfsdkv2types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/connection" + "github.com/crossplane/crossplane-runtime/pkg/controller" + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + + svcapitypes "github.com/crossplane-contrib/provider-aws/apis/servicecatalog/v1alpha1" + "github.com/crossplane-contrib/provider-aws/apis/v1alpha1" + aws "github.com/crossplane-contrib/provider-aws/pkg/clients" + awsclient "github.com/crossplane-contrib/provider-aws/pkg/clients" + clientset "github.com/crossplane-contrib/provider-aws/pkg/clients/servicecatalog" + "github.com/crossplane-contrib/provider-aws/pkg/features" +) + +const ( + acceptLanguageEnglish = "en" + + errProvisionedProductStatusSdkTainted = "provisioned product has status TAINTED" + errProvisionedProductStatusSdkError = "provisioned product has status ERROR" +) + +// SetupProvisionedProduct adds a controller that reconciles a ProvisionedProduct +func SetupProvisionedProduct(mgr ctrl.Manager, o controller.Options) error { + name := managed.ControllerName(svcapitypes.ProvisionedProductKind) + opt, err := setupExternal(&clientset.CustomServiceCatalogClient{}) + if err != nil { + return err + } + opts := []option{opt} + cps := []managed.ConnectionPublisher{managed.NewAPISecretPublisher(mgr.GetClient(), mgr.GetScheme())} + if o.Features.Enabled(features.EnableAlphaExternalSecretStores) { + cps = append(cps, connection.NewDetailsManager(mgr.GetClient(), v1alpha1.StoreConfigGroupVersionKind)) + } + + return ctrl.NewControllerManagedBy(mgr). + Named(name). + WithOptions(o.ForControllerRuntime()). + WithEventFilter(resource.DesiredStateChanged()). + For(&svcapitypes.ProvisionedProduct{}). + Complete(managed.NewReconciler(mgr, + resource.ManagedKind(svcapitypes.ProvisionedProductGroupVersionKind), + managed.WithExternalConnecter(&connector{kube: mgr.GetClient(), opts: opts}), + managed.WithPollInterval(o.PollInterval), + managed.WithLogger(o.Logger.WithValues("controller", name)), + managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))), + managed.WithConnectionPublishers(cps...))) +} + +func setupExternal(customClient clientset.Client) (func(*external), error) { + if reflect.DeepEqual(customClient, &clientset.CustomServiceCatalogClient{}) { + awsCfg, err := awsconfig.LoadDefaultConfig(context.TODO()) + if err != nil { + return func(*external) {}, err + } + cfClient := cfsdkv2.NewFromConfig(awsCfg) + return func(e *external) { + c := &custom{client: &clientset.CustomServiceCatalogClient{CfClient: cfClient, Client: e.client}} + e.isUpToDate = c.isUpToDate + e.lateInitialize = c.lateInitialize + e.postObserve = c.postObserve + e.preCreate = preCreate + e.postCreate = postCreate + e.preDelete = preDelete + e.preUpdate = c.preUpdate + }, + nil + } + return func(e *external) { + c := &custom{client: customClient} + e.isUpToDate = c.isUpToDate + e.lateInitialize = c.lateInitialize + e.postObserve = c.postObserve + e.preCreate = preCreate + e.postCreate = postCreate + e.preDelete = preDelete + e.preUpdate = c.preUpdate + }, + nil + +} + +type custom struct { + client clientset.Client + cache cache +} + +type cache struct { + provisionedProductOutputs []*svcsdk.RecordOutput +} + +func (c *custom) isUpToDate(cr *svcapitypes.ProvisionedProduct, resp *svcsdk.DescribeProvisionedProductOutput) (bool, error) { + if aws.StringValue(cr.Status.AtProvider.Status) == string(svcapitypes.ProvisionedProductStatus_SDK_UNDER_CHANGE) { + return true, nil + } + getPPInput := &svcsdk.GetProvisionedProductOutputsInput{ProvisionedProductId: resp.ProvisionedProductDetail.Id} + getPPOutput, err := c.client.GetProvisionedProductOutputs(getPPInput) + if err != nil { + return true, err + } + c.cache.provisionedProductOutputs = getPPOutput.Outputs + + cfStackParameters, err := c.client.GetCloudformationStackParameters(getPPOutput.Outputs) + if err != nil { + return true, awsclient.Wrap(err, *resp.ProvisionedProductDetail.Name) + } + if *cr.Spec.ForProvider.ProvisioningArtifactID != *resp.ProvisionedProductDetail.ProvisioningArtifactId || + !provisioningParamsAreNotChanged(cfStackParameters, cr.Spec.ForProvider.ProvisioningParameters) { + return false, nil + } + return true, nil +} + +func (c *custom) lateInitialize(spec *svcapitypes.ProvisionedProductParameters, resp *svcsdk.DescribeProvisionedProductOutput) error { + if *resp.ProvisionedProductDetail.LastSuccessfulProvisioningRecordId != "" { + describeRecordInput := svcsdk.DescribeRecordInput{Id: resp.ProvisionedProductDetail.LastSuccessfulProvisioningRecordId} + describeRecordOutput, err := c.client.DescribeRecord(&describeRecordInput) + if err != nil { + return err + } + pathID := describeRecordOutput.RecordDetail.PathId + spec.PathID = awsclient.LateInitializeStringPtr(spec.PathID, pathID) + } + acceptLanguageEnglish := acceptLanguageEnglish + if reflect.ValueOf(spec.AcceptLanguage).IsZero() { + spec.AcceptLanguage = &acceptLanguageEnglish + } + return nil +} + +func (c *custom) postObserve(_ context.Context, cr *svcapitypes.ProvisionedProduct, resp *svcsdk.DescribeProvisionedProductOutput, obs managed.ExternalObservation, err error) (managed.ExternalObservation, error) { + if err != nil { + return managed.ExternalObservation{}, err + } + + describeRecordInput := svcsdk.DescribeRecordInput{Id: resp.ProvisionedProductDetail.LastRecordId} + describeRecordOutput, err := c.client.DescribeRecord(&describeRecordInput) + if err != nil { + return managed.ExternalObservation{}, err + } + + ppStatus := aws.StringValue(resp.ProvisionedProductDetail.Status) + switch { + case ppStatus == string(svcapitypes.ProvisionedProductStatus_SDK_AVAILABLE): + cr.Status.SetConditions(xpv1.Available()) + case ppStatus == string(svcapitypes.ProvisionedProductStatus_SDK_UNDER_CHANGE) && *describeRecordOutput.RecordDetail.RecordType == "UPDATE_PROVISIONED_PRODUCT": + cr.SetConditions(xpv1.Available().WithMessage("Provisioned Product is updating, availability depends on product")) + case ppStatus == string(svcapitypes.ProvisionedProductStatus_SDK_ERROR): + cr.Status.SetConditions(xpv1.ReconcileError(errors.New(errProvisionedProductStatusSdkError))) + case ppStatus == string(svcapitypes.ProvisionedProductStatus_SDK_TAINTED): + cr.Status.SetConditions(xpv1.ReconcileError(errors.New(errProvisionedProductStatusSdkTainted))) + } + + var outputs = make(map[string]*svcapitypes.RecordOutput) + for _, v := range c.cache.provisionedProductOutputs { + outputs[*v.OutputKey] = &svcapitypes.RecordOutput{ + Description: v.Description, + OutputValue: v.OutputValue} + } + + cr.Status.AtProvider.Outputs = outputs + cr.Status.AtProvider.ARN = resp.ProvisionedProductDetail.Arn + cr.Status.AtProvider.CreatedTime = &metav1.Time{Time: *resp.ProvisionedProductDetail.CreatedTime} + cr.Status.AtProvider.LastProvisioningRecordID = resp.ProvisionedProductDetail.LastProvisioningRecordId + cr.Status.AtProvider.LaunchRoleARN = resp.ProvisionedProductDetail.LaunchRoleArn + cr.Status.AtProvider.Status = resp.ProvisionedProductDetail.Status + cr.Status.AtProvider.StatusMessage = resp.ProvisionedProductDetail.StatusMessage + cr.Status.AtProvider.ProvisionedProductType = resp.ProvisionedProductDetail.Type + cr.Status.AtProvider.RecordType = describeRecordOutput.RecordDetail.RecordType + + return obs, nil +} + +func preCreate(_ context.Context, _ *svcapitypes.ProvisionedProduct, obj *svcsdk.ProvisionProductInput) error { + obj.ProvisionToken = aws.String(genIdempotencyToken()) + return nil +} + +func postCreate(_ context.Context, cr *svcapitypes.ProvisionedProduct, resp *svcsdk.ProvisionProductOutput, cre managed.ExternalCreation, err error) (managed.ExternalCreation, error) { + if err != nil { + return managed.ExternalCreation{}, err + } + meta.SetExternalName(cr, aws.StringValue(resp.RecordDetail.ProvisionedProductId)) + return cre, nil +} + +func preDelete(_ context.Context, cr *svcapitypes.ProvisionedProduct, obj *svcsdk.TerminateProvisionedProductInput) (bool, error) { + obj.TerminateToken = aws.String(genIdempotencyToken()) + obj.ProvisionedProductId = aws.String(meta.GetExternalName(cr)) + if *cr.Status.AtProvider.Status == string(svcapitypes.ProvisionedProductStatus_SDK_UNDER_CHANGE) { + return true, nil + } + return false, nil +} + +func (c *custom) preUpdate(_ context.Context, cr *svcapitypes.ProvisionedProduct, obj *svcsdk.UpdateProvisionedProductInput) error { + obj.UpdateToken = aws.String(genIdempotencyToken()) + obj.ProvisionedProductId = aws.String(meta.GetExternalName(cr)) + return nil +} + +func provisioningParamsAreNotChanged(cfStackParams []cfsdkv2types.Parameter, currentParams []*svcapitypes.ProvisioningParameter) bool { + if len(cfStackParams) != len(currentParams) { + return false + } + + cfStackKeyValue := make(map[string]string) + for _, v := range cfStackParams { + cfStackKeyValue[*v.ParameterKey] = *v.ParameterValue + } + + for _, v := range currentParams { + if cfv, ok := cfStackKeyValue[*v.Key]; ok && cfv == *v.Value { + continue + } else { + return false + } + } + return true +} + +func genIdempotencyToken() string { + var mutex sync.Mutex + mutex.Lock() + defer mutex.Unlock() + timestamp := strings.Replace( + time.Now().UTC().Format("20060102150405.0000"), ".", "", 1) + randomPostfix := rand.Uint32() //nolint:gosec,unused // this postfix should not have cryptographic strength + return fmt.Sprintf("provider-aws-%s%08x", timestamp, randomPostfix) +} diff --git a/pkg/controller/servicecatalog/provisionedproduct/setup_test.go b/pkg/controller/servicecatalog/provisionedproduct/setup_test.go new file mode 100644 index 0000000000..779f2714c2 --- /dev/null +++ b/pkg/controller/servicecatalog/provisionedproduct/setup_test.go @@ -0,0 +1,522 @@ +/* +Copyright 2023 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package provisionedproduct + +import ( + "context" + "errors" + "testing" + "time" + + cfsdkv2types "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + svcsdkapi "github.com/aws/aws-sdk-go/service/servicecatalog/servicecatalogiface" + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/test" + "github.com/google/go-cmp/cmp" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/crossplane-contrib/provider-aws/apis/servicecatalog/v1alpha1" + aws "github.com/crossplane-contrib/provider-aws/pkg/clients" + "github.com/crossplane-contrib/provider-aws/pkg/clients/servicecatalog/fake" +) + +const ( + provisioningArtifactID = "pa-1234567890" + pathID = "lpv3-fake" + acceptLanguage = "jp" + latelyInitializedPathID = "lpv3-latelyInitialized" + latelyInitializedAcceptLanguage = "en" +) + +type args struct { + kube client.Client + client svcsdkapi.ServiceCatalogAPI + customClient *fake.MockCustomServiceCatalogClient + object *v1alpha1.ProvisionedProduct + resp *svcsdk.DescribeProvisionedProductOutput +} + +type provisionedProductModifier func(provisionedProduct *v1alpha1.ProvisionedProduct) + +func withSpec(p v1alpha1.ProvisionedProductParameters) provisionedProductModifier { + return func(cr *v1alpha1.ProvisionedProduct) { cr.Spec.ForProvider = p } +} + +func withStatus(p v1alpha1.ProvisionedProductStatus) provisionedProductModifier { + return func(cr *v1alpha1.ProvisionedProduct) { cr.Status = p } +} + +func provisionedProduct(m ...provisionedProductModifier) *v1alpha1.ProvisionedProduct { + cr := &v1alpha1.ProvisionedProduct{} + cr.Name = "test-provisioned-product-name" + for _, f := range m { + f(cr) + } + return cr +} + +type describeProvisionedProductOutputModifier func(describeProvisionedProductOutput *svcsdk.DescribeProvisionedProductOutput) + +func withDetails(d svcsdk.ProvisionedProductDetail) describeProvisionedProductOutputModifier { + return func(output *svcsdk.DescribeProvisionedProductOutput) { output.ProvisionedProductDetail = &d } +} + +func describeProvisionedProduct(m ...describeProvisionedProductOutputModifier) *svcsdk.DescribeProvisionedProductOutput { + output := &svcsdk.DescribeProvisionedProductOutput{} + for _, f := range m { + f(output) + } + return output +} + +func TestIsUpToDate(t *testing.T) { + provisioningArtifactID := provisioningArtifactID + type want struct { + result bool + err error + } + cases := map[string]struct { + args + want + }{ + "ArtifactIdHasChanged": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + ProvisioningArtifactID: aws.String("pa-new1234567890"), + ProvisioningParameters: []*v1alpha1.ProvisioningParameter{ + {Key: aws.String("Parameter"), Value: aws.String("foo")}}, + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Id: aws.String("pp-fake"), + ProvisioningArtifactId: aws.String(provisioningArtifactID), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockGetCloudformationStackParameters: func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return []cfsdkv2types.Parameter{{ParameterKey: aws.String("Parameter"), ParameterValue: aws.String("foo")}}, nil + }, + MockGetProvisionedProductOutputs: func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return &svcsdk.GetProvisionedProductOutputsOutput{}, nil + }, + }, + }, + want: want{ + result: false, + err: nil, + }, + }, + "ParametersValueHasChanged": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + ProvisioningArtifactID: aws.String(provisioningArtifactID), + ProvisioningParameters: []*v1alpha1.ProvisioningParameter{ + {Key: aws.String("ParameterIsNotChanged"), Value: aws.String("true")}}, + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Id: aws.String("pp-fake"), + ProvisioningArtifactId: aws.String(provisioningArtifactID), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockGetCloudformationStackParameters: func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return []cfsdkv2types.Parameter{{ParameterKey: aws.String("ParameterIsNotChanged"), ParameterValue: aws.String("false")}}, nil + }, + MockGetProvisionedProductOutputs: func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return &svcsdk.GetProvisionedProductOutputsOutput{}, nil + }, + }, + }, + want: want{ + result: false, + err: nil, + }, + }, + "NewParameterHasBeenAdded": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + ProvisioningArtifactID: aws.String(provisioningArtifactID), + ProvisioningParameters: []*v1alpha1.ProvisioningParameter{ + {Key: aws.String("OldParameter"), Value: aws.String("foo")}, + {Key: aws.String("NewParameter"), Value: aws.String("bar")}, + }, + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Id: aws.String("pp-fake"), + ProvisioningArtifactId: aws.String(provisioningArtifactID), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockGetCloudformationStackParameters: func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return []cfsdkv2types.Parameter{ + {ParameterKey: aws.String("OldParameter"), ParameterValue: aws.String("foo")}}, nil + }, + MockGetProvisionedProductOutputs: func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return &svcsdk.GetProvisionedProductOutputsOutput{}, nil + }, + }, + }, + want: want{ + result: false, + err: nil, + }, + }, + "ExistingParameterHasBeenRemoved": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + ProvisioningArtifactID: aws.String(provisioningArtifactID), + ProvisioningParameters: []*v1alpha1.ProvisioningParameter{ + {Key: aws.String("Parameter1"), Value: aws.String("foo")}, + }, + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Id: aws.String("pp-fake"), + ProvisioningArtifactId: aws.String(provisioningArtifactID), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockGetCloudformationStackParameters: func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return []cfsdkv2types.Parameter{ + {ParameterKey: aws.String("Parameter1"), ParameterValue: aws.String("foo")}, + {ParameterKey: aws.String("Parameter2"), ParameterValue: aws.String("bar")}, + }, + nil + }, + MockGetProvisionedProductOutputs: func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return &svcsdk.GetProvisionedProductOutputsOutput{}, nil + }, + }, + }, + want: want{ + result: false, + err: nil, + }, + }, + "ParametersAreNotChanged": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + ProvisioningArtifactID: aws.String(provisioningArtifactID), + ProvisioningParameters: []*v1alpha1.ProvisioningParameter{ + {Key: aws.String("Parameter1"), Value: aws.String("foo")}, + {Key: aws.String("Parameter2"), Value: aws.String("bar")}, + }, + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Id: aws.String("pp-fake"), + ProvisioningArtifactId: aws.String(provisioningArtifactID), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockGetCloudformationStackParameters: func(provisionedProductOutputs []*svcsdk.RecordOutput) ([]cfsdkv2types.Parameter, error) { + return []cfsdkv2types.Parameter{ + {ParameterKey: aws.String("Parameter1"), ParameterValue: aws.String("foo")}, + {ParameterKey: aws.String("Parameter2"), ParameterValue: aws.String("bar")}, + }, + nil + }, + MockGetProvisionedProductOutputs: func(getPPInput *svcsdk.GetProvisionedProductOutputsInput) (*svcsdk.GetProvisionedProductOutputsOutput, error) { + return &svcsdk.GetProvisionedProductOutputsOutput{}, nil + }, + }, + }, + want: want{ + result: true, + err: nil, + }, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + opt, _ := setupExternal(tc.args.customClient) + opts := []option{opt} + e := newExternal(tc.args.kube, tc.args.client, opts) + result, err := e.isUpToDate(tc.args.object, tc.args.resp) + if diff := cmp.Diff(err, tc.want.err, test.EquateErrors()); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + } + if diff := cmp.Diff(result, tc.want.result); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + } + }) + } +} + +func TestLateInitialize(t *testing.T) { + type want struct { + pathID string + acceptLanguage string + } + cases := map[string]struct { + args + want + }{ + "ValuesAreNotSpecified": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + PathID: aws.String(""), + AcceptLanguage: aws.String(""), + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{PathId: aws.String("lpv3-latelyInitialized")}}, nil + }, + }, + }, + want: want{ + pathID: latelyInitializedPathID, + acceptLanguage: latelyInitializedAcceptLanguage, + }, + }, + "ValuesAreSpecified": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withSpec(v1alpha1.ProvisionedProductParameters{ + PathID: aws.String(pathID), + AcceptLanguage: aws.String(acceptLanguage), + }), + }...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{PathId: aws.String("lpv3-latelyInitialized")}}, nil + }, + }, + }, + want: want{ + pathID: pathID, + acceptLanguage: acceptLanguage, + }, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + opt, _ := setupExternal(tc.args.customClient) + opts := []option{opt} + e := newExternal(tc.args.kube, tc.args.client, opts) + _ = e.lateInitialize(&tc.args.object.Spec.ForProvider, tc.args.resp) + if diff := cmp.Diff(*tc.args.object.Spec.ForProvider.PathID, tc.want.pathID); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + } + if diff := cmp.Diff(*tc.args.object.Spec.ForProvider.AcceptLanguage, tc.want.acceptLanguage); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + } + }) + } +} + +func TestPostObserve(t *testing.T) { + type want struct { + status xpv1.Condition + } + testStaringTime := time.Now() + provisionedProductStatus := withStatus(v1alpha1.ProvisionedProductStatus{ + ResourceStatus: xpv1.ResourceStatus{ + ConditionedStatus: xpv1.ConditionedStatus{ + Conditions: []xpv1.Condition{}}}, + }) + cases := map[string]struct { + args + want + }{ + "StatusAvailable": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{provisionedProductStatus}...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Status: aws.String(string(v1alpha1.ProvisionedProductStatus_SDK_AVAILABLE)), + Arn: aws.String("arn:aws:servicecatalog:fake"), + CreatedTime: &testStaringTime, + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + LaunchRoleArn: aws.String("arn:aws:iam::fake"), + StatusMessage: aws.String("fake"), + Type: aws.String("CFN_STACK"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{RecordType: aws.String("PROVISION_PRODUCT")}}, nil + }, + }, + }, + want: want{ + status: xpv1.Available(), + }, + }, + "StatusAvailableWithAmendment": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{provisionedProductStatus}...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Status: aws.String(string(v1alpha1.ProvisionedProductStatus_SDK_UNDER_CHANGE)), + Arn: aws.String("arn:aws:servicecatalog:fake"), + CreatedTime: &testStaringTime, + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + LaunchRoleArn: aws.String("arn:aws:iam::fake"), + StatusMessage: aws.String("fake"), + Type: aws.String("CFN_STACK"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{RecordType: aws.String("UPDATE_PROVISIONED_PRODUCT")}}, nil + }, + }, + }, + want: want{ + status: xpv1.Available().WithMessage("Provisioned Product is updating, availability depends on product"), + }, + }, + "StatusReconcileErrorProductError": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{provisionedProductStatus}...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Status: aws.String(string(v1alpha1.ProvisionedProductStatus_SDK_ERROR)), + Arn: aws.String("arn:aws:servicecatalog:fake"), + CreatedTime: &testStaringTime, + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + LaunchRoleArn: aws.String("arn:aws:iam::fake"), + StatusMessage: aws.String("fake"), + Type: aws.String("CFN_STACK"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{RecordType: aws.String("PROVISION_PRODUCT")}}, nil + }, + }, + }, + want: want{ + status: xpv1.ReconcileError(errors.New(errProvisionedProductStatusSdkError)), + }, + }, + "StatusReconcileErrorProductTainted": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{provisionedProductStatus}...), + resp: describeProvisionedProduct([]describeProvisionedProductOutputModifier{ + withDetails(svcsdk.ProvisionedProductDetail{ + Status: aws.String(string(v1alpha1.ProvisionedProductStatus_SDK_TAINTED)), + Arn: aws.String("arn:aws:servicecatalog:fake"), + CreatedTime: &testStaringTime, + LastSuccessfulProvisioningRecordId: aws.String("rec-fake"), + LaunchRoleArn: aws.String("arn:aws:iam::fake"), + StatusMessage: aws.String("fake"), + Type: aws.String("CFN_STACK"), + }), + }...), + customClient: &fake.MockCustomServiceCatalogClient{ + MockDescribeRecord: func(describeRecordInput *svcsdk.DescribeRecordInput) (*svcsdk.DescribeRecordOutput, error) { + return &svcsdk.DescribeRecordOutput{RecordDetail: &svcsdk.RecordDetail{RecordType: aws.String("PROVISION_PRODUCT")}}, nil + }, + }, + }, + want: want{ + status: xpv1.ReconcileError(errors.New(errProvisionedProductStatusSdkTainted)), + }, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + opt, _ := setupExternal(tc.args.customClient) + opts := []option{opt} + e := newExternal(tc.args.kube, tc.args.client, opts) + _, _ = e.postObserve(context.TODO(), tc.args.object, tc.args.resp, managed.ExternalObservation{}, nil) + conditions := tc.args.object.Status.Conditions + latestCondition := conditions[len(conditions)-1] + if diff := cmp.Diff(latestCondition, tc.want.status); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + } + test.EquateConditions() + }) + } +} + +func TestPreDelete(t *testing.T) { + type want struct { + ignoreDeletion bool + } + cases := map[string]struct { + args + want + }{ + "ignoreDeletion": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withStatus(v1alpha1.ProvisionedProductStatus{ + AtProvider: v1alpha1.ProvisionedProductObservation{ + Status: aws.String(string(v1alpha1.ProvisionedProductStatus_SDK_UNDER_CHANGE))}, + }), + }...), + }, + want: want{ + ignoreDeletion: true, + }, + }, + "passDeletion": { + args: args{ + object: provisionedProduct([]provisionedProductModifier{ + withStatus(v1alpha1.ProvisionedProductStatus{ + AtProvider: v1alpha1.ProvisionedProductObservation{ + Status: aws.String("not_UNDER_CHANGE")}, + }), + }...), + }, + want: want{ + ignoreDeletion: false, + }, + }, + } + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + opt, _ := setupExternal(tc.args.customClient) + opts := []option{opt} + e := newExternal(tc.args.kube, tc.args.client, opts) + ignore, _ := e.preDelete(context.TODO(), tc.args.object, &svcsdk.TerminateProvisionedProductInput{}) + if diff := cmp.Diff(ignore, tc.want.ignoreDeletion); diff != "" { + t.Errorf("r: -want, +got:\n%s", diff) + + } + }) + } +} diff --git a/pkg/controller/servicecatalog/provisionedproduct/zz_controller.go b/pkg/controller/servicecatalog/provisionedproduct/zz_controller.go new file mode 100644 index 0000000000..42ab5f7981 --- /dev/null +++ b/pkg/controller/servicecatalog/provisionedproduct/zz_controller.go @@ -0,0 +1,314 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package provisionedproduct + +import ( + "context" + + svcapi "github.com/aws/aws-sdk-go/service/servicecatalog" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + svcsdkapi "github.com/aws/aws-sdk-go/service/servicecatalog/servicecatalogiface" + "github.com/google/go-cmp/cmp" + "github.com/pkg/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + cpresource "github.com/crossplane/crossplane-runtime/pkg/resource" + + svcapitypes "github.com/crossplane-contrib/provider-aws/apis/servicecatalog/v1alpha1" + awsclient "github.com/crossplane-contrib/provider-aws/pkg/clients" +) + +const ( + errUnexpectedObject = "managed resource is not an ProvisionedProduct resource" + + errCreateSession = "cannot create a new session" + errCreate = "cannot create ProvisionedProduct in AWS" + errUpdate = "cannot update ProvisionedProduct in AWS" + errDescribe = "failed to describe ProvisionedProduct" + errDelete = "failed to delete ProvisionedProduct" +) + +type connector struct { + kube client.Client + opts []option +} + +func (c *connector) Connect(ctx context.Context, mg cpresource.Managed) (managed.ExternalClient, error) { + cr, ok := mg.(*svcapitypes.ProvisionedProduct) + if !ok { + return nil, errors.New(errUnexpectedObject) + } + sess, err := awsclient.GetConfigV1(ctx, c.kube, mg, cr.Spec.ForProvider.Region) + if err != nil { + return nil, errors.Wrap(err, errCreateSession) + } + return newExternal(c.kube, svcapi.New(sess), c.opts), nil +} + +func (e *external) Observe(ctx context.Context, mg cpresource.Managed) (managed.ExternalObservation, error) { + cr, ok := mg.(*svcapitypes.ProvisionedProduct) + if !ok { + return managed.ExternalObservation{}, errors.New(errUnexpectedObject) + } + if meta.GetExternalName(cr) == "" { + return managed.ExternalObservation{ + ResourceExists: false, + }, nil + } + input := GenerateDescribeProvisionedProductInput(cr) + if err := e.preObserve(ctx, cr, input); err != nil { + return managed.ExternalObservation{}, errors.Wrap(err, "pre-observe failed") + } + resp, err := e.client.DescribeProvisionedProductWithContext(ctx, input) + if err != nil { + return managed.ExternalObservation{ResourceExists: false}, awsclient.Wrap(cpresource.Ignore(IsNotFound, err), errDescribe) + } + currentSpec := cr.Spec.ForProvider.DeepCopy() + if err := e.lateInitialize(&cr.Spec.ForProvider, resp); err != nil { + return managed.ExternalObservation{}, errors.Wrap(err, "late-init failed") + } + GenerateProvisionedProduct(resp).Status.AtProvider.DeepCopyInto(&cr.Status.AtProvider) + + upToDate, err := e.isUpToDate(cr, resp) + if err != nil { + return managed.ExternalObservation{}, errors.Wrap(err, "isUpToDate check failed") + } + return e.postObserve(ctx, cr, resp, managed.ExternalObservation{ + ResourceExists: true, + ResourceUpToDate: upToDate, + ResourceLateInitialized: !cmp.Equal(&cr.Spec.ForProvider, currentSpec), + }, nil) +} + +func (e *external) Create(ctx context.Context, mg cpresource.Managed) (managed.ExternalCreation, error) { + cr, ok := mg.(*svcapitypes.ProvisionedProduct) + if !ok { + return managed.ExternalCreation{}, errors.New(errUnexpectedObject) + } + cr.Status.SetConditions(xpv1.Creating()) + input := GenerateProvisionProductInput(cr) + if err := e.preCreate(ctx, cr, input); err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, "pre-create failed") + } + resp, err := e.client.ProvisionProductWithContext(ctx, input) + if err != nil { + return managed.ExternalCreation{}, awsclient.Wrap(err, errCreate) + } + + if resp.RecordDetail.CreatedTime != nil { + cr.Status.AtProvider.CreatedTime = &metav1.Time{*resp.RecordDetail.CreatedTime} + } else { + cr.Status.AtProvider.CreatedTime = nil + } + if resp.RecordDetail.LaunchRoleArn != nil { + cr.Status.AtProvider.LaunchRoleARN = resp.RecordDetail.LaunchRoleArn + } else { + cr.Status.AtProvider.LaunchRoleARN = nil + } + if resp.RecordDetail.PathId != nil { + cr.Spec.ForProvider.PathID = resp.RecordDetail.PathId + } else { + cr.Spec.ForProvider.PathID = nil + } + if resp.RecordDetail.ProductId != nil { + cr.Spec.ForProvider.ProductID = resp.RecordDetail.ProductId + } else { + cr.Spec.ForProvider.ProductID = nil + } + if resp.RecordDetail.ProvisionedProductId != nil { + cr.Status.AtProvider.ProvisionedProductID = resp.RecordDetail.ProvisionedProductId + } else { + cr.Status.AtProvider.ProvisionedProductID = nil + } + if resp.RecordDetail.ProvisionedProductName != nil { + cr.Spec.ForProvider.Name = resp.RecordDetail.ProvisionedProductName + } else { + cr.Spec.ForProvider.Name = nil + } + if resp.RecordDetail.ProvisionedProductType != nil { + cr.Status.AtProvider.ProvisionedProductType = resp.RecordDetail.ProvisionedProductType + } else { + cr.Status.AtProvider.ProvisionedProductType = nil + } + if resp.RecordDetail.ProvisioningArtifactId != nil { + cr.Spec.ForProvider.ProvisioningArtifactID = resp.RecordDetail.ProvisioningArtifactId + } else { + cr.Spec.ForProvider.ProvisioningArtifactID = nil + } + if resp.RecordDetail.RecordErrors != nil { + f8 := []*svcapitypes.RecordError{} + for _, f8iter := range resp.RecordDetail.RecordErrors { + f8elem := &svcapitypes.RecordError{} + if f8iter.Code != nil { + f8elem.Code = f8iter.Code + } + if f8iter.Description != nil { + f8elem.Description = f8iter.Description + } + f8 = append(f8, f8elem) + } + cr.Status.AtProvider.RecordErrors = f8 + } else { + cr.Status.AtProvider.RecordErrors = nil + } + if resp.RecordDetail.RecordId != nil { + cr.Status.AtProvider.RecordID = resp.RecordDetail.RecordId + } else { + cr.Status.AtProvider.RecordID = nil + } + if resp.RecordDetail.RecordTags != nil { + f10 := []*svcapitypes.RecordTag{} + for _, f10iter := range resp.RecordDetail.RecordTags { + f10elem := &svcapitypes.RecordTag{} + if f10iter.Key != nil { + f10elem.Key = f10iter.Key + } + if f10iter.Value != nil { + f10elem.Value = f10iter.Value + } + f10 = append(f10, f10elem) + } + cr.Status.AtProvider.RecordTags = f10 + } else { + cr.Status.AtProvider.RecordTags = nil + } + if resp.RecordDetail.RecordType != nil { + cr.Status.AtProvider.RecordType = resp.RecordDetail.RecordType + } else { + cr.Status.AtProvider.RecordType = nil + } + if resp.RecordDetail.Status != nil { + cr.Status.AtProvider.Status = resp.RecordDetail.Status + } else { + cr.Status.AtProvider.Status = nil + } + if resp.RecordDetail.UpdatedTime != nil { + cr.Status.AtProvider.UpdatedTime = &metav1.Time{*resp.RecordDetail.UpdatedTime} + } else { + cr.Status.AtProvider.UpdatedTime = nil + } + + return e.postCreate(ctx, cr, resp, managed.ExternalCreation{}, err) +} + +func (e *external) Update(ctx context.Context, mg cpresource.Managed) (managed.ExternalUpdate, error) { + cr, ok := mg.(*svcapitypes.ProvisionedProduct) + if !ok { + return managed.ExternalUpdate{}, errors.New(errUnexpectedObject) + } + input := GenerateUpdateProvisionedProductInput(cr) + if err := e.preUpdate(ctx, cr, input); err != nil { + return managed.ExternalUpdate{}, errors.Wrap(err, "pre-update failed") + } + resp, err := e.client.UpdateProvisionedProductWithContext(ctx, input) + return e.postUpdate(ctx, cr, resp, managed.ExternalUpdate{}, awsclient.Wrap(err, errUpdate)) +} + +func (e *external) Delete(ctx context.Context, mg cpresource.Managed) error { + cr, ok := mg.(*svcapitypes.ProvisionedProduct) + if !ok { + return errors.New(errUnexpectedObject) + } + cr.Status.SetConditions(xpv1.Deleting()) + input := GenerateTerminateProvisionedProductInput(cr) + ignore, err := e.preDelete(ctx, cr, input) + if err != nil { + return errors.Wrap(err, "pre-delete failed") + } + if ignore { + return nil + } + resp, err := e.client.TerminateProvisionedProductWithContext(ctx, input) + return e.postDelete(ctx, cr, resp, awsclient.Wrap(cpresource.Ignore(IsNotFound, err), errDelete)) +} + +type option func(*external) + +func newExternal(kube client.Client, client svcsdkapi.ServiceCatalogAPI, opts []option) *external { + e := &external{ + kube: kube, + client: client, + preObserve: nopPreObserve, + postObserve: nopPostObserve, + lateInitialize: nopLateInitialize, + isUpToDate: alwaysUpToDate, + preCreate: nopPreCreate, + postCreate: nopPostCreate, + preDelete: nopPreDelete, + postDelete: nopPostDelete, + preUpdate: nopPreUpdate, + postUpdate: nopPostUpdate, + } + for _, f := range opts { + f(e) + } + return e +} + +type external struct { + kube client.Client + client svcsdkapi.ServiceCatalogAPI + preObserve func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.DescribeProvisionedProductInput) error + postObserve func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.DescribeProvisionedProductOutput, managed.ExternalObservation, error) (managed.ExternalObservation, error) + lateInitialize func(*svcapitypes.ProvisionedProductParameters, *svcsdk.DescribeProvisionedProductOutput) error + isUpToDate func(*svcapitypes.ProvisionedProduct, *svcsdk.DescribeProvisionedProductOutput) (bool, error) + preCreate func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.ProvisionProductInput) error + postCreate func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.ProvisionProductOutput, managed.ExternalCreation, error) (managed.ExternalCreation, error) + preDelete func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.TerminateProvisionedProductInput) (bool, error) + postDelete func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.TerminateProvisionedProductOutput, error) error + preUpdate func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.UpdateProvisionedProductInput) error + postUpdate func(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.UpdateProvisionedProductOutput, managed.ExternalUpdate, error) (managed.ExternalUpdate, error) +} + +func nopPreObserve(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.DescribeProvisionedProductInput) error { + return nil +} + +func nopPostObserve(_ context.Context, _ *svcapitypes.ProvisionedProduct, _ *svcsdk.DescribeProvisionedProductOutput, obs managed.ExternalObservation, err error) (managed.ExternalObservation, error) { + return obs, err +} +func nopLateInitialize(*svcapitypes.ProvisionedProductParameters, *svcsdk.DescribeProvisionedProductOutput) error { + return nil +} +func alwaysUpToDate(*svcapitypes.ProvisionedProduct, *svcsdk.DescribeProvisionedProductOutput) (bool, error) { + return true, nil +} + +func nopPreCreate(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.ProvisionProductInput) error { + return nil +} +func nopPostCreate(_ context.Context, _ *svcapitypes.ProvisionedProduct, _ *svcsdk.ProvisionProductOutput, cre managed.ExternalCreation, err error) (managed.ExternalCreation, error) { + return cre, err +} +func nopPreDelete(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.TerminateProvisionedProductInput) (bool, error) { + return false, nil +} +func nopPostDelete(_ context.Context, _ *svcapitypes.ProvisionedProduct, _ *svcsdk.TerminateProvisionedProductOutput, err error) error { + return err +} +func nopPreUpdate(context.Context, *svcapitypes.ProvisionedProduct, *svcsdk.UpdateProvisionedProductInput) error { + return nil +} +func nopPostUpdate(_ context.Context, _ *svcapitypes.ProvisionedProduct, _ *svcsdk.UpdateProvisionedProductOutput, upd managed.ExternalUpdate, err error) (managed.ExternalUpdate, error) { + return upd, err +} diff --git a/pkg/controller/servicecatalog/provisionedproduct/zz_conversions.go b/pkg/controller/servicecatalog/provisionedproduct/zz_conversions.go new file mode 100644 index 0000000000..a223f8e864 --- /dev/null +++ b/pkg/controller/servicecatalog/provisionedproduct/zz_conversions.go @@ -0,0 +1,262 @@ +/* +Copyright 2021 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ack-generate. DO NOT EDIT. + +package provisionedproduct + +import ( + "github.com/aws/aws-sdk-go/aws/awserr" + svcsdk "github.com/aws/aws-sdk-go/service/servicecatalog" + + svcapitypes "github.com/crossplane-contrib/provider-aws/apis/servicecatalog/v1alpha1" +) + +// NOTE(muvaf): We return pointers in case the function needs to start with an +// empty object, hence need to return a new pointer. + +// GenerateDescribeProvisionedProductInput returns input for read +// operation. +func GenerateDescribeProvisionedProductInput(cr *svcapitypes.ProvisionedProduct) *svcsdk.DescribeProvisionedProductInput { + res := &svcsdk.DescribeProvisionedProductInput{} + + if cr.Spec.ForProvider.AcceptLanguage != nil { + res.SetAcceptLanguage(*cr.Spec.ForProvider.AcceptLanguage) + } + if cr.Spec.ForProvider.Name != nil { + res.SetName(*cr.Spec.ForProvider.Name) + } + + return res +} + +// GenerateProvisionedProduct returns the current state in the form of *svcapitypes.ProvisionedProduct. +func GenerateProvisionedProduct(resp *svcsdk.DescribeProvisionedProductOutput) *svcapitypes.ProvisionedProduct { + cr := &svcapitypes.ProvisionedProduct{} + + return cr +} + +// GenerateProvisionProductInput returns a create input. +func GenerateProvisionProductInput(cr *svcapitypes.ProvisionedProduct) *svcsdk.ProvisionProductInput { + res := &svcsdk.ProvisionProductInput{} + + if cr.Spec.ForProvider.AcceptLanguage != nil { + res.SetAcceptLanguage(*cr.Spec.ForProvider.AcceptLanguage) + } + if cr.Spec.ForProvider.NotificationARNs != nil { + f1 := []*string{} + for _, f1iter := range cr.Spec.ForProvider.NotificationARNs { + var f1elem string + f1elem = *f1iter + f1 = append(f1, &f1elem) + } + res.SetNotificationArns(f1) + } + if cr.Spec.ForProvider.PathID != nil { + res.SetPathId(*cr.Spec.ForProvider.PathID) + } + if cr.Spec.ForProvider.PathName != nil { + res.SetPathName(*cr.Spec.ForProvider.PathName) + } + if cr.Spec.ForProvider.ProductID != nil { + res.SetProductId(*cr.Spec.ForProvider.ProductID) + } + if cr.Spec.ForProvider.ProductName != nil { + res.SetProductName(*cr.Spec.ForProvider.ProductName) + } + if cr.Spec.ForProvider.Name != nil { + res.SetProvisionedProductName(*cr.Spec.ForProvider.Name) + } + if cr.Spec.ForProvider.ProvisioningArtifactID != nil { + res.SetProvisioningArtifactId(*cr.Spec.ForProvider.ProvisioningArtifactID) + } + if cr.Spec.ForProvider.ProvisioningArtifactName != nil { + res.SetProvisioningArtifactName(*cr.Spec.ForProvider.ProvisioningArtifactName) + } + if cr.Spec.ForProvider.ProvisioningParameters != nil { + f9 := []*svcsdk.ProvisioningParameter{} + for _, f9iter := range cr.Spec.ForProvider.ProvisioningParameters { + f9elem := &svcsdk.ProvisioningParameter{} + if f9iter.Key != nil { + f9elem.SetKey(*f9iter.Key) + } + if f9iter.Value != nil { + f9elem.SetValue(*f9iter.Value) + } + f9 = append(f9, f9elem) + } + res.SetProvisioningParameters(f9) + } + if cr.Spec.ForProvider.ProvisioningPreferences != nil { + f10 := &svcsdk.ProvisioningPreferences{} + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetAccounts != nil { + f10f0 := []*string{} + for _, f10f0iter := range cr.Spec.ForProvider.ProvisioningPreferences.StackSetAccounts { + var f10f0elem string + f10f0elem = *f10f0iter + f10f0 = append(f10f0, &f10f0elem) + } + f10.SetStackSetAccounts(f10f0) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureToleranceCount != nil { + f10.SetStackSetFailureToleranceCount(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureToleranceCount) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureTolerancePercentage != nil { + f10.SetStackSetFailureTolerancePercentage(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureTolerancePercentage) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyCount != nil { + f10.SetStackSetMaxConcurrencyCount(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyCount) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyPercentage != nil { + f10.SetStackSetMaxConcurrencyPercentage(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyPercentage) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetRegions != nil { + f10f5 := []*string{} + for _, f10f5iter := range cr.Spec.ForProvider.ProvisioningPreferences.StackSetRegions { + var f10f5elem string + f10f5elem = *f10f5iter + f10f5 = append(f10f5, &f10f5elem) + } + f10.SetStackSetRegions(f10f5) + } + res.SetProvisioningPreferences(f10) + } + if cr.Spec.ForProvider.Tags != nil { + f11 := []*svcsdk.Tag{} + for _, f11iter := range cr.Spec.ForProvider.Tags { + f11elem := &svcsdk.Tag{} + if f11iter.Key != nil { + f11elem.SetKey(*f11iter.Key) + } + if f11iter.Value != nil { + f11elem.SetValue(*f11iter.Value) + } + f11 = append(f11, f11elem) + } + res.SetTags(f11) + } + + return res +} + +// GenerateUpdateProvisionedProductInput returns an update input. +func GenerateUpdateProvisionedProductInput(cr *svcapitypes.ProvisionedProduct) *svcsdk.UpdateProvisionedProductInput { + res := &svcsdk.UpdateProvisionedProductInput{} + + if cr.Spec.ForProvider.AcceptLanguage != nil { + res.SetAcceptLanguage(*cr.Spec.ForProvider.AcceptLanguage) + } + if cr.Spec.ForProvider.PathID != nil { + res.SetPathId(*cr.Spec.ForProvider.PathID) + } + if cr.Spec.ForProvider.PathName != nil { + res.SetPathName(*cr.Spec.ForProvider.PathName) + } + if cr.Spec.ForProvider.ProductID != nil { + res.SetProductId(*cr.Spec.ForProvider.ProductID) + } + if cr.Spec.ForProvider.ProductName != nil { + res.SetProductName(*cr.Spec.ForProvider.ProductName) + } + if cr.Spec.ForProvider.ProvisioningArtifactID != nil { + res.SetProvisioningArtifactId(*cr.Spec.ForProvider.ProvisioningArtifactID) + } + if cr.Spec.ForProvider.ProvisioningArtifactName != nil { + res.SetProvisioningArtifactName(*cr.Spec.ForProvider.ProvisioningArtifactName) + } + if cr.Spec.ForProvider.ProvisioningParameters != nil { + f8 := []*svcsdk.UpdateProvisioningParameter{} + for _, f8iter := range cr.Spec.ForProvider.ProvisioningParameters { + f8elem := &svcsdk.UpdateProvisioningParameter{} + if f8iter.Key != nil { + f8elem.SetKey(*f8iter.Key) + } + if f8iter.Value != nil { + f8elem.SetValue(*f8iter.Value) + } + f8 = append(f8, f8elem) + } + res.SetProvisioningParameters(f8) + } + if cr.Spec.ForProvider.ProvisioningPreferences != nil { + f9 := &svcsdk.UpdateProvisioningPreferences{} + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetAccounts != nil { + f9f0 := []*string{} + for _, f9f0iter := range cr.Spec.ForProvider.ProvisioningPreferences.StackSetAccounts { + var f9f0elem string + f9f0elem = *f9f0iter + f9f0 = append(f9f0, &f9f0elem) + } + f9.SetStackSetAccounts(f9f0) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureToleranceCount != nil { + f9.SetStackSetFailureToleranceCount(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureToleranceCount) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureTolerancePercentage != nil { + f9.SetStackSetFailureTolerancePercentage(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetFailureTolerancePercentage) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyCount != nil { + f9.SetStackSetMaxConcurrencyCount(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyCount) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyPercentage != nil { + f9.SetStackSetMaxConcurrencyPercentage(*cr.Spec.ForProvider.ProvisioningPreferences.StackSetMaxConcurrencyPercentage) + } + if cr.Spec.ForProvider.ProvisioningPreferences.StackSetRegions != nil { + f9f5 := []*string{} + for _, f9f5iter := range cr.Spec.ForProvider.ProvisioningPreferences.StackSetRegions { + var f9f5elem string + f9f5elem = *f9f5iter + f9f5 = append(f9f5, &f9f5elem) + } + f9.SetStackSetRegions(f9f5) + } + res.SetProvisioningPreferences(f9) + } + if cr.Spec.ForProvider.Tags != nil { + f10 := []*svcsdk.Tag{} + for _, f10iter := range cr.Spec.ForProvider.Tags { + f10elem := &svcsdk.Tag{} + if f10iter.Key != nil { + f10elem.SetKey(*f10iter.Key) + } + if f10iter.Value != nil { + f10elem.SetValue(*f10iter.Value) + } + f10 = append(f10, f10elem) + } + res.SetTags(f10) + } + + return res +} + +// GenerateTerminateProvisionedProductInput returns a deletion input. +func GenerateTerminateProvisionedProductInput(cr *svcapitypes.ProvisionedProduct) *svcsdk.TerminateProvisionedProductInput { + res := &svcsdk.TerminateProvisionedProductInput{} + + if cr.Spec.ForProvider.AcceptLanguage != nil { + res.SetAcceptLanguage(*cr.Spec.ForProvider.AcceptLanguage) + } + + return res +} + +// IsNotFound returns whether the given error is of type NotFound or not. +func IsNotFound(err error) bool { + awsErr, ok := err.(awserr.Error) + return ok && awsErr.Code() == "ResourceNotFoundException" +}