// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
//     http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file 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 db_proxy

import (
	"context"
	"errors"
	"fmt"
	"math"
	"reflect"
	"strings"

	ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
	ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
	ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition"
	ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors"
	ackrequeue "github.com/aws-controllers-k8s/runtime/pkg/requeue"
	ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log"
	"github.com/aws/aws-sdk-go-v2/aws"
	svcsdk "github.com/aws/aws-sdk-go-v2/service/rds"
	svcsdktypes "github.com/aws/aws-sdk-go-v2/service/rds/types"
	smithy "github.com/aws/smithy-go"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	svcapitypes "github.com/aws-controllers-k8s/rds-controller/apis/v1alpha1"
)

// Hack to avoid import errors during build...
var (
	_ = &metav1.Time{}
	_ = strings.ToLower("")
	_ = &svcsdk.Client{}
	_ = &svcapitypes.DBProxy{}
	_ = ackv1alpha1.AWSAccountID("")
	_ = &ackerr.NotFound
	_ = &ackcondition.NotManagedMessage
	_ = &reflect.Value{}
	_ = fmt.Sprintf("")
	_ = &ackrequeue.NoRequeue{}
	_ = &aws.Config{}
)

// sdkFind returns SDK-specific information about a supplied resource
func (rm *resourceManager) sdkFind(
	ctx context.Context,
	r *resource,
) (latest *resource, err error) {
	rlog := ackrtlog.FromContext(ctx)
	exit := rlog.Trace("rm.sdkFind")
	defer func() {
		exit(err)
	}()
	// If any required fields in the input shape are missing, AWS resource is
	// not created yet. Return NotFound here to indicate to callers that the
	// resource isn't yet created.
	if rm.requiredFieldsMissingFromReadManyInput(r) {
		return nil, ackerr.NotFound
	}

	input, err := rm.newListRequestPayload(r)
	if err != nil {
		return nil, err
	}
	var resp *svcsdk.DescribeDBProxiesOutput
	resp, err = rm.sdkapi.DescribeDBProxies(ctx, input)
	rm.metrics.RecordAPICall("READ_MANY", "DescribeDBProxies", err)
	if err != nil {
		var awsErr smithy.APIError
		if errors.As(err, &awsErr) && awsErr.ErrorCode() == "DBProxyNotFoundFault" {
			return nil, ackerr.NotFound
		}
		return nil, err
	}

	// Merge in the information we read from the API call above to the copy of
	// the original Kubernetes object we passed to the function
	ko := r.ko.DeepCopy()

	found := false
	for _, elem := range resp.DBProxies {
		if elem.Auth != nil {
			f0 := []*svcapitypes.UserAuthConfig{}
			for _, f0iter := range elem.Auth {
				f0elem := &svcapitypes.UserAuthConfig{}
				if f0iter.AuthScheme != "" {
					f0elem.AuthScheme = aws.String(string(f0iter.AuthScheme))
				}
				if f0iter.ClientPasswordAuthType != "" {
					f0elem.ClientPasswordAuthType = aws.String(string(f0iter.ClientPasswordAuthType))
				}
				if f0iter.Description != nil {
					f0elem.Description = f0iter.Description
				}
				if f0iter.IAMAuth != "" {
					f0elem.IAMAuth = aws.String(string(f0iter.IAMAuth))
				}
				if f0iter.SecretArn != nil {
					f0elem.SecretARN = f0iter.SecretArn
				}
				if f0iter.UserName != nil {
					f0elem.UserName = f0iter.UserName
				}
				f0 = append(f0, f0elem)
			}
			ko.Spec.Auth = f0
		} else {
			ko.Spec.Auth = nil
		}
		if elem.CreatedDate != nil {
			ko.Status.CreatedDate = &metav1.Time{*elem.CreatedDate}
		} else {
			ko.Status.CreatedDate = nil
		}
		if elem.DBProxyArn != nil {
			if ko.Status.ACKResourceMetadata == nil {
				ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
			}
			tmpARN := ackv1alpha1.AWSResourceName(*elem.DBProxyArn)
			ko.Status.ACKResourceMetadata.ARN = &tmpARN
		}
		if elem.DBProxyName != nil {
			ko.Spec.Name = elem.DBProxyName
		} else {
			ko.Spec.Name = nil
		}
		if elem.DebugLogging != nil {
			ko.Spec.DebugLogging = elem.DebugLogging
		} else {
			ko.Spec.DebugLogging = nil
		}
		if elem.Endpoint != nil {
			ko.Status.Endpoint = elem.Endpoint
		} else {
			ko.Status.Endpoint = nil
		}
		if elem.EngineFamily != nil {
			ko.Spec.EngineFamily = elem.EngineFamily
		} else {
			ko.Spec.EngineFamily = nil
		}
		if elem.IdleClientTimeout != nil {
			idleClientTimeoutCopy := int64(*elem.IdleClientTimeout)
			ko.Spec.IdleClientTimeout = &idleClientTimeoutCopy
		} else {
			ko.Spec.IdleClientTimeout = nil
		}
		if elem.RequireTLS != nil {
			ko.Spec.RequireTLS = elem.RequireTLS
		} else {
			ko.Spec.RequireTLS = nil
		}
		if elem.RoleArn != nil {
			ko.Spec.RoleARN = elem.RoleArn
		} else {
			ko.Spec.RoleARN = nil
		}
		if elem.Status != "" {
			ko.Status.Status = aws.String(string(elem.Status))
		} else {
			ko.Status.Status = nil
		}
		if elem.UpdatedDate != nil {
			ko.Status.UpdatedDate = &metav1.Time{*elem.UpdatedDate}
		} else {
			ko.Status.UpdatedDate = nil
		}
		if elem.VpcId != nil {
			ko.Status.VPCID = elem.VpcId
		} else {
			ko.Status.VPCID = nil
		}
		if elem.VpcSecurityGroupIds != nil {
			ko.Spec.VPCSecurityGroupIDs = aws.StringSlice(elem.VpcSecurityGroupIds)
		} else {
			ko.Spec.VPCSecurityGroupIDs = nil
		}
		if elem.VpcSubnetIds != nil {
			ko.Spec.VPCSubnetIDs = aws.StringSlice(elem.VpcSubnetIds)
		} else {
			ko.Spec.VPCSubnetIDs = nil
		}
		found = true
		break
	}
	if !found {
		return nil, ackerr.NotFound
	}

	rm.setStatusDefaults(ko)
	if !proxyAvailable(&resource{ko}) {
		// Setting resource synced condition to false will trigger a requeue of
		// the resource. No need to return a requeue error here.
		ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil)
	}
	return &resource{ko}, nil
}

// requiredFieldsMissingFromReadManyInput returns true if there are any fields
// for the ReadMany Input shape that are required but not present in the
// resource's Spec or Status
func (rm *resourceManager) requiredFieldsMissingFromReadManyInput(
	r *resource,
) bool {
	return r.ko.Spec.Name == nil

}

// newListRequestPayload returns SDK-specific struct for the HTTP request
// payload of the List API call for the resource
func (rm *resourceManager) newListRequestPayload(
	r *resource,
) (*svcsdk.DescribeDBProxiesInput, error) {
	res := &svcsdk.DescribeDBProxiesInput{}

	if r.ko.Spec.Name != nil {
		res.DBProxyName = r.ko.Spec.Name
	}

	return res, nil
}

// sdkCreate creates the supplied resource in the backend AWS service API and
// returns a copy of the resource with resource fields (in both Spec and
// Status) filled in with values from the CREATE API operation's Output shape.
func (rm *resourceManager) sdkCreate(
	ctx context.Context,
	desired *resource,
) (created *resource, err error) {
	rlog := ackrtlog.FromContext(ctx)
	exit := rlog.Trace("rm.sdkCreate")
	defer func() {
		exit(err)
	}()
	input, err := rm.newCreateRequestPayload(ctx, desired)
	if err != nil {
		return nil, err
	}

	var resp *svcsdk.CreateDBProxyOutput
	_ = resp
	resp, err = rm.sdkapi.CreateDBProxy(ctx, input)
	rm.metrics.RecordAPICall("CREATE", "CreateDBProxy", err)
	if err != nil {
		return nil, err
	}
	// Merge in the information we read from the API call above to the copy of
	// the original Kubernetes object we passed to the function
	ko := desired.ko.DeepCopy()

	if resp.DBProxy.Auth != nil {
		f0 := []*svcapitypes.UserAuthConfig{}
		for _, f0iter := range resp.DBProxy.Auth {
			f0elem := &svcapitypes.UserAuthConfig{}
			if f0iter.AuthScheme != "" {
				f0elem.AuthScheme = aws.String(string(f0iter.AuthScheme))
			}
			if f0iter.ClientPasswordAuthType != "" {
				f0elem.ClientPasswordAuthType = aws.String(string(f0iter.ClientPasswordAuthType))
			}
			if f0iter.Description != nil {
				f0elem.Description = f0iter.Description
			}
			if f0iter.IAMAuth != "" {
				f0elem.IAMAuth = aws.String(string(f0iter.IAMAuth))
			}
			if f0iter.SecretArn != nil {
				f0elem.SecretARN = f0iter.SecretArn
			}
			if f0iter.UserName != nil {
				f0elem.UserName = f0iter.UserName
			}
			f0 = append(f0, f0elem)
		}
		ko.Spec.Auth = f0
	} else {
		ko.Spec.Auth = nil
	}
	if resp.DBProxy.CreatedDate != nil {
		ko.Status.CreatedDate = &metav1.Time{*resp.DBProxy.CreatedDate}
	} else {
		ko.Status.CreatedDate = nil
	}
	if ko.Status.ACKResourceMetadata == nil {
		ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
	}
	if resp.DBProxy.DBProxyArn != nil {
		arn := ackv1alpha1.AWSResourceName(*resp.DBProxy.DBProxyArn)
		ko.Status.ACKResourceMetadata.ARN = &arn
	}
	if resp.DBProxy.DBProxyName != nil {
		ko.Spec.Name = resp.DBProxy.DBProxyName
	} else {
		ko.Spec.Name = nil
	}
	if resp.DBProxy.DebugLogging != nil {
		ko.Spec.DebugLogging = resp.DBProxy.DebugLogging
	} else {
		ko.Spec.DebugLogging = nil
	}
	if resp.DBProxy.Endpoint != nil {
		ko.Status.Endpoint = resp.DBProxy.Endpoint
	} else {
		ko.Status.Endpoint = nil
	}
	if resp.DBProxy.EngineFamily != nil {
		ko.Spec.EngineFamily = resp.DBProxy.EngineFamily
	} else {
		ko.Spec.EngineFamily = nil
	}
	if resp.DBProxy.IdleClientTimeout != nil {
		idleClientTimeoutCopy := int64(*resp.DBProxy.IdleClientTimeout)
		ko.Spec.IdleClientTimeout = &idleClientTimeoutCopy
	} else {
		ko.Spec.IdleClientTimeout = nil
	}
	if resp.DBProxy.RequireTLS != nil {
		ko.Spec.RequireTLS = resp.DBProxy.RequireTLS
	} else {
		ko.Spec.RequireTLS = nil
	}
	if resp.DBProxy.RoleArn != nil {
		ko.Spec.RoleARN = resp.DBProxy.RoleArn
	} else {
		ko.Spec.RoleARN = nil
	}
	if resp.DBProxy.Status != "" {
		ko.Status.Status = aws.String(string(resp.DBProxy.Status))
	} else {
		ko.Status.Status = nil
	}
	if resp.DBProxy.UpdatedDate != nil {
		ko.Status.UpdatedDate = &metav1.Time{*resp.DBProxy.UpdatedDate}
	} else {
		ko.Status.UpdatedDate = nil
	}
	if resp.DBProxy.VpcId != nil {
		ko.Status.VPCID = resp.DBProxy.VpcId
	} else {
		ko.Status.VPCID = nil
	}
	if resp.DBProxy.VpcSecurityGroupIds != nil {
		ko.Spec.VPCSecurityGroupIDs = aws.StringSlice(resp.DBProxy.VpcSecurityGroupIds)
	} else {
		ko.Spec.VPCSecurityGroupIDs = nil
	}
	if resp.DBProxy.VpcSubnetIds != nil {
		ko.Spec.VPCSubnetIDs = aws.StringSlice(resp.DBProxy.VpcSubnetIds)
	} else {
		ko.Spec.VPCSubnetIDs = nil
	}

	rm.setStatusDefaults(ko)
	// We expect the DB proxy to be in 'creating' status since we just
	// issued the call to create it, but I suppose it doesn't hurt to check
	// here.
	if proxyCreating(&resource{ko}) {
		// Setting resource synced condition to false will trigger a requeue of
		// the resource. No need to return a requeue error here.
		ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil)
		return &resource{ko}, nil
	}

	return &resource{ko}, nil
}

// newCreateRequestPayload returns an SDK-specific struct for the HTTP request
// payload of the Create API call for the resource
func (rm *resourceManager) newCreateRequestPayload(
	ctx context.Context,
	r *resource,
) (*svcsdk.CreateDBProxyInput, error) {
	res := &svcsdk.CreateDBProxyInput{}

	if r.ko.Spec.Auth != nil {
		f0 := []svcsdktypes.UserAuthConfig{}
		for _, f0iter := range r.ko.Spec.Auth {
			f0elem := &svcsdktypes.UserAuthConfig{}
			if f0iter.AuthScheme != nil {
				f0elem.AuthScheme = svcsdktypes.AuthScheme(*f0iter.AuthScheme)
			}
			if f0iter.ClientPasswordAuthType != nil {
				f0elem.ClientPasswordAuthType = svcsdktypes.ClientPasswordAuthType(*f0iter.ClientPasswordAuthType)
			}
			if f0iter.Description != nil {
				f0elem.Description = f0iter.Description
			}
			if f0iter.IAMAuth != nil {
				f0elem.IAMAuth = svcsdktypes.IAMAuthMode(*f0iter.IAMAuth)
			}
			if f0iter.SecretARN != nil {
				f0elem.SecretArn = f0iter.SecretARN
			}
			if f0iter.UserName != nil {
				f0elem.UserName = f0iter.UserName
			}
			f0 = append(f0, *f0elem)
		}
		res.Auth = f0
	}
	if r.ko.Spec.Name != nil {
		res.DBProxyName = r.ko.Spec.Name
	}
	if r.ko.Spec.DebugLogging != nil {
		res.DebugLogging = r.ko.Spec.DebugLogging
	}
	if r.ko.Spec.EngineFamily != nil {
		res.EngineFamily = svcsdktypes.EngineFamily(*r.ko.Spec.EngineFamily)
	}
	if r.ko.Spec.IdleClientTimeout != nil {
		idleClientTimeoutCopy0 := *r.ko.Spec.IdleClientTimeout
		if idleClientTimeoutCopy0 > math.MaxInt32 || idleClientTimeoutCopy0 < math.MinInt32 {
			return nil, fmt.Errorf("error: field IdleClientTimeout is of type int32")
		}
		idleClientTimeoutCopy := int32(idleClientTimeoutCopy0)
		res.IdleClientTimeout = &idleClientTimeoutCopy
	}
	if r.ko.Spec.RequireTLS != nil {
		res.RequireTLS = r.ko.Spec.RequireTLS
	}
	if r.ko.Spec.RoleARN != nil {
		res.RoleArn = r.ko.Spec.RoleARN
	}
	if r.ko.Spec.Tags != nil {
		f7 := []svcsdktypes.Tag{}
		for _, f7iter := range r.ko.Spec.Tags {
			f7elem := &svcsdktypes.Tag{}
			if f7iter.Key != nil {
				f7elem.Key = f7iter.Key
			}
			if f7iter.Value != nil {
				f7elem.Value = f7iter.Value
			}
			f7 = append(f7, *f7elem)
		}
		res.Tags = f7
	}
	if r.ko.Spec.VPCSecurityGroupIDs != nil {
		res.VpcSecurityGroupIds = aws.ToStringSlice(r.ko.Spec.VPCSecurityGroupIDs)
	}
	if r.ko.Spec.VPCSubnetIDs != nil {
		res.VpcSubnetIds = aws.ToStringSlice(r.ko.Spec.VPCSubnetIDs)
	}

	return res, nil
}

