diff --git a/dev/tools/controllerbuilder/generate.sh b/dev/tools/controllerbuilder/generate.sh index a30443514f..f3b57efe2f 100755 --- a/dev/tools/controllerbuilder/generate.sh +++ b/dev/tools/controllerbuilder/generate.sh @@ -209,5 +209,11 @@ go run . generate-types \ --api-version apigee.cnrm.cloud.google.com/v1alpha1 \ --resource ApigeeInstance:GoogleCloudApigeeV1Instance +go run . generate-controller \ + --service mockgcp.cloud.apigee.v1 \ + --api-version apigee.cnrm.cloud.google.com/v1alpha1 \ + --kind ApigeeInstance \ + --proto-resource GoogleCloudApigeeV1Instance + # Fix up formatting ${REPO_ROOT}/dev/tasks/fix-gofmt diff --git a/pkg/controller/direct/apigee/client.go b/pkg/controller/direct/apigee/client.go index 675a2e70b5..260ae67a9c 100644 --- a/pkg/controller/direct/apigee/client.go +++ b/pkg/controller/direct/apigee/client.go @@ -45,6 +45,10 @@ func newGCPClient(ctx context.Context, config *config.ControllerConfig) (*gcpCli return gcpClient, nil } +func (m *gcpClient) instancesClient() *api.OrganizationsInstancesService { + return api.NewOrganizationsInstancesService(m.service) +} + func (m *gcpClient) envgroupsClient() *api.OrganizationsEnvgroupsService { return api.NewOrganizationsEnvgroupsService(m.service) } diff --git a/pkg/controller/direct/apigee/instance_controller.go b/pkg/controller/direct/apigee/instance_controller.go new file mode 100644 index 0000000000..045ee1202e --- /dev/null +++ b/pkg/controller/direct/apigee/instance_controller.go @@ -0,0 +1,264 @@ +// Copyright 2024 Google LLC +// +// 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 apigee + +import ( + "context" + "fmt" + "reflect" + "strings" + "time" + + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/apigee/v1alpha1" + refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1alpha1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/registry" + + api "google.golang.org/api/apigee/v1" + "google.golang.org/protobuf/types/known/fieldmaskpb" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func init() { + registry.RegisterModel(krm.ApigeeInstanceGVK, NewApigeeInstanceModel) +} + +func NewApigeeInstanceModel(ctx context.Context, config *config.ControllerConfig) (directbase.Model, error) { + return &modelApigeeInstance{config: config}, nil +} + +var _ directbase.Model = &modelApigeeInstance{} + +type modelApigeeInstance struct { + config *config.ControllerConfig +} + +func (m *modelApigeeInstance) AdapterForObject(ctx context.Context, reader client.Reader, u *unstructured.Unstructured) (directbase.Adapter, error) { + obj := &krm.ApigeeInstance{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, &obj); err != nil { + return nil, fmt.Errorf("error converting to %T: %w", obj, err) + } + + id, err := krm.NewApigeeInstanceIdentity(ctx, reader, obj) + if err != nil { + return nil, err + } + + // Get apigee GCP client + gcpClient, err := newGCPClient(ctx, m.config) + if err != nil { + return nil, err + } + return &ApigeeInstanceAdapter{ + id: id, + desired: obj, + instancesClient: gcpClient.instancesClient(), + operationsClient: gcpClient.operationsClient(), + }, nil +} + +func (m *modelApigeeInstance) AdapterForURL(ctx context.Context, url string) (directbase.Adapter, error) { + // TODO: Support URLs + return nil, nil +} + +type ApigeeInstanceAdapter struct { + id *krm.InstanceIdentity + instancesClient *api.OrganizationsInstancesService + operationsClient *api.OrganizationsOperationsService + desired *krm.ApigeeInstance + actual *api.GoogleCloudApigeeV1Instance +} + +var _ directbase.Adapter = &ApigeeInstanceAdapter{} + +// Find retrieves the GCP resource. +// Return true means the object is found. This triggers Adapter `Update` call. +// Return false means the object is not found. This triggers Adapter `Create` call. +// Return a non-nil error requeues the requests. +func (a *ApigeeInstanceAdapter) Find(ctx context.Context) (bool, error) { + log := klog.FromContext(ctx) + log.V(2).Info("getting ApigeeInstance", "name", a.id) + + googlecloudapigeev1instancepb, err := a.instancesClient.Get(a.id.String()).Context(ctx).Do() + if err != nil { + if direct.IsNotFound(err) { + return false, nil + } + return false, fmt.Errorf("getting ApigeeInstance %q: %w", a.id, err) + } + + a.actual = googlecloudapigeev1instancepb + return true, nil +} + +// Create creates the resource in GCP based on `spec` and update the Config Connector object `status` based on the GCP response. +func (a *ApigeeInstanceAdapter) Create(ctx context.Context, createOp *directbase.CreateOperation) error { + log := klog.FromContext(ctx) + log.V(2).Info("creating ApigeeInstance", "name", a.id) + mapCtx := &direct.MapContext{} + + desired := a.desired.DeepCopy() + resource := ApigeeInstanceSpec_ToAPI(mapCtx, &desired.Spec) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + resource.Name = a.id.ID() + + op, err := a.instancesClient.Create(a.id.Parent().String(), resource).Context(ctx).Do() + if err != nil { + return fmt.Errorf("creating ApigeeInstance %s: %w", a.id, err) + } + if err := a.waitForOp(ctx, op); err != nil { + return fmt.Errorf("ApigeeInstance %s waiting creation: %w", a.id, err) + } + + created, err := a.instancesClient.Get(a.id.String()).Context(ctx).Do() + if err != nil { + return fmt.Errorf("getting created ApigeeInstance: %w", err) + } + + log.V(2).Info("successfully created ApigeeInstance", "name", a.id) + + status := &krm.ApigeeInstanceStatus{} + status.ObservedState = ApigeeInstanceObservedState_FromAPI(mapCtx, created) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + status.ExternalRef = direct.LazyPtr(a.id.String()) + return createOp.UpdateStatus(ctx, status, nil) +} + +// Update updates the resource in GCP based on `spec` and update the Config Connector object `status` based on the GCP response. +func (a *ApigeeInstanceAdapter) Update(ctx context.Context, updateOp *directbase.UpdateOperation) error { + log := klog.FromContext(ctx) + log.V(2).Info("updating ApigeeInstance", "name", a.id) + mapCtx := &direct.MapContext{} + updateMask := fieldmaskpb.FieldMask{} + + resource := ApigeeInstanceSpec_ToAPI(mapCtx, &a.desired.DeepCopy().Spec) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + + if resource.AccessLoggingConfig != nil && !reflect.DeepEqual(resource.AccessLoggingConfig, a.actual.AccessLoggingConfig) { + log.V(2).Info("change detected: accessLoggingConfig") + updateMask.Paths = append(updateMask.Paths, "accessLoggingConfig") + } + if resource.ConsumerAcceptList != nil && !reflect.DeepEqual(resource.ConsumerAcceptList, a.actual.ConsumerAcceptList) { + log.V(2).Info("change detected: consumerAcceptList") + updateMask.Paths = append(updateMask.Paths, "consumerAcceptList") + } + + if len(updateMask.Paths) == 0 { + log.V(2).Info("no field needs update", "name", a.id) + status := &krm.ApigeeInstanceStatus{} + status.ObservedState = ApigeeInstanceObservedState_FromAPI(mapCtx, a.actual) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + return updateOp.UpdateStatus(ctx, status, nil) + } + + op, err := a.instancesClient.Patch(a.id.String(), resource).UpdateMask(strings.Join(updateMask.Paths, ",")).Context(ctx).Do() + if err != nil { + return fmt.Errorf("updating ApigeeInstance %s: %w", a.id, err) + } + if err := a.waitForOp(ctx, op); err != nil { + return fmt.Errorf("ApigeeInstance %s waiting update: %w", a.id, err) + } + updated, err := a.instancesClient.Get(a.id.String()).Context(ctx).Do() + if err != nil { + return fmt.Errorf("getting updated ApigeeInstance: %w", err) + } + log.V(2).Info("successfully updated ApigeeInstance", "name", a.id) + + status := &krm.ApigeeInstanceStatus{} + status.ObservedState = ApigeeInstanceObservedState_FromAPI(mapCtx, updated) + if mapCtx.Err() != nil { + return mapCtx.Err() + } + return updateOp.UpdateStatus(ctx, status, nil) +} + +// Export maps the GCP object to a Config Connector resource `spec`. +func (a *ApigeeInstanceAdapter) Export(ctx context.Context) (*unstructured.Unstructured, error) { + if a.actual == nil { + return nil, fmt.Errorf("Find() not called") + } + u := &unstructured.Unstructured{} + + obj := &krm.ApigeeInstance{} + mapCtx := &direct.MapContext{} + obj.Spec = direct.ValueOf(ApigeeInstanceSpec_FromAPI(mapCtx, a.actual)) + if mapCtx.Err() != nil { + return nil, mapCtx.Err() + } + obj.Spec.OrganizationRef = &refs.ApigeeOrganizationRef{External: a.id.Parent().String()} + uObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj) + if err != nil { + return nil, err + } + + u.SetName(a.id.ID()) + u.SetGroupVersionKind(krm.ApigeeInstanceGVK) + + u.Object = uObj + return u, nil +} + +// Delete the resource from GCP service when the corresponding Config Connector resource is deleted. +func (a *ApigeeInstanceAdapter) Delete(ctx context.Context, deleteOp *directbase.DeleteOperation) (bool, error) { + log := klog.FromContext(ctx) + log.V(2).Info("deleting ApigeeInstance", "name", a.id) + + op, err := a.instancesClient.Delete(a.id.String()).Context(ctx).Do() + if err != nil { + if direct.IsNotFound(err) { + // Return success if not found (assume it was already deleted) + return true, nil + } + return false, fmt.Errorf("deleting ApigeeInstance %s: %w", a.id, err) + } + log.V(2).Info("successfully deleted ApigeeInstance", "name", a.id) + + if err := a.waitForOp(ctx, op); err != nil { + return false, fmt.Errorf("waiting delete ApigeeInstance %s: %w", a.id, err) + } + return true, nil +} + +func (a *ApigeeInstanceAdapter) waitForOp(ctx context.Context, op *api.GoogleLongrunningOperation) error { + for { + current, err := a.operationsClient.Get(op.Name).Context(ctx).Do() + if err != nil { + return fmt.Errorf("getting operation status of %q: %w", op.Name, err) + } + if current.Done { + if current.Error != nil { + return fmt.Errorf("operation %q completed with error: %v", op.Name, current.Error) + } else { + return nil + } + } + time.Sleep(2 * time.Second) + } +} diff --git a/pkg/controller/direct/apigee/instance_mappings.go b/pkg/controller/direct/apigee/instance_mappings.go new file mode 100644 index 0000000000..f236cdd269 --- /dev/null +++ b/pkg/controller/direct/apigee/instance_mappings.go @@ -0,0 +1,142 @@ +// Copyright 2025 Google LLC +// +// 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 apigee + +import ( + krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/apigee/v1alpha1" + "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct" + pb "google.golang.org/api/apigee/v1" +) + +func AccessLoggingConfig_FromAPI(mapCtx *direct.MapContext, in *pb.GoogleCloudApigeeV1AccessLoggingConfig) *krm.AccessLoggingConfig { + if in == nil { + return nil + } + out := &krm.AccessLoggingConfig{} + out.Enabled = direct.LazyPtr(in.Enabled) + out.Filter = direct.LazyPtr(in.Filter) + return out +} +func AccessLoggingConfig_ToAPI(mapCtx *direct.MapContext, in *krm.AccessLoggingConfig) *pb.GoogleCloudApigeeV1AccessLoggingConfig { + if in == nil { + return nil + } + out := &pb.GoogleCloudApigeeV1AccessLoggingConfig{} + out.Enabled = direct.ValueOf(in.Enabled) + out.Filter = direct.ValueOf(in.Filter) + return out +} +func ApigeeEnvgroupObservedState_FromAPI(mapCtx *direct.MapContext, in *pb.GoogleCloudApigeeV1EnvironmentGroup) *krm.ApigeeEnvgroupObservedState { + if in == nil { + return nil + } + out := &krm.ApigeeEnvgroupObservedState{} + out.CreatedAt = direct.LazyPtr(in.CreatedAt) + out.LastModifiedAt = direct.LazyPtr(in.LastModifiedAt) + out.Name = direct.LazyPtr(in.Name) + out.State = direct.LazyPtr(in.State) + return out +} +func ApigeeEnvgroupObservedState_ToAPI(mapCtx *direct.MapContext, in *krm.ApigeeEnvgroupObservedState) *pb.GoogleCloudApigeeV1EnvironmentGroup { + if in == nil { + return nil + } + out := &pb.GoogleCloudApigeeV1EnvironmentGroup{} + out.CreatedAt = direct.ValueOf(in.CreatedAt) + out.LastModifiedAt = direct.ValueOf(in.LastModifiedAt) + out.Name = direct.ValueOf(in.Name) + out.State = direct.ValueOf(in.State) + return out +} +func ApigeeEnvgroupSpec_FromAPI(mapCtx *direct.MapContext, in *pb.GoogleCloudApigeeV1EnvironmentGroup) *krm.ApigeeEnvgroupSpec { + if in == nil { + return nil + } + out := &krm.ApigeeEnvgroupSpec{} + out.Hostnames = in.Hostnames + return out +} +func ApigeeEnvgroupSpec_ToAPI(mapCtx *direct.MapContext, in *krm.ApigeeEnvgroupSpec) *pb.GoogleCloudApigeeV1EnvironmentGroup { + if in == nil { + return nil + } + out := &pb.GoogleCloudApigeeV1EnvironmentGroup{} + out.Hostnames = in.Hostnames + return out +} +func ApigeeInstanceObservedState_FromAPI(mapCtx *direct.MapContext, in *pb.GoogleCloudApigeeV1Instance) *krm.ApigeeInstanceObservedState { + if in == nil { + return nil + } + out := &krm.ApigeeInstanceObservedState{} + out.CreatedAt = direct.LazyPtr(in.CreatedAt) + // MISSING: DiskEncryptionKeyName + out.Host = direct.LazyPtr(in.Host) + out.LastModifiedAt = direct.LazyPtr(in.LastModifiedAt) + // MISSING: Name + out.Port = direct.LazyPtr(in.Port) + out.RuntimeVersion = direct.LazyPtr(in.RuntimeVersion) + out.ServiceAttachment = direct.LazyPtr(in.ServiceAttachment) + out.State = direct.LazyPtr(in.State) + return out +} +func ApigeeInstanceObservedState_ToAPI(mapCtx *direct.MapContext, in *krm.ApigeeInstanceObservedState) *pb.GoogleCloudApigeeV1Instance { + if in == nil { + return nil + } + out := &pb.GoogleCloudApigeeV1Instance{} + out.CreatedAt = direct.ValueOf(in.CreatedAt) + // MISSING: DiskEncryptionKeyName + out.Host = direct.ValueOf(in.Host) + out.LastModifiedAt = direct.ValueOf(in.LastModifiedAt) + // MISSING: Name + out.Port = direct.ValueOf(in.Port) + out.RuntimeVersion = direct.ValueOf(in.RuntimeVersion) + out.ServiceAttachment = direct.ValueOf(in.ServiceAttachment) + out.State = direct.ValueOf(in.State) + return out +} +func ApigeeInstanceSpec_FromAPI(mapCtx *direct.MapContext, in *pb.GoogleCloudApigeeV1Instance) *krm.ApigeeInstanceSpec { + if in == nil { + return nil + } + out := &krm.ApigeeInstanceSpec{} + out.AccessLoggingConfig = AccessLoggingConfig_FromAPI(mapCtx, in.AccessLoggingConfig) + out.ConsumerAcceptList = in.ConsumerAcceptList + out.Description = direct.LazyPtr(in.Description) + // MISSING: DiskEncryptionKeyName + out.DisplayName = direct.LazyPtr(in.DisplayName) + out.IPRange = direct.LazyPtr(in.IpRange) + out.Location = direct.LazyPtr(in.Location) + // MISSING: Name + out.PeeringCIDRRange = direct.LazyPtr(in.PeeringCidrRange) + return out +} +func ApigeeInstanceSpec_ToAPI(mapCtx *direct.MapContext, in *krm.ApigeeInstanceSpec) *pb.GoogleCloudApigeeV1Instance { + if in == nil { + return nil + } + out := &pb.GoogleCloudApigeeV1Instance{} + out.AccessLoggingConfig = AccessLoggingConfig_ToAPI(mapCtx, in.AccessLoggingConfig) + out.ConsumerAcceptList = in.ConsumerAcceptList + out.Description = direct.ValueOf(in.Description) + // MISSING: DiskEncryptionKeyName + out.DisplayName = direct.ValueOf(in.DisplayName) + out.IpRange = direct.ValueOf(in.IPRange) + out.Location = direct.ValueOf(in.Location) + // MISSING: Name + out.PeeringCidrRange = direct.ValueOf(in.PeeringCIDRRange) + return out +} diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_generated_object_apigeeinstance-basic.golden.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_generated_object_apigeeinstance-basic.golden.yaml new file mode 100644 index 0000000000..3e2c6dc028 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_generated_object_apigeeinstance-basic.golden.yaml @@ -0,0 +1,32 @@ +apiVersion: apigee.cnrm.cloud.google.com/v1alpha1 +kind: ApigeeInstance +metadata: + finalizers: + - cnrm.cloud.google.com/finalizer + - cnrm.cloud.google.com/deletion-defender + generation: 1 + labels: + cnrm-test: "true" + name: apigeeinstance-${uniqueId} + namespace: ${uniqueId} +spec: + location: us-central1 + organizationRef: + external: organizations/${organizationID} +status: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: The resource is up to date + reason: UpToDate + status: "True" + type: Ready + externalRef: organizations/${organizationID}/instances/apigeeinstance-${uniqueId} + observedGeneration: 1 + observedState: + createdAt: 1711974896 + host: 10.39.56.2 + lastModifiedAt: 1711974896 + port: "443" + runtimeVersion: 1-14-0-apigee-4 + serviceAttachment: projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-xmhe + state: ACTIVE diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_http.log b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_http.log new file mode 100644 index 0000000000..5b362127e5 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/_http.log @@ -0,0 +1,184 @@ +GET https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +404 Not Found +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "error": { + "code": 404, + "message": "generic::not_found: resource organizations/${projectId}/instances/apigeeinstance-${uniqueId} not found", + "status": "NOT_FOUND" + } +} + +--- + +POST https://apigee.googleapis.com/v1/organizations/${projectId}/instances?alt=json&prettyPrint=false +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +{ + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}" +} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "INSERT", + "state": "IN_PROGRESS", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}" +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "done": true, + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "INSERT", + "progress": { + "description": "Succeeded", + "percentDone": 100 + }, + "state": "FINISHED", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}", + "response": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.Instance", + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-xmhe", + "state": "ACTIVE" + } +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-xmhe", + "state": "ACTIVE" +} + +--- + +DELETE https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "DELETE", + "state": "IN_PROGRESS", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}" +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "done": true, + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "DELETE", + "state": "FINISHED", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}", + "response": { + "@type": "type.googleapis.com/google.protobuf.Empty" + } +} \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/create.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/create.yaml new file mode 100644 index 0000000000..16eb2fa339 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-basic/create.yaml @@ -0,0 +1,27 @@ +# Copyright 2024 Google LLC +# +# 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. + +apiVersion: apigee.cnrm.cloud.google.com/v1alpha1 +kind: ApigeeInstance +metadata: + name: apigeeinstance-${uniqueId} +spec: + organizationRef: + # Note: This refers to a manually-created organization with default settings. This is + # because it is impossible to create multiple Apigee organizations in the same GCP project, + # and it is also infeasible to create + delete organizations quickly enough for automated + # testing. Deleting an organization takes 24 hours. For more information, see + # https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations/delete#deletionretention). + external: organizations/${projectId} + location: us-central1 \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_generated_object_apigeeinstance-full.golden.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_generated_object_apigeeinstance-full.golden.yaml new file mode 100644 index 0000000000..2fe8d432db --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_generated_object_apigeeinstance-full.golden.yaml @@ -0,0 +1,45 @@ +apiVersion: apigee.cnrm.cloud.google.com/v1alpha1 +kind: ApigeeInstance +metadata: + finalizers: + - cnrm.cloud.google.com/finalizer + - cnrm.cloud.google.com/deletion-defender + generation: 2 + labels: + cnrm-test: "true" + name: apigeeinstance-${uniqueId} + namespace: ${uniqueId} +spec: + accessLoggingConfig: + enabled: true + filter: status_code >= 200 && status_code < 400 + consumerAcceptList: + - ${organizationID} + description: This is a test apigee instance + diskEncryptionKMSCryptoKeyRef: + name: kmscryptokey-${uniqueId} + namespace: ${organizationID} + displayName: My Apigee Instance + ipRange: 10.39.56.0/22,10.14.0.64/28 + location: us-central1 + organizationRef: + external: organizations/${organizationID} + peeringCIDRRange: SLASH_22 + resourceID: apigeeinstance-${uniqueId} +status: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: The resource is up to date + reason: UpToDate + status: "True" + type: Ready + externalRef: organizations/${organizationID}/instances/apigeeinstance-${uniqueId} + observedGeneration: 2 + observedState: + createdAt: 1711974896 + host: 10.39.56.2 + lastModifiedAt: 1711974896 + port: "443" + runtimeVersion: 1-14-0-apigee-4 + serviceAttachment: projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-f7pw + state: ACTIVE diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_http.log b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_http.log new file mode 100644 index 0000000000..1c883fd0ec --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/_http.log @@ -0,0 +1,802 @@ +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +404 Not Found +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "error": { + "code": 404, + "message": "KeyRing projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId} not found.", + "status": "NOT_FOUND" + } +} + +--- + +POST https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings?alt=json&keyRingId=kmskeyring-${uniqueId} +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +404 Not Found +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "error": { + "code": 404, + "message": "CryptoKey projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId} not found.", + "status": "NOT_FOUND" + } +} + +--- + +POST https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys?alt=json&cryptoKeyId=kmscryptokey-${uniqueId}&skipInitialVersionCreation=false +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +{ + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "purpose": "ENCRYPT_DECRYPT" +} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +404 Not Found +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "error": { + "code": 404, + "message": "generic::not_found: resource organizations/${projectId}/instances/apigeeinstance-${uniqueId} not found", + "status": "NOT_FOUND" + } +} + +--- + +POST https://apigee.googleapis.com/v1/organizations/${projectId}/instances?alt=json&prettyPrint=false +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +{ + "accessLoggingConfig": { + "filter": "status_code \u003e= 200 \u0026\u0026 status_code \u003c 300" + }, + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22" +} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "INSERT", + "state": "IN_PROGRESS", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "done": true, + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "INSERT", + "progress": { + "description": "Succeeded", + "percentDone": 100 + }, + "state": "FINISHED", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}", + "response": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.Instance", + "accessLoggingConfig": { + "filter": "status_code \u003e= 200 and status_code \u003c 300" + }, + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-f7pw", + "state": "ACTIVE" + } +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "accessLoggingConfig": { + "filter": "status_code \u003e= 200 and status_code \u003c 300" + }, + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-f7pw", + "state": "ACTIVE" +} + +--- + +PATCH https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false&updateMask=accessLoggingConfig +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +{ + "accessLoggingConfig": { + "enabled": true, + "filter": "status_code \u003e= 200 \u0026\u0026 status_code \u003c 400" + }, + "consumerAcceptList": [ + "${projectId}" + ], + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "location": "us-central1", + "peeringCidrRange": "SLASH_22" +} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "UPDATE", + "state": "IN_PROGRESS", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}" +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "done": true, + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "UPDATE", + "state": "FINISHED", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}", + "response": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.Instance", + "accessLoggingConfig": { + "enabled": true, + "filter": "status_code \u003e= 200 \u0026\u0026 status_code \u003c 400" + }, + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-f7pw", + "state": "ACTIVE" + } +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "accessLoggingConfig": { + "enabled": true, + "filter": "status_code \u003e= 200 \u0026\u0026 status_code \u003c 400" + }, + "consumerAcceptList": [ + "${projectId}" + ], + "createdAt": "1711974896", + "description": "This is a test apigee instance", + "displayName": "My Apigee Instance", + "host": "10.1.2.3", + "ipRange": "10.39.56.0/22,10.14.0.64/28", + "lastModifiedAt": "1711974896", + "location": "us-central1", + "name": "apigeeinstance-${uniqueId}", + "peeringCidrRange": "SLASH_22", + "port": "443", + "runtimeVersion": "1-14-0-apigee-4", + "serviceAttachment": "projects/eef779b38d9fb4b50p-tp/regions/us-central1/serviceAttachments/apigee-us-central1-f7pw", + "state": "ACTIVE" +} + +--- + +DELETE https://apigee.googleapis.com/v1/organizations/${projectId}/instances/apigeeinstance-${uniqueId}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "DELETE", + "state": "IN_PROGRESS", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://apigee.googleapis.com/v1/organizations/${projectId}/operations/${operationID}?alt=json&prettyPrint=false +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "done": true, + "metadata": { + "@type": "type.googleapis.com/google.cloud.apigee.v1.OperationMetadata", + "operationType": "DELETE", + "state": "FINISHED", + "targetResourceName": "organizations/${projectId}/instances/apigeeinstance-${uniqueId}" + }, + "name": "organizations/${projectId}/operations/${operationID}", + "response": { + "@type": "type.googleapis.com/google.protobuf.Empty" + } +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyScheduledDuration": "2592000s", + "labels": { + "cnrm-test": "true", + "managed-by-cnrm": "true" + }, + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}", + "primary": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + }, + "purpose": "ENCRYPT_DECRYPT", + "versionTemplate": { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "protectionLevel": "SOFTWARE" + } +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions?alt=json&prettyPrint=false +User-Agent: google-api-go-client/0.5 kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "cryptoKeyVersions": [ + { + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "ENABLED" + } + ], + "totalSize": 1 +} + +--- + +POST https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1:destroy?alt=json&prettyPrint=false +Content-Type: application/json +User-Agent: google-api-go-client/0.5 kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +{} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "algorithm": "GOOGLE_SYMMETRIC_ENCRYPTION", + "createTime": "2024-04-01T12:34:56.123456Z", + "destroyTime": "2024-04-01T12:34:56.123456Z", + "generateTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}/cryptoKeys/kmscryptokey-${uniqueId}/cryptoKeyVersions/1", + "protectionLevel": "SOFTWARE", + "state": "DESTROY_SCHEDULED" +} + +--- + +GET https://cloudkms.googleapis.com/v1/projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}?alt=json +Content-Type: application/json +User-Agent: kcc/${kccVersion} (+https://github.com/GoogleCloudPlatform/k8s-config-connector) kcc/controller-manager/${kccVersion} + +200 OK +Content-Type: application/json; charset=UTF-8 +Server: ESF +Vary: Origin +Vary: X-Origin +Vary: Referer +X-Content-Type-Options: nosniff +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 + +{ + "createTime": "2024-04-01T12:34:56.123456Z", + "name": "projects/${projectId}/locations/us-central1/keyRings/kmskeyring-${uniqueId}" +} \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/create.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/create.yaml new file mode 100644 index 0000000000..4a584680e8 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/create.yaml @@ -0,0 +1,39 @@ +# Copyright 2024 Google LLC +# +# 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. + +apiVersion: apigee.cnrm.cloud.google.com/v1alpha1 +kind: ApigeeInstance +metadata: + name: apigeeinstance-${uniqueId} +spec: + organizationRef: + # Note: This refers to a manually-created organization with default settings. This is + # because it is impossible to create multiple Apigee organizations in the same GCP project, + # and it is also infeasible to create + delete organizations quickly enough for automated + # testing. Deleting an organization takes 24 hours. For more information, see + # https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations/delete#deletionretention). + external: organizations/${projectId} + location: us-central1 + resourceID: apigeeinstance-${uniqueId} + accessLoggingConfig: + enabled: false + filter: "status_code >= 200 && status_code < 300" + consumerAcceptList: [] + description: "This is a test apigee instance" + diskEncryptionKMSCryptoKeyRef: + name: kmscryptokey-${uniqueId} + namespace: ${projectId} + displayName: "My Apigee Instance" + ipRange: "10.39.56.0/22,10.14.0.64/28" + peeringCIDRRange: "SLASH_22" diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/dependencies.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/dependencies.yaml new file mode 100644 index 0000000000..9be90dd533 --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/dependencies.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 Google LLC +# +# 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. + +--- +apiVersion: kms.cnrm.cloud.google.com/v1beta1 +kind: KMSKeyRing +metadata: + name: kmskeyring-${uniqueId} +spec: + location: us-central1 +--- +apiVersion: kms.cnrm.cloud.google.com/v1beta1 +kind: KMSCryptoKey +metadata: + name: kmscryptokey-${uniqueId} +spec: + keyRingRef: + name: kmskeyring-${uniqueId} + purpose: ENCRYPT_DECRYPT \ No newline at end of file diff --git a/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/update.yaml b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/update.yaml new file mode 100644 index 0000000000..ffe66d705b --- /dev/null +++ b/pkg/test/resourcefixture/testdata/basic/apigee/v1alpha1/apigeeinstance/apigeeinstance-full/update.yaml @@ -0,0 +1,40 @@ +# Copyright 2024 Google LLC +# +# 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. + +apiVersion: apigee.cnrm.cloud.google.com/v1alpha1 +kind: ApigeeInstance +metadata: + name: apigeeinstance-${uniqueId} +spec: + organizationRef: + # Note: This refers to a manually-created organization with default settings. This is + # because it is impossible to create multiple Apigee organizations in the same GCP project, + # and it is also infeasible to create + delete organizations quickly enough for automated + # testing. Deleting an organization takes 24 hours. For more information, see + # https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations/delete#deletionretention). + external: organizations/${projectId} + location: us-central1 + resourceID: apigeeinstance-${uniqueId} + accessLoggingConfig: + enabled: true # previous value: false + filter: "status_code >= 200 && status_code < 400" # previous value: "status_code >= 200 && status_code < 300" + consumerAcceptList: + - ${projectId} # previous value: [] + description: "This is a test apigee instance" + diskEncryptionKMSCryptoKeyRef: + name: kmscryptokey-${uniqueId} + namespace: ${projectId} + displayName: "My Apigee Instance" + ipRange: "10.39.56.0/22,10.14.0.64/28" + peeringCIDRRange: "SLASH_22"