code

package
v0.13.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 8, 2021 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	PrimaryIdentifierARNOverride = "ARN"
)

Functions

func CheckExceptionMessage added in v0.2.3

func CheckExceptionMessage(
	cfg *ackgenconfig.Config,
	r *model.CRD,
	httpStatusCode int,
) string

CheckExceptionMessage returns Go code that contains a condition to check if the message_prefix/message_suffix specified for a particular HTTP status code in generator config is a prefix for the exception message returned by AWS API. If message_prefix/message_suffix field was not specified for this HTTP code in generator config, we return an empty string

Sample Output:

&& strings.HasPrefix(awsErr.Message(), "Could not find model") && strings.HasSuffix(awsErr.Message(), "does not exist.")

func CheckRequiredFieldsMissingFromShape

func CheckRequiredFieldsMissingFromShape(
	r *model.CRD,
	opType model.OpType,
	koVarName string,
	indentLevel int,
) string

CheckRequiredFieldsMissingFromShape returns Go code that contains a condition checking that the required fields in the supplied Shape have a non-nil value in the corresponding CR's Spec or Status substruct.

Sample Output:

return r.ko.Spec.APIID == nil || r.ko.Status.RouteID == nil

func CompareResource

func CompareResource(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	deltaVarName string,

	firstResVarName string,

	secondResVarName string,

	indentLevel int,
) string

CompareResource returns the Go code that traverses a set of two Resources, adding differences between the two Resources to an `ackcompare.Delta`

By default, we produce Go code that only looks at the fields in a resource's Spec, since those are the fields that represent the desired state of a resource. When we make a ReadOne/ReadMany/GetAttributes call to a backend AWS API, we construct a Resource and set the Spec fields to values contained in the ReadOne/ReadMany/GetAttributes Output shape. This Resource, constructed from the Read operation, is compared to the Resource we got from the Kubernetes API server's event bus. The code that is returned from this function is the code that compares those two Resources.

The Go code we return depends on the Go type of the various fields for the resource being compared.

For *scalar* Go types, the output Go code looks like this:

if ackcompare.HasNilDifference(a.ko.Spec.GrantFullControl, b.ko.Spec.GrantFullControl) {
    delta.Add("Spec.GrantFullControl", a.ko.Spec.GrantFullControl, b.ko.Spec.GrantFullControl)
} else if a.ko.Spec.GrantFullControl != nil && b.ko.Spec.GrantFullControl != nil {
    if *a.ko.Spec.GrantFullControl != *b.ko.Spec.GrantFullControl {
        delta.Add("Spec.GrantFullControl", a.ko.Spec.GrantFullControl, b.ko.Spec.GrantFullControl)
    }
}