// sdkUpdate patches the supplied resource in the backend AWS service API and
// returns a new resource with updated fields.
func (rm *resourceManager) sdkUpdate(
	ctx context.Context,
	desired *resource,
	latest *resource,
	delta *ackcompare.Delta,
) (updated *resource, err error) {
	rlog := ackrtlog.FromContext(ctx)
	exit := rlog.Trace("rm.sdkUpdate")
	defer func() {
		exit(err)
	}()
	if proxyDeleting(latest) {
		msg := "DB proxy is currently being deleted"
		ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil)
		return desired, requeueWaitWhileDeleting
	}
	if proxyCreating(latest) {
		msg := "DB proxy is currently being created"
		ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil)
		return desired, requeueWaitUntilCanModify(latest)
	}
	if proxyHasTerminalStatus(latest) {
		msg := "DB proxy is in '" + *latest.ko.Status.Status + "' status"
		ackcondition.SetTerminal(desired, corev1.ConditionTrue, &msg, nil)
		ackcondition.SetSynced(desired, corev1.ConditionTrue, nil, nil)
		return desired, nil
	}
	if !proxyAvailable(latest) {
		msg := "DB proxy cannot be modifed while in '" + *latest.ko.Status.Status + "' status"
		ackcondition.SetSynced(desired, corev1.ConditionFalse, &msg, nil)
		return desired, requeueWaitUntilCanModify(latest)
	}
	input, err := rm.newUpdateRequestPayload(ctx, desired, delta)
	if err != nil {
		return nil, err
	}

	var resp *svcsdk.ModifyDBProxyOutput
	_ = resp
	resp, err = rm.sdkapi.ModifyDBProxy(ctx, input)
	rm.metrics.RecordAPICall("UPDATE", "ModifyDBProxy", err)
	if err != nil {
		return nil, err
	}
	// Merge in the information we read from the API call above to the copy of
	// the original Kubernetes object we passed to the function
	ko := desired.ko.DeepCopy()

	if resp.DBProxy.Auth != nil {
		f0 := []*svcapitypes.UserAuthConfig{}
		for _, f0iter := range resp.DBProxy.Auth {
			f0elem := &svcapitypes.UserAuthConfig{}
			if f0iter.AuthScheme != "" {
				f0elem.AuthScheme = aws.String(string(f0iter.AuthScheme))
			}
			if f0iter.ClientPasswordAuthType != "" {
				f0elem.ClientPasswordAuthType = aws.String(string(f0iter.ClientPasswordAuthType))
			}
			if f0iter.Description != nil {
				f0elem.Description = f0iter.Description
			}
			if f0iter.IAMAuth != "" {
				f0elem.IAMAuth = aws.String(string(f0iter.IAMAuth))
			}
			if f0iter.SecretArn != nil {
				f0elem.SecretARN = f0iter.SecretArn
			}
			if f0iter.UserName != nil {
				f0elem.UserName = f0iter.UserName
			}
			f0 = append(f0, f0elem)
		}
		ko.Spec.Auth = f0
	} else {
		ko.Spec.Auth = nil
	}
	if resp.DBProxy.CreatedDate != nil {
		ko.Status.CreatedDate = &metav1.Time{*resp.DBProxy.CreatedDate}
	} else {
		ko.Status.CreatedDate = nil
	}
	if ko.Status.ACKResourceMetadata == nil {
		ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
	}
	if resp.DBProxy.DBProxyArn != nil {
		arn := ackv1alpha1.AWSResourceName(*resp.DBProxy.DBProxyArn)
		ko.Status.ACKResourceMetadata.ARN = &arn
	}
	if resp.DBProxy.DBProxyName != nil {
		ko.Spec.Name = resp.DBProxy.DBProxyName
	} else {
		ko.Spec.Name = nil
	}
	if resp.DBProxy.DebugLogging != nil {
		ko.Spec.DebugLogging = resp.DBProxy.DebugLogging
	} else {
		ko.Spec.DebugLogging = nil
	}
	if resp.DBProxy.Endpoint != nil {
		ko.Status.Endpoint = resp.DBProxy.Endpoint
	} else {
		ko.Status.Endpoint = nil
	}
	if resp.DBProxy.EngineFamily != nil {
		ko.Spec.EngineFamily = resp.DBProxy.EngineFamily
	} else {
		ko.Spec.EngineFamily = nil
	}
	if resp.DBProxy.IdleClientTimeout != nil {
		idleClientTimeoutCopy := int64(*resp.DBProxy.IdleClientTimeout)
		ko.Spec.IdleClientTimeout = &idleClientTimeoutCopy
	} else {
		ko.Spec.IdleClientTimeout = nil
	}
	if resp.DBProxy.RequireTLS != nil {
		ko.Spec.RequireTLS = resp.DBProxy.RequireTLS
	} else {
		ko.Spec.RequireTLS = nil
	}
	if resp.DBProxy.RoleArn != nil {
		ko.Spec.RoleARN = resp.DBProxy.RoleArn
	} else {
		ko.Spec.RoleARN = nil
	}
	if resp.DBProxy.Status != "" {
		ko.Status.Status = aws.String(string(resp.DBProxy.Status))
	} else {
		ko.Status.Status = nil
	}
	if resp.DBProxy.UpdatedDate != nil {
		ko.Status.UpdatedDate = &metav1.Time{*resp.DBProxy.UpdatedDate}
	} else {
		ko.Status.UpdatedDate = nil
	}
	if resp.DBProxy.VpcId != nil {
		ko.Status.VPCID = resp.DBProxy.VpcId
	} else {
		ko.Status.VPCID = nil
	}
	if resp.DBProxy.VpcSecurityGroupIds != nil {
		ko.Spec.VPCSecurityGroupIDs = aws.StringSlice(resp.DBProxy.VpcSecurityGroupIds)
	} else {
		ko.Spec.VPCSecurityGroupIDs = nil
	}
	if resp.DBProxy.VpcSubnetIds != nil {
		ko.Spec.VPCSubnetIDs = aws.StringSlice(resp.DBProxy.VpcSubnetIds)
	} else {
		ko.Spec.VPCSubnetIDs = nil
	}

	rm.setStatusDefaults(ko)
	// When ModifyDBProxy API is successful, it asynchronously
	// updates the DBProxyStatus. Requeue to find the current
	// DBProxy status and set Synced condition accordingly
	if err == nil {
		// Setting resource synced condition to false will trigger a requeue of
		// the resource. No need to return a requeue error here.
		ackcondition.SetSynced(&resource{ko}, corev1.ConditionFalse, nil, nil)
	}
	return &resource{ko}, nil
}

// newUpdateRequestPayload returns an SDK-specific struct for the HTTP request
// payload of the Update API call for the resource
func (rm *resourceManager) newUpdateRequestPayload(
	ctx context.Context,
	r *resource,
	delta *ackcompare.Delta,
) (*svcsdk.ModifyDBProxyInput, error) {
	res := &svcsdk.ModifyDBProxyInput{}

	if r.ko.Spec.Auth != nil {
		f0 := []svcsdktypes.UserAuthConfig{}
		for _, f0iter := range r.ko.Spec.Auth {
			f0elem := &svcsdktypes.UserAuthConfig{}
			if f0iter.AuthScheme != nil {
				f0elem.AuthScheme = svcsdktypes.AuthScheme(*f0iter.AuthScheme)
			}
			if f0iter.ClientPasswordAuthType != nil {
				f0elem.ClientPasswordAuthType = svcsdktypes.ClientPasswordAuthType(*f0iter.ClientPasswordAuthType)
			}
			if f0iter.Description != nil {
				f0elem.Description = f0iter.Description
			}
			if f0iter.IAMAuth != nil {
				f0elem.IAMAuth = svcsdktypes.IAMAuthMode(*f0iter.IAMAuth)
			}
			if f0iter.SecretARN != nil {
				f0elem.SecretArn = f0iter.SecretARN
			}
			if f0iter.UserName != nil {
				f0elem.UserName = f0iter.UserName
			}
			f0 = append(f0, *f0elem)
		}
		res.Auth = f0
	}
	if r.ko.Spec.Name != nil {
		res.DBProxyName = r.ko.Spec.Name
	}
	if r.ko.Spec.DebugLogging != nil {
		res.DebugLogging = r.ko.Spec.DebugLogging
	}
	if r.ko.Spec.IdleClientTimeout != nil {
		idleClientTimeoutCopy0 := *r.ko.Spec.IdleClientTimeout
		if idleClientTimeoutCopy0 > math.MaxInt32 || idleClientTimeoutCopy0 < math.MinInt32 {
			return nil, fmt.Errorf("error: field IdleClientTimeout is of type int32")
		}
		idleClientTimeoutCopy := int32(idleClientTimeoutCopy0)
		res.IdleClientTimeout = &idleClientTimeoutCopy
	}
	if r.ko.Spec.RequireTLS != nil {
		res.RequireTLS = r.ko.Spec.RequireTLS
	}
	if r.ko.Spec.RoleARN != nil {
		res.RoleArn = r.ko.Spec.RoleARN
	}

	return res, nil
}

// sdkDelete deletes the supplied resource in the backend AWS service API
func (rm *resourceManager) sdkDelete(
	ctx context.Context,
	r *resource,
) (latest *resource, err error) {
	rlog := ackrtlog.FromContext(ctx)
	exit := rlog.Trace("rm.sdkDelete")
	defer func() {
		exit(err)
	}()
	if proxyDeleting(r) {
		return r, requeueWaitWhileDeleting
	}

	input, err := rm.newDeleteRequestPayload(r)
	if err != nil {
		return nil, err
	}
	var resp *svcsdk.DeleteDBProxyOutput
	_ = resp
	resp, err = rm.sdkapi.DeleteDBProxy(ctx, input)
	rm.metrics.RecordAPICall("DELETE", "DeleteDBProxy", err)
	return nil, err
}

// newDeleteRequestPayload returns an SDK-specific struct for the HTTP request
// payload of the Delete API call for the resource
func (rm *resourceManager) newDeleteRequestPayload(
	r *resource,
) (*svcsdk.DeleteDBProxyInput, error) {
	res := &svcsdk.DeleteDBProxyInput{}

	if r.ko.Spec.Name != nil {
		res.DBProxyName = r.ko.Spec.Name
	}

	return res, nil
}

// setStatusDefaults sets default properties into supplied custom resource
func (rm *resourceManager) setStatusDefaults(
	ko *svcapitypes.DBProxy,
) {
	if ko.Status.ACKResourceMetadata == nil {
		ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
	}
	if ko.Status.ACKResourceMetadata.Region == nil {
		ko.Status.ACKResourceMetadata.Region = &rm.awsRegion
	}
	if ko.Status.ACKResourceMetadata.OwnerAccountID == nil {
		ko.Status.ACKResourceMetadata.OwnerAccountID = &rm.awsAccountID
	}
	if ko.Status.Conditions == nil {
		ko.Status.Conditions = []*ackv1alpha1.Condition{}
	}
}

// updateConditions returns updated resource, true; if conditions were updated
// else it returns nil, false
func (rm *resourceManager) updateConditions(
	r *resource,
	onSuccess bool,
	err error,
) (*resource, bool) {
	ko := r.ko.DeepCopy()
	rm.setStatusDefaults(ko)

	// Terminal condition
	var terminalCondition *ackv1alpha1.Condition = nil
	var recoverableCondition *ackv1alpha1.Condition = nil
	var syncCondition *ackv1alpha1.Condition = nil
	for _, condition := range ko.Status.Conditions {
		if condition.Type == ackv1alpha1.ConditionTypeTerminal {
			terminalCondition = condition
		}
		if condition.Type == ackv1alpha1.ConditionTypeRecoverable {
			recoverableCondition = condition
		}
		if condition.Type == ackv1alpha1.ConditionTypeResourceSynced {
			syncCondition = condition
		}
	}
	var termError *ackerr.TerminalError
	if rm.terminalAWSError(err) || err == ackerr.SecretTypeNotSupported || err == ackerr.SecretNotFound || errors.As(err, &termError) {
		if terminalCondition == nil {
			terminalCondition = &ackv1alpha1.Condition{
				Type: ackv1alpha1.ConditionTypeTerminal,
			}
			ko.Status.Conditions = append(ko.Status.Conditions, terminalCondition)
		}
		var errorMessage = ""
		if err == ackerr.SecretTypeNotSupported || err == ackerr.SecretNotFound || errors.As(err, &termError) {
			errorMessage = err.Error()
		} else {
			awsErr, _ := ackerr.AWSError(err)
			errorMessage = awsErr.Error()
		}
		terminalCondition.Status = corev1.ConditionTrue
		terminalCondition.Message = &errorMessage
	} else {
		// Clear the terminal condition if no longer present
		if terminalCondition != nil {
			terminalCondition.Status = corev1.ConditionFalse
			terminalCondition.Message = nil
		}
		// Handling Recoverable Conditions
		if err != nil {
			if recoverableCondition == nil {
				// Add a new Condition containing a non-terminal error
				recoverableCondition = &ackv1alpha1.Condition{
					Type: ackv1alpha1.ConditionTypeRecoverable,
				}
				ko.Status.Conditions = append(ko.Status.Conditions, recoverableCondition)
			}
			recoverableCondition.Status = corev1.ConditionTrue
			awsErr, _ := ackerr.AWSError(err)
			errorMessage := err.Error()
			if awsErr != nil {
				errorMessage = awsErr.Error()
			}
			recoverableCondition.Message = &errorMessage
		} else if recoverableCondition != nil {
			recoverableCondition.Status = corev1.ConditionFalse
			recoverableCondition.Message = nil
		}
	}
	// Required to avoid the "declared but not used" error in the default case
	_ = syncCondition
	if terminalCondition != nil || recoverableCondition != nil || syncCondition != nil {
		return &resource{ko}, true // updated
	}
	return nil, false // not updated
}

// terminalAWSError returns awserr, true; if the supplied error is an aws Error type
// and if the exception indicates that it is a Terminal exception
// 'Terminal' exception are specified in generator configuration
func (rm *resourceManager) terminalAWSError(err error) bool {
	if err == nil {
		return false
	}

	var terminalErr smithy.APIError
	if !errors.As(err, &terminalErr) {
		return false
	}
	switch terminalErr.ErrorCode() {
	case "InvalidSubnet":
		return true
	default:
		return false
	}
}