For *struct* Go types, the output Go code looks like this (note that it is a simple recursive-descent output of all the struct's fields...):

if ackcompare.HasNilDifference(a.ko.Spec.CreateBucketConfiguration, b.ko.Spec.CreateBucketConfiguration) {
    delta.Add("Spec.CreateBucketConfiguration", a.ko.Spec.CreateBucketConfiguration, b.ko.Spec.CreateBucketConfiguration)
} else if a.ko.Spec.CreateBucketConfiguration != nil && b.ko.Spec.CreateBucketConfiguration != nil {
    if ackcompare.HasNilDifference(a.ko.Spec.CreateBucketConfiguration.LocationConstraint, b.ko.Spec.CreateBucketConfiguration.LocationConstraint) {
        delta.Add("Spec.CreateBucketConfiguration.LocationConstraint", a.ko.Spec.CreateBucketConfiguration.LocationConstraint, b.ko.Spec.CreateBucketConfiguration.LocationConstraint)
    } else if a.ko.Spec.CreateBucketConfiguration.LocationConstraint != nil && b.ko.Spec.CreateBucketConfiguration.LocationConstraint != nil {
        if *a.ko.Spec.CreateBucketConfiguration.LocationConstraint != *b.ko.Spec.CreateBucketConfiguration.LocationConstraint {
            delta.Add("Spec.CreateBucketConfiguration.LocationConstraint", a.ko.Spec.CreateBucketConfiguration.LocationConstraint, b.ko.Spec.CreateBucketConfiguration.LocationConstraint)
        }
    }
}

For *slice of strings* Go types, the output Go code looks like this:

if ackcompare.HasNilDifference(a.ko.Spec.AllowedPublishers, b.ko.Spec.AllowedPublishers) {
    delta.Add("Spec.AllowedPublishers", a.ko.Spec.AllowedPublishers, b.ko.Spec.AllowedPublishers)
} else if a.ko.Spec.AllowedPublishers != nil && b.ko.Spec.AllowedPublishers != nil {
    if !ackcompare.SliceStringPEqual(a.ko.Spec.AllowedPublishers.SigningProfileVersionARNs, b.ko.Spec.AllowedPublishers.SigningProfileVersionARNs) {
        delta.Add("Spec.AllowedPublishers.SigningProfileVersionARNs", a.ko.Spec.AllowedPublishers.SigningProfileVersionARNs, b.ko.Spec.AllowedPublishers.SigningProfileVersionARNs)
    }
}

func FindARNIdentifiersInShape added in v0.13.1

func FindARNIdentifiersInShape(
	r *model.CRD,
	shape *awssdkmodel.Shape,
) []string

FindIdentifiersInShape returns the identifier fields of a given shape which fit expect an ARN.

func FindIdentifiersInShape added in v0.10.0

func FindIdentifiersInShape(
	r *model.CRD,
	shape *awssdkmodel.Shape) []string

FindIdentifiersInShape returns the identifier fields of a given shape which can be singular or plural.

func FindLateInitializedFieldNames added in v0.10.0

func FindLateInitializedFieldNames(
	cfg *ackgenconfig.Config,
	r *model.CRD,
	resVarName string,

	indentLevel int,
) string

FindLateInitializedFieldNames outputs the code to create a sorted slice of fieldNames to late initialize. This slice helps with short circuiting the AWSResourceManager.LateInitialize() method if there are no fields to late initialize.

Sample Output: var lateInitializeFieldNames = []string{"Name"}

func FindPluralizedIdentifiersInShape added in v0.13.1

func FindPluralizedIdentifiersInShape(
	r *model.CRD,
	shape *awssdkmodel.Shape,
) (crField string, shapeField string)

FindPluralizedIdentifiersInShape returns the name of a Spec OR Status field that has a matching pluralized field in the given shape and the name of the corresponding shape field name. This method will returns the original field name - renames will need to be handled separately. For example, DescribeVpcsInput has a `VpcIds` field which would be matched to the `Status.VPCID` CRD field - the return value would be "VPCID", "VpcIds".

func FindPrimaryIdentifierFieldNames added in v0.13.1

func FindPrimaryIdentifierFieldNames(
	cfg *ackgenconfig.Config,
	r *model.CRD,
	op *awssdkmodel.Operation,
) (crField string, shapeField string)

FindPrimaryIdentifierFieldNames returns the resource identifier field name for the primary identifier used in a given operation and its corresponding shape field name.

func IncompleteLateInitialization added in v0.10.0

func IncompleteLateInitialization(
	cfg *ackgenconfig.Config,
	r *model.CRD,
	resVarName string,

	indentLevel int,
) string

IncompleteLateInitialization returns the go code which checks whether all the fields are late initialized. If all the fields are not late initialized, this method also returns the requeue delay needed to attempt late initialization again.

Sample GeneratorConfig: fields:

Name:
  late_initialize: {}
ImageScanningConfiguration.ScanOnPush:
  late_initialize:
    min_backoff_seconds: 5
    max_backoff_seconds: 15
map..subfield.x:
  late_initialize:
    min_backoff_seconds: 5
another.map..lastfield:
  late_initialize:
    min_backoff_seconds: 5
some.list:
  late_initialize:
    min_backoff_seconds: 10
structA.mapB..structC.valueD:
  late_initialize:
    min_backoff_seconds: 20

Sample Output:

ko := rm.concreteResource(latest).ko.DeepCopy()
if ko.Spec.ImageScanningConfiguration != nil {
	if ko.Spec.ImageScanningConfiguration.ScanOnPush == nil {
		return true
	}
}
if ko.Spec.Name == nil {
	return true
}
if ko.Spec.another != nil {
	if ko.Spec.another.map != nil {
		if ko.Spec.another.map["lastfield"] == nil {
			return true
		}
	}
}
if ko.Spec.map != nil {
	if ko.Spec.map["subfield"] != nil {
		if ko.Spec.map["subfield"].x == nil {
			return true
		}
	}
}
if ko.Spec.some != nil {
	if ko.Spec.some.list == nil {
		return true
	}
}
if ko.Spec.structA != nil {
	if ko.Spec.structA.mapB != nil {
		if ko.Spec.structA.mapB["structC"] != nil {
			if ko.Spec.structA.mapB["structC"].valueD == nil {
				return true
			}
		}
	}
}
return false

func LateInitializeFromReadOne added in v0.10.0

func LateInitializeFromReadOne(
	cfg *ackgenconfig.Config,
	r *model.CRD,
	sourceResVarName string,
	targetResVarName string,

	indentLevel int,
) string

LateInitializeFromReadOne returns the gocode to set LateInitialization fields from the ReadOne output Field path separated by '.' indicates members in a struct Field path separated by '..' indicates member/key in a map Note: Unlike Map, updating individual element of a list is not supported. LateInitializing complete list is supported.

Sample generator config: fields:

Name:
  late_initialize: {}
ImageScanningConfiguration.ScanOnPush:
  late_initialize:
    min_backoff_seconds: 5
    max_backoff_seconds: 15
map..subfield.x:
  late_initialize:
    min_backoff_seconds: 5
another.map..lastfield:
  late_initialize:
    min_backoff_seconds: 5
some.list:
  late_initialize:
    min_backoff_seconds: 10
structA.mapB..structC.valueD:
  late_initialize:
    min_backoff_seconds: 20

Sample output:

observedKo := rm.concreteResource(observed).ko
latestKo := rm.concreteResource(latest).ko
if observedKo.Spec.ImageScanningConfiguration != nil && latestKo.Spec.ImageScanningConfiguration != nil {
	if observedKo.Spec.ImageScanningConfiguration.ScanOnPush != nil && latestKo.Spec.ImageScanningConfiguration.ScanOnPush == nil {
		latestKo.Spec.ImageScanningConfiguration.ScanOnPush = observedKo.Spec.ImageScanningConfiguration.ScanOnPush
	}
}
if observedKo.Spec.Name != nil && latestKo.Spec.Name == nil {
	latestKo.Spec.Name = observedKo.Spec.Name
}
if observedKo.Spec.another != nil && latestKo.Spec.another != nil {
	if observedKo.Spec.another.map != nil && latestKo.Spec.another.map != nil {
		if observedKo.Spec.another.map["lastfield"] != nil && latestKo.Spec.another.map["lastfield"] == nil {
			latestKo.Spec.another.map["lastfield"] = observedKo.Spec.another.map["lastfield"]
		}
	}
}
if observedKo.Spec.map != nil && latestKo.Spec.map != nil {
	if observedKo.Spec.map["subfield"] != nil && latestKo.Spec.map["subfield"] != nil {
		if observedKo.Spec.map["subfield"].x != nil && latestKo.Spec.map["subfield"].x == nil {
			latestKo.Spec.map["subfield"].x = observedKo.Spec.map["subfield"].x
		}
	}
}
if observedKo.Spec.some != nil && latestKo.Spec.some != nil {
	if observedKo.Spec.some.list != nil && latestKo.Spec.some.list == nil {
		latestKo.Spec.some.list = observedKo.Spec.some.list
	}
}
if observedKo.Spec.structA != nil && latestKo.Spec.structA != nil {
	if observedKo.Spec.structA.mapB != nil && latestKo.Spec.structA.mapB != nil {
		if observedKo.Spec.structA.mapB["structC"] != nil && latestKo.Spec.structA.mapB["structC"] != nil {
			if observedKo.Spec.structA.mapB["structC"].valueD != nil && latestKo.Spec.structA.mapB["structC"].valueD == nil {
				latestKo.Spec.structA.mapB["structC"].valueD = observedKo.Spec.structA.mapB["structC"].valueD
			}
		}
	}
}
return &resource{latestKo}

func ListMemberNameInReadManyOutput

func ListMemberNameInReadManyOutput(
	r *model.CRD,
) string

func SetResource

func SetResource(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	opType model.OpType,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetResource returns the Go code that sets a CRD's field value to the value of an output shape's member fields. Status fields are always updated.

Assume a CRD called Repository that looks like this pseudo-schema:

.Status

.Authors ([]*string)
.ImageData
  .Location (*string)
  .Tag (*string)
.Name (*string)

And assume an SDK Shape CreateRepositoryOutput that looks like this pseudo-schema:

.Repository

.Authors ([]*string)
.ImageData
  .Location (*string)
  .Tag (*string)
.Name

This function is called from a template that generates the Go code that represents linkage between the Kubernetes objects (CRs) and the aws-sdk-go (SDK) objects. If we call this function with the following parameters:

opType:			OpTypeCreate
sourceVarName:	resp
targetVarName:	ko.Status
indentLevel:	1

Then this function should output something like this:

field0 := []*string{}
for _, iter0 := range resp.Authors {
    var elem0 string
    elem0 = *iter
    field0 = append(field0, &elem0)
}
ko.Status.Authors = field0
field1 := &svcapitypes.ImageData{}
field1.Location = resp.ImageData.Location
field1.Tag = resp.ImageData.Tag
ko.Status.ImageData = field1
ko.Status.Name = resp.Name

func SetResourceForStruct added in v0.9.2

func SetResourceForStruct(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	targetFieldName string,

	targetVarName string,

	targetShapeRef *awssdkmodel.ShapeRef,

	sourceVarName string,

	sourceShapeRef *awssdkmodel.ShapeRef,
	indentLevel int,
) string

SetResourceForStruct returns a string of Go code that sets a target variable value to a source variable when the type of the source variable is a struct.

func SetResourceGetAttributes

func SetResourceGetAttributes(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetResourceGetAttributes returns the Go code that sets the Status fields from the Output shape returned from a resource's GetAttributes operation.

As an example, for the GetTopicAttributes SNS API call, the returned code looks like this:

if ko.Status.ACKResourceMetadata == nil {
    ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
}

ko.Status.EffectiveDeliveryPolicy = resp.Attributes["EffectiveDeliveryPolicy"] ko.Status.ACKResourceMetadata.OwnerAccountID = ackv1alpha1.AWSAccountID(resp.Attributes["Owner"]) ko.Status.ACKResourceMetadata.ARN = ackv1alpha1.AWSResourceName(resp.Attributes["TopicArn"])

func SetResourceIdentifiers added in v0.4.0

func SetResourceIdentifiers(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetResourceIdentifiers returns the Go code that sets an empty CR object with Spec and Status field values that correspond to the primary identifier (be that an ARN, ID or Name) and any other "additional keys" required for the AWS service to uniquely identify the object.

The method will attempt to use the `ReadOne` operation, if present, otherwise will fall back to using `ReadMany`. If it detects the operation uses an ARN to identify the resource it will read it from the metadata status field. Otherwise it will use any fields with a matching name in the operation, pulling from spec or status - requiring that exactly one of those fields is marked as the "primary" identifier.

An example of code with no additional keys:

```

if identifier.NameOrID == nil {
	return ackerrors.MissingNameIdentifier
}
r.ko.Status.BrokerID = identifier.NameOrID

```

An example of code with additional keys:

```

if identifier.NameOrID == nil {
	  return ackerrors.MissingNameIdentifier
}

r.ko.Spec.ResourceID = identifier.NameOrID

f0, f0ok := identifier.AdditionalKeys["scalableDimension"]

if f0ok {
	  r.ko.Spec.ScalableDimension = f0
}

f1, f1ok := identifier.AdditionalKeys["serviceNamespace"]

if f1ok {
	  r.ko.Spec.ServiceNamespace = f1
}

``` An example of code that uses the ARN:

```

if r.ko.Status.ACKResourceMetadata == nil {
	r.ko.Status.ACKResourceMetadata = &ackv1alpha1.ResourceMetadata{}
}

r.ko.Status.ACKResourceMetadata.ARN = identifier.ARN

f0, f0ok := identifier.AdditionalKeys["modelPackageName"]

if f0ok {
	r.ko.Spec.ModelPackageName = &f0
}

```

func SetSDK

func SetSDK(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	opType model.OpType,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetSDK returns the Go code that sets an SDK input shape's member fields from a CRD's fields.

Assume a CRD called Repository that looks like this pseudo-schema:

.Status

.Authors ([]*string)
.ImageData
  .Location (*string)
  .Tag (*string)
.Name (*string)

And assume an SDK Shape CreateRepositoryInput that looks like this pseudo-schema:

.Repository

.Authors ([]*string)
.ImageData
  .Location (*string)
  .Tag (*string)
.Name

This function is called from a template that generates the Go code that represents linkage between the Kubernetes objects (CRs) and the aws-sdk-go (SDK) objects. If we call this function with the following parameters:

opType:			OpTypeCreate
sourceVarName:	ko
targetVarName:	res
indentLevel:	1

Then this function should output something like this:

  field1 := []*string{}
  for _, elem0 := range r.ko.Spec.Authors {
      elem0 := &string{*elem0}
      field0 = append(field0, elem0)
  }
  res.Authors = field1
  field1 := &svcsdk.ImageData{}
  field1.SetLocation(*r.ko.Spec.ImageData.Location)
  field1.SetTag(*r.ko.Spec.ImageData.Tag)
  res.ImageData = field1
	 res.SetName(*r.ko.Spec.Name)

Note that for scalar fields, we use the SetXXX methods that are on all aws-sdk-go SDK structs

func SetSDKForStruct added in v0.9.2

func SetSDKForStruct(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	targetFieldName string,

	targetVarName string,

	targetShapeRef *awssdkmodel.ShapeRef,

	sourceFieldPath string,

	sourceVarName string,
	indentLevel int,
) string

SetSDKForStruct returns a string of Go code that sets a target variable value to a source variable when the type of the source variable is a struct.

func SetSDKGetAttributes

func SetSDKGetAttributes(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetSDKGetAttributes returns the Go code that sets the Input shape for a resource's GetAttributes operation.

As an example, for the GetTopicAttributes SNS API call, the returned code looks like this:

res.SetTopicArn(string(*r.ko.Status.ACKResourceMetadata.ARN))

For the SQS API's GetQueueAttributes call, the returned code looks like this:

res.SetQueueUrl(*r.ko.Status.QueueURL)

You will note the difference due to the special handling of the ARN fields.

func SetSDKSetAttributes

func SetSDKSetAttributes(
	cfg *ackgenconfig.Config,
	r *model.CRD,

	sourceVarName string,

	targetVarName string,

	indentLevel int,
) string

SetSDKSetAttributes returns the Go code that sets the Input shape for a resource's SetAttributes operation.

Unfortunately, the AWS SetAttributes API operations (even within the *same* API) are inconsistent regarding whether the SetAttributes sets a batch of attributes or a single attribute. We need to construct the method differently depending on this behaviour. For example, the SNS SetTopicAttributes API call actually only allows the caller to set a single attribute, which needs to be specified in an AttributeName and AttributeValue field in the Input shape. On the other hand, the SNS SetPlatformApplicationAttributes API call's Input shape has an Attributes field which is a map[string]string containing all the attribute key/value pairs to replace. Your guess is as good as mine as to why these APIs are different.

The returned code looks something like this:

attrMap := map[string]*string{}

if r.ko.Spec.DeliveryPolicy != nil {
    attrMap["DeliveryPolicy"] = r.ko.Spec.DeliveryPolicy
}
if r.ko.Spec.DisplayName != nil {
    attrMap["DisplayName"} = r.ko.Spec.DisplayName
}
if r.ko.Spec.KMSMasterKeyID != nil {
    attrMap["KmsMasterKeyId"] = r.ko.Spec.KMSMasterKeyID
}
if r.ko.Spec.Policy != nil {
    attrMap["Policy"] = r.ko.Spec.Policy
}

res.SetAttributes(attrMap)

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL