diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 078c4df8ec..ca956562c4 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,7 +1,7 @@ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.137.0/containers/go/.devcontainer/base.Dockerfile # This is pinned to a particular version of go: -FROM mcr.microsoft.com/vscode/devcontainers/go:0-1.18 +FROM mcr.microsoft.com/vscode/devcontainers/go:0-1.19 # APT dependencies ENV DEBIAN_FRONTEND=noninteractive diff --git a/.devcontainer/install-dependencies.sh b/.devcontainer/install-dependencies.sh index 3c2e66be33..23f1791163 100755 --- a/.devcontainer/install-dependencies.sh +++ b/.devcontainer/install-dependencies.sh @@ -88,7 +88,7 @@ fi GOVER=$(go version) write-info "Go version: ${GOVER[*]}" -GOVERREQUIRED="go1.18.*" +GOVERREQUIRED="go1.19.*" GOVERACTUAL=$(go version | { read _ _ ver _; echo $ver; }) if ! [[ "$GOVERACTUAL" =~ $GOVERREQUIRED ]]; then write-error "Go must be version $GOVERREQUIRED, not $GOVERACTUAL; see : https://golang.org/doc/install" diff --git a/v2/internal/genericarmclient/cloud_error.go b/v2/internal/genericarmclient/cloud_error.go index 9da4af6bb4..2181d98434 100644 --- a/v2/internal/genericarmclient/cloud_error.go +++ b/v2/internal/genericarmclient/cloud_error.go @@ -22,7 +22,6 @@ import ( // However, some services put the code & message at the top level instead. // This is common enough that the Azure Python SDK has specific handling to promote a nested error to the top level. // See https://github.com/Azure/azure-sdk-for-python/blob/9791fb5bc4cb6001768e6e1fb986b8d8f8326c43/sdk/core/azure-core/azure/core/exceptions.py#L153 -// type CloudError struct { error error diff --git a/v2/internal/resolver/resource_hierarchy.go b/v2/internal/resolver/resource_hierarchy.go index 3b1be4ff1c..deab4dbe35 100644 --- a/v2/internal/resolver/resource_hierarchy.go +++ b/v2/internal/resolver/resource_hierarchy.go @@ -175,12 +175,12 @@ func (h ResourceHierarchy) fullyQualifiedARMIDImpl(subscriptionID string, origin // rootKind returns the ResourceHierarchyRoot type of the hierarchy. // There are 5 cases here: -// 1. The hierarchy is comprised solely of a resource group. This is subscription rooted. -// 2. The hierarchy has multiple entries and roots up to a resource group. This is Resource Group rooted. -// 3. The hierarchy has multiple entries and doesn't root up to a resource group. This is subscription rooted. -// 4. The hierarchy roots up to a tenant scope resource. This is tenant rooted. -// 5. The hierarchy contains a resource that sets genruntime.ChildResourceIDOverrideAnnotation. This is -// "Override" rooted. +// 1. The hierarchy is comprised solely of a resource group. This is subscription rooted. +// 2. The hierarchy has multiple entries and roots up to a resource group. This is Resource Group rooted. +// 3. The hierarchy has multiple entries and doesn't root up to a resource group. This is subscription rooted. +// 4. The hierarchy roots up to a tenant scope resource. This is tenant rooted. +// 5. The hierarchy contains a resource that sets genruntime.ChildResourceIDOverrideAnnotation. This is +// "Override" rooted. func (h ResourceHierarchy) rootKind(originalHierarchy ResourceHierarchy) ResourceHierarchyRoot { if len(h) == 0 { panic("resource hierarchy cannot be len 0") diff --git a/v2/internal/testcommon/error_translating_roundtripper.go b/v2/internal/testcommon/error_translating_roundtripper.go index 690e489a12..a4206962db 100644 --- a/v2/internal/testcommon/error_translating_roundtripper.go +++ b/v2/internal/testcommon/error_translating_roundtripper.go @@ -29,9 +29,9 @@ import ( // // Ideally we would panic on this error but we don't have a good way to deal with the following // problem at the moment: -// - during record the controller does GET (404), PUT, … GET (OK) -// - during playback the controller does GET (which now returns OK), DELETE, PUT, … -// and fails due to a missing DELETE recording +// - during record the controller does GET (404), PUT, … GET (OK) +// - during playback the controller does GET (which now returns OK), DELETE, PUT, … +// and fails due to a missing DELETE recording func translateErrors(r *recorder.Recorder, cassetteName string, t *testing.T) http.RoundTripper { return errorTranslation{r, cassetteName, nil, t} } diff --git a/v2/internal/testcommon/kube_per_test_context.go b/v2/internal/testcommon/kube_per_test_context.go index 8a667b688e..4c3e108125 100644 --- a/v2/internal/testcommon/kube_per_test_context.go +++ b/v2/internal/testcommon/kube_per_test_context.go @@ -241,11 +241,11 @@ func (tc *KubePerTestContext) CreateResourceGroup(rg *resources.ResourceGroup) ( // registerCleanup registers the resource for cleanup at the end of the test. We must do this for every resource // for two reasons: -// 1. Because OwnerReferences based deletion doesn't even run in EnvTest, see: -// https://book.kubebuilder.io/reference/envtest.html#testing-considerations -// 2. Even if it did run, it happens in the background which means that there's no guarantee that all the resources -// are deleted before the test ends. When the resources aren't deleted, they attempt to log to a closed logger -// which panics. +// 1. Because OwnerReferences based deletion doesn't even run in EnvTest, see: +// https://book.kubebuilder.io/reference/envtest.html#testing-considerations +// 2. Even if it did run, it happens in the background which means that there's no guarantee that all the resources +// are deleted before the test ends. When the resources aren't deleted, they attempt to log to a closed logger +// which panics. func (tc *KubePerTestContext) registerCleanup(obj client.Object) { tc.tracker.Track(obj) } @@ -279,10 +279,10 @@ var OperationTimeoutReplaying = 2 * time.Minute // OperationTimeoutRecording is the default timeout for a single operation when recording. // This is so high because the following operations are slow: -// * Deleting an AKS cluster. -// * Creating a Redis Enterprise Database. -// * Deleting a CosmosDB MongoDB. -// * Creating a Virtual Network Gateway Controller. +// - Deleting an AKS cluster. +// - Creating a Redis Enterprise Database. +// - Deleting a CosmosDB MongoDB. +// - Creating a Virtual Network Gateway Controller. var OperationTimeoutRecording = 30 * time.Minute func (tc *KubePerTestContext) DefaultOperationTimeout() time.Duration { @@ -521,13 +521,14 @@ func (tc *KubePerTestContext) deleteResourcesAndWait(objs ...client.Object) { // Note that this protects against deleting resources that have a parent-child relationship in the same request. This is perfectly // fine in the real world, but in many of our recording envtests we can get into a situation where there's a race // during deletion that causes HTTP replay issues. The sequence of events is: -// 1. Delete parent resource and child resource at the same time. -// 2. During recording, child deletion never sees a successful (finished) DELETE request because parent is deleted so soon -// after the child that we just record a successful DELETE for the parent and don't bother sending the final child -// DELETE that would return success. -// 3. During replay, the race is how quickly the parent deletes and how many requests the child has a chance to send -// in that time. If the parent deletes slowly the child might try to send more requests than we actually have recorded -// (because none of them represent a terminal "actually deleted" state), which will cause a test failure. +// 1. Delete parent resource and child resource at the same time. +// 2. During recording, child deletion never sees a successful (finished) DELETE request because parent is deleted so soon +// after the child that we just record a successful DELETE for the parent and don't bother sending the final child +// DELETE that would return success. +// 3. During replay, the race is how quickly the parent deletes and how many requests the child has a chance to send +// in that time. If the parent deletes slowly the child might try to send more requests than we actually have recorded +// (because none of them represent a terminal "actually deleted" state), which will cause a test failure. +// // In envtest it's still critical to delete everything, because ownership based deletion isn't enabled in envtest and we can't // leave resources around or they will continue to attempt to log to a closed test logger. To avoid this we // carefully delete resources starting with the root and working our way down one rank at a time. This shouldn't be much diff --git a/v2/internal/util/interval/interval_calculator.go b/v2/internal/util/interval/interval_calculator.go index 69a58e0d0e..9fd68b24e5 100644 --- a/v2/internal/util/interval/interval_calculator.go +++ b/v2/internal/util/interval/interval_calculator.go @@ -71,9 +71,9 @@ var _ Calculator = &calculator{} // 2. If syncPeriod is set, success results that would normally be terminal are instead configured to try again in syncPeriod. // 3. If requeueDelayOverride is set, all happy-path requests have requeueDelayOverride set. // The scenarios that this handler doesn't target: -// 1. Any error other than ReadyConditionImpacting error. -// 2. Happy-path requests when requeueDelayOverride is not set. These are scenarios where the operator is working -// as expected and we're just doing something like polling an async operation. +// 1. Any error other than ReadyConditionImpacting error. +// 2. Happy-path requests when requeueDelayOverride is not set. These are scenarios where the operator is working +// as expected and we're just doing something like polling an async operation. func (i *calculator) NextInterval(req ctrl.Request, result ctrl.Result, err error) (ctrl.Result, error) { i.failuresLock.Lock() defer i.failuresLock.Unlock() diff --git a/v2/internal/util/interval/interval_calculator_test.go b/v2/internal/util/interval/interval_calculator_test.go index 6361ec4017..78602fb1a3 100644 --- a/v2/internal/util/interval/interval_calculator_test.go +++ b/v2/internal/util/interval/interval_calculator_test.go @@ -56,7 +56,7 @@ func Test_Success_WithSyncPeriod_ReturnsSyncPeriod(t *testing.T) { t.Parallel() g := NewGomegaWithT(t) - syncPeriod := 10 * time.Second + syncPeriod := 12 * time.Second calc := newCalculator( CalculatorParameters{ ErrorBaseDelay: 1 * time.Second, @@ -69,7 +69,10 @@ func Test_Success_WithSyncPeriod_ReturnsSyncPeriod(t *testing.T) { result, err := calc.NextInterval(req, ctrl.Result{}, nil) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(result.RequeueAfter > 8*time.Second).To(BeTrue()) + + // Threshold here needs to be at or below the lower-bound of the RequeuePeriod, taking Jitter into account + // Currently jitter is 0.25, so the 12s above becomes 9s to 15s + g.Expect(result.RequeueAfter >= 9*time.Second).To(BeTrue()) g.Expect(calc.(*calculator).failures).To(HaveLen(0)) } diff --git a/v2/pkg/genruntime/conditions/conditions.go b/v2/pkg/genruntime/conditions/conditions.go index a3abb12d46..0c89f8cd73 100644 --- a/v2/pkg/genruntime/conditions/conditions.go +++ b/v2/pkg/genruntime/conditions/conditions.go @@ -154,10 +154,11 @@ func (c Condition) ShouldOverwrite(other Condition) bool { // priority of the condition for overwrite purposes if Condition ObservedGeneration's are the same. Higher is more important. // The result of this is the following: -// 1. Status == True conditions, and Status == False conditions with Severity == Warning or Error are all the highest priority. -// This means that the most recent update with any of those states will overwrite anything. -// 2. Status == False conditions with Severity == Info will only overwrite other Status == False conditions with Severity == Info. -// 3. Status == Unknown conditions will not overwrite anything. +// 1. Status == True conditions, and Status == False conditions with Severity == Warning or Error are all the highest priority. +// This means that the most recent update with any of those states will overwrite anything. +// 2. Status == False conditions with Severity == Info will only overwrite other Status == False conditions with Severity == Info. +// 3. Status == Unknown conditions will not overwrite anything. +// // Keep in mind that this priority is specifically for comparing Conditions with the same ObservedGeneration. If the ObservedGeneration // is different, the newer one always wins. func (c Condition) priority() int { diff --git a/v2/pkg/genruntime/convertible_spec.go b/v2/pkg/genruntime/convertible_spec.go index ba63dd9fdf..49267206a9 100644 --- a/v2/pkg/genruntime/convertible_spec.go +++ b/v2/pkg/genruntime/convertible_spec.go @@ -19,24 +19,23 @@ import ( // referencing types from other packages. If we tried to use an interface with a single method, we'd inevitably end up // with circular package references: // -// +----------------+ +----------------+ -// | v1 | | v2 | -// | PersonSpec | --- import v2 ---> | PersonSpec | -// | | | | -// | ConvertTo() | <--- import v1 --- | ConvertTo() | -// +----------------+ +----------------+ +// +----------------+ +----------------+ +// | v1 | | v2 | +// | PersonSpec | --- import v2 ---> | PersonSpec | +// | | | | +// | ConvertTo() | <--- import v1 --- | ConvertTo() | +// +----------------+ +----------------+ // // Instead, we have to have support for both directions, so that we can always operate from one side of the package // reference chain: // -// +----------------+ +----------------+ -// | v1 | | v2 | -// | PersonSpec | | PersonSpec | -// | | | | -// | ConvertTo() | --- import v2 ---> | | -// | ConvertFrom() | | | -// +----------------+ +----------------+ -// +// +----------------+ +----------------+ +// | v1 | | v2 | +// | PersonSpec | | PersonSpec | +// | | | | +// | ConvertTo() | --- import v2 ---> | | +// | ConvertFrom() | | | +// +----------------+ +----------------+ type ConvertibleSpec interface { // ConvertSpecTo will populate the passed Spec by copying over all available information from this one ConvertSpecTo(destination ConvertibleSpec) error diff --git a/v2/pkg/genruntime/convertible_status.go b/v2/pkg/genruntime/convertible_status.go index e2450271ba..9ead924684 100644 --- a/v2/pkg/genruntime/convertible_status.go +++ b/v2/pkg/genruntime/convertible_status.go @@ -14,7 +14,6 @@ import ( // ConvertibleStatus is implemented by status types to allow conversion among the different versions of a given status // // Why do we need both directions of conversion? See ConvertibleSpec for details. -// type ConvertibleStatus interface { // ConvertStatusTo will populate the passed Status by copying over all available information from this one ConvertStatusTo(destination ConvertibleStatus) error diff --git a/v2/tools/generator/internal/armconversion/convert_from_arm_function_builder.go b/v2/tools/generator/internal/armconversion/convert_from_arm_function_builder.go index 13355f60cd..e7523994df 100644 --- a/v2/tools/generator/internal/armconversion/convert_from_arm_function_builder.go +++ b/v2/tools/generator/internal/armconversion/convert_from_arm_function_builder.go @@ -309,8 +309,8 @@ func (builder *convertFromARMBuilder) operatorSpecPropertyHandler( // // If 'X' is a property that was flattened: // -// k8sObj.Y1 = armObj.X.Y1; -// k8sObj.Y2 = armObj.X.Y2; +// k8sObj.Y1 = armObj.X.Y1; +// k8sObj.Y2 = armObj.X.Y2; // // in reality each assignment is likely to be another conversion that is specific // to the type being converted. @@ -464,6 +464,7 @@ func (builder *convertFromARMBuilder) propertiesWithSameNameHandler( // convertComplexTypeNameProperty handles conversion of complex TypeName properties. // This function generates code that looks like this: +// // Converted := {} // err = Converted.FromARM(owner, ) // if err != nil { diff --git a/v2/tools/generator/internal/armconversion/convert_to_arm_function_builder.go b/v2/tools/generator/internal/armconversion/convert_to_arm_function_builder.go index 6c4295c2cc..5f221bcdc1 100644 --- a/v2/tools/generator/internal/armconversion/convert_to_arm_function_builder.go +++ b/v2/tools/generator/internal/armconversion/convert_to_arm_function_builder.go @@ -294,8 +294,8 @@ func (builder *convertToARMBuilder) referencePropertyHandler( // // If 'X' is a property that was flattened: // -// armObj.X.Y1 = k8sObj.Y1; -// armObj.X.Y2 = k8sObj.Y2; +// armObj.X.Y1 = k8sObj.Y1; +// armObj.X.Y2 = k8sObj.Y2; // // in reality each assignment is likely to be another conversion that is specific // to the type being converted. @@ -399,9 +399,10 @@ func (builder *convertToARMBuilder) flattenedPropertyHandler( // that assigns it a value if any of the “from” properties are not nil. // // Resultant code looks like: -// if (from1 != nil) || (from2 != nil) || … { -// . = &{} -// } +// +// if (from1 != nil) || (from2 != nil) || … { +// . = &{} +// } func (builder *convertToARMBuilder) buildToPropInitializer( fromProps []*astmodel.PropertyDefinition, toPropTypeName astmodel.TypeName, @@ -458,6 +459,7 @@ func (builder *convertToARMBuilder) propertiesWithSameNameHandler( // convertReferenceProperty handles conversion of reference properties. // This function generates code that looks like this: +// // ARMID, err := resolved.ResolvedReferences.Lookup() // if err != nil { // return nil, err @@ -493,6 +495,7 @@ func (builder *convertToARMBuilder) convertReferenceProperty(_ *astmodel.Convers // convertSecretProperty handles conversion of secret properties. // This function generates code that looks like this: +// // Secret, err := resolved.ResolvedSecrets.Lookup() // if err != nil { // return nil, errors.Wrap(err, "looking up secret for ") @@ -533,12 +536,12 @@ func (builder *convertToARMBuilder) convertSecretProperty(_ *astmodel.Conversion // convertConfigMapProperty handles conversion of configMap properties. // This function generates code that looks like this: +// // Value, err := resolved.ResolvedConfigMaps.Lookup() // if err != nil { // return nil, errors.Wrap(err, "looking up config map value for ") // } // = Value -// func (builder *convertToARMBuilder) convertConfigMapProperty(_ *astmodel.ConversionFunctionBuilder, params astmodel.ConversionParameters) []dst.Stmt { isString := astmodel.TypeEquals(params.DestinationType, astmodel.StringType) if !isString { @@ -574,7 +577,8 @@ func (builder *convertToARMBuilder) convertConfigMapProperty(_ *astmodel.Convers // convertComplexTypeNameProperty handles conversion of complex TypeName properties. // This function generates code that looks like this: -// , err := .ToARM(name) +// +// , err := .ToARM(name) // if err != nil { // return nil, err // } diff --git a/v2/tools/generator/internal/astbuilder/assignments.go b/v2/tools/generator/internal/astbuilder/assignments.go index 0a77482d51..8f5cda7b84 100644 --- a/v2/tools/generator/internal/astbuilder/assignments.go +++ b/v2/tools/generator/internal/astbuilder/assignments.go @@ -14,7 +14,7 @@ import ( // SimpleAssignment performs a simple assignment like: // -// = +// = // // See also ShortDeclaration func SimpleAssignment(lhs dst.Expr, rhs dst.Expr) *dst.AssignStmt { @@ -31,7 +31,7 @@ func SimpleAssignment(lhs dst.Expr, rhs dst.Expr) *dst.AssignStmt { // ShortDeclaration performs a simple assignment like: // -// := +// := // // Method naming inspired by https://tour.golang.org/basics/10 func ShortDeclaration(id string, rhs dst.Expr) *dst.AssignStmt { @@ -62,7 +62,9 @@ func AssignmentStatement(lhs dst.Expr, tok token.Token, rhs dst.Expr) *dst.Assig } // QualifiedAssignment performs a simple assignment like: -// . := // tok = token.DEFINE +// +// . := // tok = token.DEFINE +// // or . = // tok = token.ASSIGN func QualifiedAssignment(lhs dst.Expr, lhsSel string, tok token.Token, rhs dst.Expr) *dst.AssignStmt { return &dst.AssignStmt{ @@ -73,8 +75,9 @@ func QualifiedAssignment(lhs dst.Expr, lhsSel string, tok token.Token, rhs dst.E } // SimpleAssignmentWithErr performs a simple assignment like: -// , err := // tok = token.DEFINE -// or , err = // tok = token.ASSIGN +// +// , err := // tok = token.DEFINE +// or , err = // tok = token.ASSIGN func SimpleAssignmentWithErr(lhs dst.Expr, tok token.Token, rhs dst.Expr) *dst.AssignStmt { errId := dst.NewIdent("err") return &dst.AssignStmt{ @@ -92,6 +95,7 @@ func SimpleAssignmentWithErr(lhs dst.Expr, tok token.Token, rhs dst.Expr) *dst.A // AssignToInterface performs an assignment of a well-typed variable to an interface{}. This is usually used to // perform a type assertion on a concrete type in a subsequent statement (which Go doesn't allow, it only allows type // assertions on interface types). +// // var interface{} = func AssignToInterface(lhsVar string, rhs dst.Expr) *dst.DeclStmt { return &dst.DeclStmt{ diff --git a/v2/tools/generator/internal/astbuilder/builder.go b/v2/tools/generator/internal/astbuilder/builder.go index e445e7c12d..3cae174629 100644 --- a/v2/tools/generator/internal/astbuilder/builder.go +++ b/v2/tools/generator/internal/astbuilder/builder.go @@ -14,8 +14,8 @@ import ( // CheckErrorAndReturn checks if the err is non-nil, and if it is returns. // -// if err != nil { -// return , err +// if err != nil { +// return , err // } func CheckErrorAndReturn(otherReturns ...dst.Expr) dst.Stmt { retStmt := &dst.ReturnStmt{ @@ -28,16 +28,15 @@ func CheckErrorAndReturn(otherReturns ...dst.Expr) dst.Stmt { // CheckErrorAndWrap checks if the err is non-nil, and if it is returns it, wrapped with additional information // If no arguments are provided, will generate // -// if err != nil { -// return errors.Wrap(err, ) -// } +// if err != nil { +// return errors.Wrap(err, ) +// } // // otherwise will generate // -// if err != nil { -// return errors.Wrapf(err, , ) -// } -// +// if err != nil { +// return errors.Wrapf(err, , ) +// } func CheckErrorAndWrap(errorsPackage string, message string, args ...dst.Expr) dst.Stmt { wrap := WrapError(errorsPackage, "err", message, args...) return CheckErrorAndSingleStatement(Returns(wrap)) @@ -45,8 +44,8 @@ func CheckErrorAndWrap(errorsPackage string, message string, args ...dst.Expr) d // CheckErrorAndSingleStatement checks if the err is non-nil, and if it is executes the provided statement. // -// if err != nil { -// +// if err != nil { +// // } func CheckErrorAndSingleStatement(stmt dst.Stmt) dst.Stmt { return &dst.IfStmt{ @@ -82,10 +81,12 @@ func WrapError(errorsPackage string, err string, message string, args ...dst.Exp // with its default value. // // For example: -// var . +// +// var . // // Note that it does *not* do: -// := .{} +// +// := .{} // // …as that does not work for enum types. func NewVariableQualified(varName string, qualifier string, structName string) dst.Stmt { @@ -109,10 +110,12 @@ func NewVariableQualified(varName string, qualifier string, structName string) d // with its default value. // // For example: -// var +// +// var // // Note that it does *not* do: -// := {} +// +// := {} // // …as that does not work for enum types. func NewVariable(varName string, structName string) dst.Stmt { @@ -135,8 +138,7 @@ func NewVariableWithType(varName string, varType dst.Expr) dst.Stmt { // LocalVariableDeclaration performs a local variable declaration for use within a method // -// var -// +// var func LocalVariableDeclaration(ident string, typ dst.Expr, comment string) *dst.DeclStmt { return &dst.DeclStmt{ Decl: VariableDeclaration(ident, typ, comment), @@ -145,8 +147,8 @@ func LocalVariableDeclaration(ident string, typ dst.Expr, comment string) *dst.D // VariableDeclaration performs a global variable declaration // -// // -// var +// // +// var // // For a LocalVariable within a method, use LocalVariableDeclaration() to create an ast.Stmt instead func VariableDeclaration(ident string, typ dst.Expr, comment string) *dst.GenDecl { @@ -169,8 +171,7 @@ func VariableDeclaration(ident string, typ dst.Expr, comment string) *dst.GenDec // TypeAssert returns an assignment statement with a type assertion // -// , ok := .() -// +// , ok := .() func TypeAssert(lhs dst.Expr, rhs dst.Expr, typ dst.Expr) *dst.AssignStmt { return &dst.AssignStmt{ Lhs: []dst.Expr{ @@ -192,7 +193,6 @@ func TypeAssert(lhs dst.Expr, rhs dst.Expr, typ dst.Expr) *dst.AssignStmt { // if ok { // return // } -// func ReturnIfOk(returns ...dst.Expr) *dst.IfStmt { return ReturnIfExpr(dst.NewIdent("ok"), returns...) } @@ -202,7 +202,6 @@ func ReturnIfOk(returns ...dst.Expr) *dst.IfStmt { // if !ok { // return // } -// func ReturnIfNotOk(returns ...dst.Expr) *dst.IfStmt { return ReturnIfExpr( &dst.UnaryExpr{ @@ -214,10 +213,9 @@ func ReturnIfNotOk(returns ...dst.Expr) *dst.IfStmt { // ReturnIfNil checks if a variable is nil and if it is returns // -// if == nil { -// return +// if == nil { +// return // } -// func ReturnIfNil(toCheck dst.Expr, returns ...dst.Expr) dst.Stmt { return ReturnIfExpr( AreEqual(toCheck, Nil()), @@ -226,10 +224,9 @@ func ReturnIfNil(toCheck dst.Expr, returns ...dst.Expr) dst.Stmt { // ReturnIfNotNil checks if a variable is not nil and if it is returns // -// if != nil { -// return +// if != nil { +// return // } -// func ReturnIfNotNil(toCheck dst.Expr, returns ...dst.Expr) dst.Stmt { return ReturnIfExpr( AreNotEqual(toCheck, Nil()), @@ -239,9 +236,8 @@ func ReturnIfNotNil(toCheck dst.Expr, returns ...dst.Expr) dst.Stmt { // ReturnIfExpr returns if the expression evaluates as true // // if { -// return +// return // } -// func ReturnIfExpr(cond dst.Expr, returns ...dst.Expr) *dst.IfStmt { if len(returns) == 0 { panic("Expected at least 1 return for ReturnIfOk") @@ -262,7 +258,6 @@ func ReturnIfExpr(cond dst.Expr, returns ...dst.Expr) *dst.IfStmt { // FormatError produces a call to fmt.Errorf with the given format string and args // // fmt.Errorf(, ) -// func FormatError(fmtPackage string, formatString string, args ...dst.Expr) dst.Expr { var callArgs []dst.Expr callArgs = append( @@ -275,7 +270,6 @@ func FormatError(fmtPackage string, formatString string, args ...dst.Expr) dst.E // AddrOf returns a statement that gets the address of the provided expression. // // & -// func AddrOf(expr dst.Expr) *dst.UnaryExpr { return &dst.UnaryExpr{ Op: token.AND, @@ -299,7 +293,6 @@ func AsReference(expr dst.Expr) dst.Expr { // Dereference returns a statement that dereferences the pointer returned by the provided expression // // * -// func Dereference(expr dst.Expr) dst.Expr { return &dst.StarExpr{ X: dst.Clone(expr).(dst.Expr), @@ -308,9 +301,9 @@ func Dereference(expr dst.Expr) dst.Expr { // Returns creates a return statement with one or more expressions, of the form // -// return -// or return , , ... +// return // +// or return , , ... func Returns(returns ...dst.Expr) dst.Stmt { return &dst.ReturnStmt{ Decs: dst.ReturnStmtDecorations{ @@ -324,9 +317,8 @@ func Returns(returns ...dst.Expr) dst.Stmt { // ReturnNoError creates a return nil statement for when no error occurs // -// // No error -// return nil -// +// // No error +// return nil func ReturnNoError() dst.Stmt { result := Returns(Nil()) result.Decorations().Before = dst.EmptyLine @@ -350,7 +342,6 @@ func WrappedErrorf(errorsPackage string, template string, args ...interface{}) d // QualifiedTypeName generates a reference to a type within an imported package // // . -// func QualifiedTypeName(pkg string, name string) *dst.SelectorExpr { return &dst.SelectorExpr{ X: dst.NewIdent(pkg), @@ -361,7 +352,6 @@ func QualifiedTypeName(pkg string, name string) *dst.SelectorExpr { // Selector generates a field reference into an existing expression // // ..(.…) -// func Selector(expr dst.Expr, names ...string) *dst.SelectorExpr { exprs := []dst.Expr{dst.Clone(expr).(dst.Expr)} for _, name := range names { @@ -379,7 +369,6 @@ func Selector(expr dst.Expr, names ...string) *dst.SelectorExpr { // AreEqual generates a == comparison between the two expressions // // == -// func AreEqual(lhs dst.Expr, rhs dst.Expr) *dst.BinaryExpr { return BinaryExpr(lhs, token.EQL, rhs) } @@ -387,7 +376,6 @@ func AreEqual(lhs dst.Expr, rhs dst.Expr) *dst.BinaryExpr { // AreNotEqual generates a != comparison between the two expressions // // != -// func AreNotEqual(lhs dst.Expr, rhs dst.Expr) *dst.BinaryExpr { return BinaryExpr(lhs, token.NEQ, rhs) } diff --git a/v2/tools/generator/internal/astbuilder/calls.go b/v2/tools/generator/internal/astbuilder/calls.go index 1c4f66b608..2b40bec65e 100644 --- a/v2/tools/generator/internal/astbuilder/calls.go +++ b/v2/tools/generator/internal/astbuilder/calls.go @@ -12,7 +12,6 @@ import ( // CallFunc creates an expression to call a function with specified arguments // // (...) -// func CallFunc(funcName string, arguments ...dst.Expr) *dst.CallExpr { return createCallExpr(dst.NewIdent(funcName), arguments...) } @@ -21,7 +20,6 @@ func CallFunc(funcName string, arguments ...dst.Expr) *dst.CallExpr { // arguments // // .(arguments...) -// func CallQualifiedFunc(qualifier string, funcName string, arguments ...dst.Expr) *dst.CallExpr { return createCallExpr( &dst.SelectorExpr{ @@ -34,7 +32,6 @@ func CallQualifiedFunc(qualifier string, funcName string, arguments ...dst.Expr) // CallExpr creates an expression to call the named function with the specified arguments // // .(arguments...) -// func CallExpr(expr dst.Expr, funcName string, arguments ...dst.Expr) *dst.CallExpr { var receiver dst.Expr = expr if star, ok := expr.(*dst.StarExpr); ok { diff --git a/v2/tools/generator/internal/astbuilder/conditions.go b/v2/tools/generator/internal/astbuilder/conditions.go index b0c3cbe0ac..47c7ed55c3 100644 --- a/v2/tools/generator/internal/astbuilder/conditions.go +++ b/v2/tools/generator/internal/astbuilder/conditions.go @@ -13,10 +13,9 @@ import ( // SimpleIf creates a simple if statement with multiple statements // -// if { -// -// } -// +// if { +// +// } func SimpleIf(condition dst.Expr, statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: condition, @@ -26,12 +25,12 @@ func SimpleIf(condition dst.Expr, statements ...dst.Stmt) *dst.IfStmt { // SimpleIfElse creates a simple if else statement. Each branch may contain multiple statements. // -// if { -// -// } else { -// -// } +// if { +// +// } else { // +// +// } func SimpleIfElse(condition dst.Expr, trueBranch []dst.Stmt, falseBranch []dst.Stmt) *dst.IfStmt { result := &dst.IfStmt{ Cond: condition, @@ -44,10 +43,9 @@ func SimpleIfElse(condition dst.Expr, trueBranch []dst.Stmt, falseBranch []dst.S // IfEqual executes a series of statements if the supplied expressions are // -// if == { -// -// } -// +// if == { +// +// } func IfEqual(left dst.Expr, right dst.Expr, statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: AreEqual(left, right), @@ -57,10 +55,9 @@ func IfEqual(left dst.Expr, right dst.Expr, statements ...dst.Stmt) *dst.IfStmt // IfNotNil executes a series of statements if the supplied expression is not nil // -// if != nil { -// -// } -// +// if != nil { +// +// } func IfNotNil(toCheck dst.Expr, statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: NotNil(toCheck), @@ -70,10 +67,9 @@ func IfNotNil(toCheck dst.Expr, statements ...dst.Stmt) *dst.IfStmt { // IfNil executes a series of statements if the supplied expression is nil // -// if != nil { -// -// } -// +// if != nil { +// +// } func IfNil(toCheck dst.Expr, statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: AreEqual(toCheck, Nil()), @@ -86,7 +82,6 @@ func IfNil(toCheck dst.Expr, statements ...dst.Stmt) *dst.IfStmt { // if ok { // // } -// func IfOk(statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: dst.NewIdent("ok"), @@ -99,7 +94,6 @@ func IfOk(statements ...dst.Stmt) *dst.IfStmt { // if !ok { // // } -// func IfNotOk(statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Cond: &dst.UnaryExpr{ @@ -116,10 +110,9 @@ func IfNotOk(statements ...dst.Stmt) *dst.IfStmt { // local is the name of the local variable to initialize // statements form the body of the if statement // -// if , ok := .(); ok { -// -// } -// +// if , ok := .(); ok { +// +// } func IfType(expr dst.Expr, typeExpr dst.Expr, local string, statements ...dst.Stmt) *dst.IfStmt { return &dst.IfStmt{ Init: TypeAssert(dst.NewIdent(local), expr, typeExpr), diff --git a/v2/tools/generator/internal/astbuilder/func_details.go b/v2/tools/generator/internal/astbuilder/func_details.go index 581d8cf8e6..3fc5e27682 100644 --- a/v2/tools/generator/internal/astbuilder/func_details.go +++ b/v2/tools/generator/internal/astbuilder/func_details.go @@ -51,9 +51,10 @@ func NewTestFuncDetails(testingPackage string, testName string, body ...dst.Stmt } // DefineFunc defines a function (header, body, etc), like: -// +// +// // func ( ) () () { -// +// // } func (fn *FuncDetails) DefineFunc() *dst.FuncDecl { diff --git a/v2/tools/generator/internal/astbuilder/maps.go b/v2/tools/generator/internal/astbuilder/maps.go index 46381b5637..b1b27d6800 100644 --- a/v2/tools/generator/internal/astbuilder/maps.go +++ b/v2/tools/generator/internal/astbuilder/maps.go @@ -13,8 +13,7 @@ import ( // MakeMap returns the call expression for making a map // -// make(map[]) -// +// make(map[]) func MakeMap(key dst.Expr, value dst.Expr) *dst.CallExpr { return &dst.CallExpr{ Fun: dst.NewIdent("make"), @@ -29,8 +28,7 @@ func MakeMap(key dst.Expr, value dst.Expr) *dst.CallExpr { // MakeMapWithCapacity returns the call expression for making a map with a predefined capacity // -// make(map[], ) -// +// make(map[], ) func MakeMapWithCapacity(key dst.Expr, value dst.Expr, capacity dst.Expr) *dst.CallExpr { return &dst.CallExpr{ Fun: dst.NewIdent("make"), @@ -46,8 +44,7 @@ func MakeMapWithCapacity(key dst.Expr, value dst.Expr, capacity dst.Expr) *dst.C // InsertMap returns an assignment statement for inserting an item into a map // -// [] = -// +// [] = func InsertMap(mapExpr dst.Expr, key dst.Expr, rhs dst.Expr) *dst.AssignStmt { return SimpleAssignment( &dst.IndexExpr{ @@ -60,10 +57,9 @@ func InsertMap(mapExpr dst.Expr, key dst.Expr, rhs dst.Expr) *dst.AssignStmt { // IterateOverMapWithValue creates a statement to iterate over the content of a map using the // specified identifiers for each key and value found. // -// for , := range { -// -// } -// +// for , := range { +// +// } func IterateOverMapWithValue(key string, item string, mapExpr dst.Expr, statements ...dst.Stmt) *dst.RangeStmt { return &dst.RangeStmt{ Key: dst.NewIdent(key), diff --git a/v2/tools/generator/internal/astbuilder/slices.go b/v2/tools/generator/internal/astbuilder/slices.go index 2908efb5f3..5f89d53eee 100644 --- a/v2/tools/generator/internal/astbuilder/slices.go +++ b/v2/tools/generator/internal/astbuilder/slices.go @@ -14,7 +14,6 @@ import ( // MakeSlice returns the call expression for making a slice // // make([]) -// func MakeSlice(listType dst.Expr, len dst.Expr) *dst.CallExpr { return &dst.CallExpr{ Fun: dst.NewIdent("make"), @@ -28,7 +27,6 @@ func MakeSlice(listType dst.Expr, len dst.Expr) *dst.CallExpr { // AppendItemToSlice returns a statement to append a single item to a slice // // = append(, ) -// func AppendItemToSlice(lhs dst.Expr, rhs dst.Expr) dst.Stmt { return SimpleAssignment( dst.Clone(lhs).(dst.Expr), @@ -38,7 +36,6 @@ func AppendItemToSlice(lhs dst.Expr, rhs dst.Expr) dst.Stmt { // AppendItemsToSlice returns a statement to append many individual items to a slice // // = append(, , , , ...) -// func AppendItemsToSlice(lhs dst.Expr, rhs ...dst.Expr) dst.Stmt { args := make([]dst.Expr, 0, len(rhs)+1) args = append(args, lhs) @@ -54,7 +51,6 @@ func AppendItemsToSlice(lhs dst.Expr, rhs ...dst.Expr) dst.Stmt { // AppendSliceToSlice returns a statement to append a slice to another slice // // = append(, ...) -// func AppendSliceToSlice(lhs dst.Expr, rhs dst.Expr) dst.Stmt { f := CallFunc("append", dst.Clone(lhs).(dst.Expr), dst.Clone(rhs).(dst.Expr)) f.Ellipsis = true @@ -66,10 +62,9 @@ func AppendSliceToSlice(lhs dst.Expr, rhs dst.Expr) dst.Stmt { // IterateOverSlice creates a statement to iterate over the content of a list using the specified // identifier for each element in the list // -// for _, := range { -// -// } -// +// for _, := range { +// +// } func IterateOverSlice(item string, list dst.Expr, statements ...dst.Stmt) *dst.RangeStmt { return &dst.RangeStmt{ Key: dst.NewIdent("_"), @@ -83,10 +78,9 @@ func IterateOverSlice(item string, list dst.Expr, statements ...dst.Stmt) *dst.R // IterateOverSliceWithIndex creates a statement to iterate over the content of a list using the specified // identifiers for each index and element in the list // -// for , := range { -// -// } -// +// for , := range { +// +// } func IterateOverSliceWithIndex(index string, item string, list dst.Expr, statements ...dst.Stmt) *dst.RangeStmt { return &dst.RangeStmt{ Key: dst.NewIdent(index), diff --git a/v2/tools/generator/internal/astmodel/conversion_function_builder.go b/v2/tools/generator/internal/astmodel/conversion_function_builder.go index a8284db834..bfee9f8ec4 100644 --- a/v2/tools/generator/internal/astmodel/conversion_function_builder.go +++ b/v2/tools/generator/internal/astmodel/conversion_function_builder.go @@ -176,7 +176,8 @@ func (builder *ConversionFunctionBuilder) BuildConversion(params ConversionParam // IdentityConvertComplexOptionalProperty handles conversion for optional properties with complex elements // This function generates code that looks like this: -// if != nil { +// +// if != nil { // // = & // } @@ -222,7 +223,8 @@ func IdentityConvertComplexOptionalProperty(builder *ConversionFunctionBuilder, // IdentityConvertComplexArrayProperty handles conversion for array properties with complex elements // This function generates code that looks like this: -// for _, item := range { +// +// for _, item := range { // // = append(, ) // } @@ -293,10 +295,11 @@ func IdentityConvertComplexArrayProperty(builder *ConversionFunctionBuilder, par // IdentityConvertComplexMapProperty handles conversion for map properties with complex values. // This function panics if the map keys are not primitive types. // This function generates code that looks like this: -// if != nil { +// +// if != nil { // = make(map[, len()) // for key, value := range { -// +// // [key] = // } // } @@ -388,6 +391,7 @@ func IdentityConvertComplexMapProperty(builder *ConversionFunctionBuilder, param // Note that because this handler is dealing with TypeName's and not Optional, it is safe to // perform a simple assignment rather than a copy. // This function generates code that looks like this: +// // func IdentityAssignTypeName(_ *ConversionFunctionBuilder, params ConversionParameters) []dst.Stmt { destinationType, ok := params.DestinationType.(TypeName) @@ -474,15 +478,17 @@ func AssignToOptional(builder *ConversionFunctionBuilder, params ConversionParam // AssignFromOptional assigns address of source to destination. // This function generates code that looks like this, for simple conversions: -// if ( != nil) { -// * -// } +// +// if ( != nil) { +// * +// } // // or: -// if ( != nil) { -// Temp := convert(*) -// Temp -// } +// +// if ( != nil) { +// Temp := convert(*) +// Temp +// } func AssignFromOptional(builder *ConversionFunctionBuilder, params ConversionParameters) []dst.Stmt { optSrc, ok := params.SourceType.(*OptionalType) if !ok { @@ -556,7 +562,8 @@ func IdentityAssignValidatedTypeSource(builder *ConversionFunctionBuilder, param // IdentityDeepCopyJSON special cases copying JSON-type fields to call the DeepCopy method. // It generates code that looks like: -// = *.DeepCopy() +// +// = *.DeepCopy() func IdentityDeepCopyJSON(_ *ConversionFunctionBuilder, params ConversionParameters) []dst.Stmt { if !TypeEquals(params.DestinationType, JSONType) { return nil @@ -585,8 +592,9 @@ func AssignmentHandlerAssign(lhs dst.Expr, rhs dst.Expr) dst.Stmt { // CreateLocal creates an unused local variable name. // Names are chosen according to the following rules: -// 1. If there is no local variable with the name, use that. -// 2. If there is a local variable with the name, create a variable name . +// 1. If there is no local variable with the name, use that. +// 2. If there is a local variable with the name, create a variable name . +// // In the case that is also taken append numbers to the end in standard KnownLocalsSet fashion. // Note that this function trims numbers on the right hand side of nameHint, so a nameHint of "item1" will get a local // variable named item. diff --git a/v2/tools/generator/internal/astmodel/identifier_factory.go b/v2/tools/generator/internal/astmodel/identifier_factory.go index 46c3a11df8..eca076a115 100644 --- a/v2/tools/generator/internal/astmodel/identifier_factory.go +++ b/v2/tools/generator/internal/astmodel/identifier_factory.go @@ -329,11 +329,11 @@ func simplifyName(context string, name string) string { // sliceIntoWords splits the provided identifier into a slice of individual words. // A word is defined by one of the following: -// 1. A space ("a test" becomes "a" and "test") -// 2. A transition between lowercase and uppercase ("aWord" becomes "a" and "Word") -// 3. A transition between multiple uppercase letters and a lowercase letter ("XMLDocument" becomes "XML" and "Document") -// 4. A transition between a letter and a digit ("book12" becomes "book" and "12") -// 5. A transition between a digit and a letter ("12monkeys" becomes "12" and "monkeys") +// 1. A space ("a test" becomes "a" and "test") +// 2. A transition between lowercase and uppercase ("aWord" becomes "a" and "Word") +// 3. A transition between multiple uppercase letters and a lowercase letter ("XMLDocument" becomes "XML" and "Document") +// 4. A transition between a letter and a digit ("book12" becomes "book" and "12") +// 5. A transition between a digit and a letter ("12monkeys" becomes "12" and "monkeys") func sliceIntoWords(identifier string) []string { // Trim any leading and trailing spaces to make our life easier later identifier = strings.Trim(identifier, " ") diff --git a/v2/tools/generator/internal/astmodel/type_merger.go b/v2/tools/generator/internal/astmodel/type_merger.go index e3d68dc3c5..3213fe3a72 100644 --- a/v2/tools/generator/internal/astmodel/type_merger.go +++ b/v2/tools/generator/internal/astmodel/type_merger.go @@ -15,7 +15,7 @@ import ( // // Conceptually it takes (via Add) a list of functions of the form: // -// func ([ctx interface{},] left {some Type}, right {some Type}) (Type, error) +// func ([ctx interface{},] left {some Type}, right {some Type}) (Type, error) // // where `left` and `right` can be concrete types that implement the `Type` interface. // diff --git a/v2/tools/generator/internal/astmodel/type_test.go b/v2/tools/generator/internal/astmodel/type_test.go index 7e5a9a5eef..63b3784cff 100644 --- a/v2/tools/generator/internal/astmodel/type_test.go +++ b/v2/tools/generator/internal/astmodel/type_test.go @@ -76,7 +76,7 @@ func TestWriteDebugDescription(t *testing.T) { } // TestWriteDebugDescriptionNils ensures that WriteDebugDescription() doesn't panic even if called on a nil reference, -//(this is a diagnostic method that should pretty much always do something useful) +// (this is a diagnostic method that should pretty much always do something useful) func TestWriteDebugDescriptionNils(t *testing.T) { t.Parallel() g := NewGomegaWithT(t) diff --git a/v2/tools/generator/internal/astmodel/type_visitor_builder.go b/v2/tools/generator/internal/astmodel/type_visitor_builder.go index f6ea1f93bc..1b68cba2b2 100644 --- a/v2/tools/generator/internal/astmodel/type_visitor_builder.go +++ b/v2/tools/generator/internal/astmodel/type_visitor_builder.go @@ -28,7 +28,6 @@ import "fmt" // VisitObjectType = func(this TypeVisitor, it *ObjectType, ctx interface{}) (Type, error) // Works // VisitObjectType = func(it TypeName) Type // Fails - parameter is not an *ObjectType // VisitObjectType = func(this TypeVisitor, it TypeName, ctx interface{}) (ObjectType, error) // Fails -return is not Type -// type TypeVisitorBuilder struct { VisitTypeName interface{} VisitOneOfType interface{} diff --git a/v2/tools/generator/internal/codegen/embeddedresources/remover.go b/v2/tools/generator/internal/codegen/embeddedresources/remover.go index fd99c81046..815016b859 100644 --- a/v2/tools/generator/internal/codegen/embeddedresources/remover.go +++ b/v2/tools/generator/internal/codegen/embeddedresources/remover.go @@ -32,26 +32,27 @@ func (e resourceRemovalVisitorContext) WithMoreDepth() resourceRemovalVisitorCon // EmbeddedResourceRemover uses a variety of heuristics to remove resources that are embedded inside other resources. // There are a number of different kinds of embeddings: -// 1. A "Properties" embedding. When we process the Azure JSON schema/Swagger we manufacture a "Spec" -// type that doesn't exist in the JSON schema/Swagger. In the JSON schema the resource itself must comply with ARM -// resource requirements, meaning that all of the RP specific properties are stored in the "Properties" -// property which for the sake of example we will say has type "R1Properties". -// Other resources which have a property somewhere in their type hierarchy with that same "R1Properties" -// type are actually embedding the R1 resource entirely inside themselves. Since the R1 resource is its own -// resource it doesn't make sense to have it embedded inside another resource in Kubernetes. These embeddings -// should really just be cross resource references. This pipeline finds such embeddings and removes them. A concrete -// example of one such embedding is -// v20181001 Microsoft.Networking Connection.Spec.Properties.LocalNetworkGateway2.Properties. -// The LocalNetworkGateway2 property is of type "LocalNetworkGateway" which is itself a resource. -// The ideal shape of Connection.Spec.Properties.LocalNetworkGate2 would just be a reference to a -// LocalNetworkGateway resource. -// 2. A subresource embedding. For the same reasons above, embedded subresources don't make sense in Kubernetes. -// In the case of embedded subresources, the ideal shape would be a complete removal of the reference. We forbid -// parent resources directly referencing child resources as it complicates the Watches scenario for each resource -// reconciler. It's also not a common pattern in Kubernetes - usually you can identify children for a -// given parent via a label. An example of this type of embedding is -// v20180601 Microsoft.Networking RouteTable.Spec.Properties.Routes. The Routes property is of type RouteTableRoutes -// which is a child resource of RouteTable. +// 1. A "Properties" embedding. When we process the Azure JSON schema/Swagger we manufacture a "Spec" +// type that doesn't exist in the JSON schema/Swagger. In the JSON schema the resource itself must comply with ARM +// resource requirements, meaning that all of the RP specific properties are stored in the "Properties" +// property which for the sake of example we will say has type "R1Properties". +// Other resources which have a property somewhere in their type hierarchy with that same "R1Properties" +// type are actually embedding the R1 resource entirely inside themselves. Since the R1 resource is its own +// resource it doesn't make sense to have it embedded inside another resource in Kubernetes. These embeddings +// should really just be cross resource references. This pipeline finds such embeddings and removes them. A concrete +// example of one such embedding is +// v20181001 Microsoft.Networking Connection.Spec.Properties.LocalNetworkGateway2.Properties. +// The LocalNetworkGateway2 property is of type "LocalNetworkGateway" which is itself a resource. +// The ideal shape of Connection.Spec.Properties.LocalNetworkGate2 would just be a reference to a +// LocalNetworkGateway resource. +// 2. A subresource embedding. For the same reasons above, embedded subresources don't make sense in Kubernetes. +// In the case of embedded subresources, the ideal shape would be a complete removal of the reference. We forbid +// parent resources directly referencing child resources as it complicates the Watches scenario for each resource +// reconciler. It's also not a common pattern in Kubernetes - usually you can identify children for a +// given parent via a label. An example of this type of embedding is +// v20180601 Microsoft.Networking RouteTable.Spec.Properties.Routes. The Routes property is of type RouteTableRoutes +// which is a child resource of RouteTable. +// // Note that even though the above examples do not include Status definitions, the same rules apply to Status definitions, with // the only difference being that for Status definitions the resource reference in Swagger (the source of the Status definitions) // is to the Status type (as opposed to the "Properties" type for Spec). diff --git a/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go b/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go index 083fab9ddd..7659a46a97 100644 --- a/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go +++ b/v2/tools/generator/internal/codegen/pipeline/apply_defaulter_and_validator_interfaces.go @@ -196,20 +196,21 @@ func validateConfigMapDestinations(k *functions.ResourceFunction, codeGeneration } // validateOperatorSpecSliceBody helps generate the body of the validateResourceReferences function: -// func (account *DatabaseAccount) validateConfigMapDestinations() error { -// if .Spec.OperatorSpec == nil { -// return nil -// } -// if .Spec.OperatorSpec. == nil { -// return nil -// } -// toValidate := []*{ -// account.Spec.OperatorSpec.ConfigMaps.ClientId, -// account.Spec.OperatorSpec.ConfigMaps.PrincipalId, -// ... -// } -// return genruntime.(toValidate) -// } +// +// func (account *DatabaseAccount) validateConfigMapDestinations() error { +// if .Spec.OperatorSpec == nil { +// return nil +// } +// if .Spec.OperatorSpec. == nil { +// return nil +// } +// toValidate := []*{ +// account.Spec.OperatorSpec.ConfigMaps.ClientId, +// account.Spec.OperatorSpec.ConfigMaps.PrincipalId, +// ... +// } +// return genruntime.(toValidate) +// } func validateOperatorSpecSliceBody( codeGenerationContext *astmodel.CodeGenerationContext, resource *astmodel.ResourceType, diff --git a/v2/tools/generator/internal/codegen/pipeline/crossplane_add_for_provider.go b/v2/tools/generator/internal/codegen/pipeline/crossplane_add_for_provider.go index 252a9e9284..0983ccefe8 100644 --- a/v2/tools/generator/internal/codegen/pipeline/crossplane_add_for_provider.go +++ b/v2/tools/generator/internal/codegen/pipeline/crossplane_add_for_provider.go @@ -70,9 +70,9 @@ func nestSpecIntoForProvider( // nestType nests the contents of the provided outerType into a property with the given nestedPropertyName whose // type is the given nestedTypeName. The result is a type that looks something like the following: // -// type struct { -// `yaml:""` -// } +// type struct { +// `yaml:""` +// } func nestType( idFactory astmodel.IdentifierFactory, definitions astmodel.TypeDefinitionSet, diff --git a/v2/tools/generator/internal/codegen/pipeline/detect_skipping_properties.go b/v2/tools/generator/internal/codegen/pipeline/detect_skipping_properties.go index 67c245ef6b..325691aa5e 100644 --- a/v2/tools/generator/internal/codegen/pipeline/detect_skipping_properties.go +++ b/v2/tools/generator/internal/codegen/pipeline/detect_skipping_properties.go @@ -46,7 +46,6 @@ const DetectSkippingPropertiesStageID = "detectSkippingProperties" // Additional complexities: // - We need to handle type renaming between versions. // - When introduced, we will also need to handle property renaming between versions -// func DetectSkippingProperties() *Stage { return NewStage( DetectSkippingPropertiesStageID, diff --git a/v2/tools/generator/internal/codegen/pipeline/flatten_properties.go b/v2/tools/generator/internal/codegen/pipeline/flatten_properties.go index cadd7ee44c..0e6a14d460 100644 --- a/v2/tools/generator/internal/codegen/pipeline/flatten_properties.go +++ b/v2/tools/generator/internal/codegen/pipeline/flatten_properties.go @@ -101,7 +101,6 @@ func removeFlatten(t astmodel.Type) astmodel.Type { // We will flatten it and rename the second property, resulting in: // - `Type` // - `PropertiesType` -// func fixCollisions(props []*astmodel.PropertyDefinition) []*astmodel.PropertyDefinition { names := make(map[astmodel.PropertyName]int) diff --git a/v2/tools/generator/internal/codegen/pipeline/remove_status_property_validations.go b/v2/tools/generator/internal/codegen/pipeline/remove_status_property_validations.go index 9e5c70db5b..16e8722ae9 100644 --- a/v2/tools/generator/internal/codegen/pipeline/remove_status_property_validations.go +++ b/v2/tools/generator/internal/codegen/pipeline/remove_status_property_validations.go @@ -22,13 +22,14 @@ const RemoveStatusPropertyValidationsStageID = "removeStatusPropertyValidation" // This is required because Status is retrieved directly from the ARM API, and there are // cases where ARM might return something that isn't actually "valid" according to the validation, // but makes sense in context. Some examples: -// 1. Status has a modelAsString enum with 2 values, but in a future API version, a 3rd value is added. -// The fact that the enum is modelAsString allows the service to return the new 3rd value even in old API -// versions. -// 2. Status has an int that must be between 10 and 20. In a future API version, that restriction is relaxed and -// the same int can now be between 0 and 50. -// 3. A bug in the services Swagger specification causes the service to accept enums with any case, but always -// return the enum all uppercase +// 1. Status has a modelAsString enum with 2 values, but in a future API version, a 3rd value is added. +// The fact that the enum is modelAsString allows the service to return the new 3rd value even in old API +// versions. +// 2. Status has an int that must be between 10 and 20. In a future API version, that restriction is relaxed and +// the same int can now be between 0 and 50. +// 3. A bug in the services Swagger specification causes the service to accept enums with any case, but always +// return the enum all uppercase +// // In the above cases, if we left validation on the Status types, we would be unable to persist the content // returned by the service (apiserver will reject it as not matching the OpenAPI schema). This could be a problem // in cases where the resource was created via some other means and then imported into diff --git a/v2/tools/generator/internal/codegen/pipeline/resource_registration_file.go b/v2/tools/generator/internal/codegen/pipeline/resource_registration_file.go index 6c697c2361..c08b7fedce 100644 --- a/v2/tools/generator/internal/codegen/pipeline/resource_registration_file.go +++ b/v2/tools/generator/internal/codegen/pipeline/resource_registration_file.go @@ -175,14 +175,15 @@ func orderByFunctionName(functions []*functions.IndexRegistrationFunction) func( } // createGetKnownTypesFunc creates a getKnownTypes function that returns all known types: -// func getKnownTypes() []client.Object { -// var result []client.Object -// result = append(result, new(.)) -// result = append(result, new(.)) -// result = append(result, new(.)) -// ... -// return result -// } +// +// func getKnownTypes() []client.Object { +// var result []client.Object +// result = append(result, new(.)) +// result = append(result, new(.)) +// result = append(result, new(.)) +// ... +// return result +// } func createGetKnownTypesFunc(codeGenerationContext *astmodel.CodeGenerationContext, resources []astmodel.TypeName) (dst.Decl, error) { funcName := "getKnownTypes" funcComment := "returns the list of all types." @@ -236,27 +237,28 @@ func createGetKnownTypesFunc(codeGenerationContext *astmodel.CodeGenerationConte } // createGetKnownStorageTypesFunc creates a getKnownStorageTypes function that returns all storage types: -// func getKnownStorageTypes() []registration.StorageType { -// var result []*registration.StorageType -// result = append(result, ®istration.StorageType{ -// Obj: new(.), -// Indexes: []registration.Index{ -// { -// Key: , -// Func: , -// }, +// +// func getKnownStorageTypes() []registration.StorageType { +// var result []*registration.StorageType +// result = append(result, ®istration.StorageType{ +// Obj: new(.), +// Indexes: []registration.Index{ +// { +// Key: , +// Func: , // }, -// Watches: []registration.Watch{ -// { -// Src: (usually corev1.Secret{}), -// }, +// }, +// Watches: []registration.Watch{ +// { +// Src: (usually corev1.Secret{}), // }, -// }) -// result = append(result, registration.StorageType{Obj: new(.)}) -// result = append(result, registration.StorageType{Obj: new(.)}) -// ... -// return result -// } +// }, +// }) +// result = append(result, registration.StorageType{Obj: new(.)}) +// result = append(result, registration.StorageType{Obj: new(.)}) +// ... +// return result +// } func (r *ResourceRegistrationFile) createGetKnownStorageTypesFunc( codeGenerationContext *astmodel.CodeGenerationContext, ) dst.Decl { @@ -375,14 +377,15 @@ func (r *ResourceRegistrationFile) createGetResourceExtensions(context *astmodel } // createCreateSchemeFunc creates a createScheme() function like: -// func createScheme() *runtime.Scheme { -// scheme := runtime.NewScheme() -// _ = clientgoscheme.AddToScheme(scheme) -// _ = batchv20170901.AddToScheme(scheme) -// _ = documentdbv20150408.AddToScheme(scheme) -// _ = storagev20190401.AddToScheme(scheme) -// return scheme -// } +// +// func createScheme() *runtime.Scheme { +// scheme := runtime.NewScheme() +// _ = clientgoscheme.AddToScheme(scheme) +// _ = batchv20170901.AddToScheme(scheme) +// _ = documentdbv20150408.AddToScheme(scheme) +// _ = storagev20190401.AddToScheme(scheme) +// return scheme +// } func (r *ResourceRegistrationFile) createCreateSchemeFunc(codeGenerationContext *astmodel.CodeGenerationContext) (dst.Decl, error) { runtime, err := codeGenerationContext.GetImportedPackageName(astmodel.APIMachineryRuntimeReference) if err != nil { @@ -500,6 +503,7 @@ func (r *ResourceRegistrationFile) makeWatchesExpr(typeName astmodel.TypeName, c } // makeSimpleWatchesExpr generates code for a Watches expression: +// // { // Src: &source.Kind{Type: &{}}, // MakeEventHandler: ([]string{}, &{}), diff --git a/v2/tools/generator/internal/codegen/pipeline/stage.go b/v2/tools/generator/internal/codegen/pipeline/stage.go index 459c1538a2..a569971dbd 100644 --- a/v2/tools/generator/internal/codegen/pipeline/stage.go +++ b/v2/tools/generator/internal/codegen/pipeline/stage.go @@ -146,7 +146,6 @@ func (stage *Stage) RequiresPrerequisiteStages(prerequisites ...string) { // Post-requisites are thus not completely isomorphic with RequiresPrerequisiteStages as there may be supporting stages that are // sometimes omitted from execution when targeting different outcomes. Having both pre- and post-requisites allows the // dependencies to drop out cleanly when different stages are present. -// func (stage *Stage) RequiresPostrequisiteStages(postrequisites ...string) { if len(stage.postrequisites) > 0 { panic(fmt.Sprintf( diff --git a/v2/tools/generator/internal/codegen/pipeline/status_from_swagger.go b/v2/tools/generator/internal/codegen/pipeline/status_from_swagger.go index 308bf9fadf..53288c53b6 100644 --- a/v2/tools/generator/internal/codegen/pipeline/status_from_swagger.go +++ b/v2/tools/generator/internal/codegen/pipeline/status_from_swagger.go @@ -28,7 +28,8 @@ import ( "github.com/Azure/azure-service-operator/v2/tools/generator/internal/jsonast" ) -/* addStatusFromSwagger creates a PipelineStage to add status information into the generated resources. +/* + addStatusFromSwagger creates a PipelineStage to add status information into the generated resources. This information is derived from the Azure Swagger specifications. We parse the Swagger specs and look for any actions that appear to be ARM resources (have PUT methods with types we can use and appropriate names in the @@ -39,7 +40,6 @@ Next, we walk over all the resources we are currently generating CRDs for and at a match for the resource in the status information we have parsed. If we locate a match, it is added to the Status field of the Resource type, after we have renamed all the status types to avoid any conflicts with existing Spec types that have already been defined. - */ func AddStatusFromSwagger(idFactory astmodel.IdentifierFactory, config *config.Configuration) *Stage { return NewLegacyStage( diff --git a/v2/tools/generator/internal/codegen/pipeline/unroll_recursive_types.go b/v2/tools/generator/internal/codegen/pipeline/unroll_recursive_types.go index fe9be884e2..e0b7dc6942 100644 --- a/v2/tools/generator/internal/codegen/pipeline/unroll_recursive_types.go +++ b/v2/tools/generator/internal/codegen/pipeline/unroll_recursive_types.go @@ -18,22 +18,28 @@ import ( const UnrollRecursiveTypesStageID = "unrollRecursiveTypes" // UnrollRecursiveTypes finds types that reference themselves and "unrolls" the reference. So a type that looks like: -// type Error struct { -// code string -// message string -// errors []Error -// } +// +// type Error struct { +// code string +// message string +// errors []Error +// } +// // gets unrolled to look like: -// type Error struct { -// code string -// message string -// errors []Error_Unrolled -// } +// +// type Error struct { +// code string +// message string +// errors []Error_Unrolled +// } +// // where Error_Unrolled looks like: -// type Error_Unrolled struct { -// code string -// message string -// } +// +// type Error_Unrolled struct { +// code string +// message string +// } +// // The recursive references must be removed because // controller-tools doesn't support generating "references" (JSON $ref) so it can't support recursive types today. // See https://github.com/kubernetes-sigs/controller-tools/issues/489 for more information. diff --git a/v2/tools/generator/internal/codegen/storage/conversion_graph.go b/v2/tools/generator/internal/codegen/storage/conversion_graph.go index 663e649c9f..b62dc20f51 100644 --- a/v2/tools/generator/internal/codegen/storage/conversion_graph.go +++ b/v2/tools/generator/internal/codegen/storage/conversion_graph.go @@ -116,7 +116,6 @@ func (graph *ConversionGraph) TransitionCount() int { // declaringType is the type containing the property. // property is the name of the property. // definitions is a set of known definitions. -// func (graph *ConversionGraph) FindNextProperty( ref astmodel.PropertyReference, definitions astmodel.TypeDefinitionSet) (astmodel.PropertyReference, error) { diff --git a/v2/tools/generator/internal/codegen/storage/property_converter.go b/v2/tools/generator/internal/codegen/storage/property_converter.go index 0aab7e484b..8bb44b9a94 100644 --- a/v2/tools/generator/internal/codegen/storage/property_converter.go +++ b/v2/tools/generator/internal/codegen/storage/property_converter.go @@ -80,11 +80,12 @@ func (p *PropertyConverter) useBaseTypeForEnumerations( } // shortCircuitNamesOfSimpleTypes redirects or replaces TypeNames -// o If a TypeName points into an API package, it is redirected into the appropriate storage package -// o If a TypeName references an enumeration, it is replaced with the underlying type of the enumeration as our -// storage definitions don't use enumerations, they use primitive definitions -// o If a TypeName references an alias for a primitive type (these are used to specify validations), it is replace -// with the primitive type +// +// o If a TypeName points into an API package, it is redirected into the appropriate storage package +// o If a TypeName references an enumeration, it is replaced with the underlying type of the enumeration as our +// storage definitions don't use enumerations, they use primitive definitions +// o If a TypeName references an alias for a primitive type (these are used to specify validations), it is replace +// with the primitive type func (p *PropertyConverter) shortCircuitNamesOfSimpleTypes( tv *astmodel.TypeVisitor, tn astmodel.TypeName, ctx interface{}) (astmodel.Type, error) { diff --git a/v2/tools/generator/internal/config/group_configuration.go b/v2/tools/generator/internal/config/group_configuration.go index f917d8a71e..68697f47a9 100644 --- a/v2/tools/generator/internal/config/group_configuration.go +++ b/v2/tools/generator/internal/config/group_configuration.go @@ -26,7 +26,6 @@ import ( // │ ObjectModelConfiguration │───────║ GroupConfiguration ║───────│ VersionConfiguration │───────│ TypeConfiguration │───────│ PropertyConfiguration │ // │ │1 1..n║ ║1 1..n│ │1 1..n│ │1 1..n│ │ // └──────────────────────────┘ ╚════════════════════╝ └──────────────────────┘ └───────────────────┘ └───────────────────────┘ -// type GroupConfiguration struct { name string versions map[string]*VersionConfiguration diff --git a/v2/tools/generator/internal/config/object_model_configuration.go b/v2/tools/generator/internal/config/object_model_configuration.go index cea179adb3..2c6302cb95 100644 --- a/v2/tools/generator/internal/config/object_model_configuration.go +++ b/v2/tools/generator/internal/config/object_model_configuration.go @@ -24,7 +24,6 @@ import ( // ║ ObjectModelConfiguration ║───────│ GroupConfiguration │───────│ VersionConfiguration │───────│ TypeConfiguration │───────│ PropertyConfiguration │ // ║ ║1 1..n│ │1 1..n│ │1 1..n│ │1 1..n│ │ // ╚══════════════════════════╝ └────────────────────┘ └──────────────────────┘ └───────────────────┘ └───────────────────────┘ -// type ObjectModelConfiguration struct { groups map[string]*GroupConfiguration // nested configuration for individual groups typoAdvisor *TypoAdvisor diff --git a/v2/tools/generator/internal/config/property_configuration.go b/v2/tools/generator/internal/config/property_configuration.go index db2b2e5860..4c4b4af863 100644 --- a/v2/tools/generator/internal/config/property_configuration.go +++ b/v2/tools/generator/internal/config/property_configuration.go @@ -21,7 +21,6 @@ import ( // │ ObjectModelConfiguration │───────│ GroupConfiguration │───────│ VersionConfiguration │───────│ TypeConfiguration │───────║ PropertyConfiguration ║ // │ │1 1..n│ │1 1..n│ │1 1..n│ │1 1..n║ ║ // └──────────────────────────┘ └────────────────────┘ └──────────────────────┘ └───────────────────┘ ╚═══════════════════════╝ -// type PropertyConfiguration struct { name string nameInNextVersion configurable[string] // Name this property has in the next version diff --git a/v2/tools/generator/internal/config/type_configuration.go b/v2/tools/generator/internal/config/type_configuration.go index 5ccd73d213..e74edebfdf 100644 --- a/v2/tools/generator/internal/config/type_configuration.go +++ b/v2/tools/generator/internal/config/type_configuration.go @@ -24,7 +24,6 @@ import ( // │ ObjectModelConfiguration │───────│ GroupConfiguration │───────│ VersionConfiguration │───────║ TypeConfiguration ║───────│ PropertyConfiguration │ // │ │1 1..n│ │1 1..n│ │1 1..n║ ║1 1..n│ │ // └──────────────────────────┘ └────────────────────┘ └──────────────────────┘ ╚═══════════════════╝ └───────────────────────┘ -// type TypeConfiguration struct { name string properties map[string]*PropertyConfiguration diff --git a/v2/tools/generator/internal/config/version_configuration.go b/v2/tools/generator/internal/config/version_configuration.go index ef9631a1ae..32589912e2 100644 --- a/v2/tools/generator/internal/config/version_configuration.go +++ b/v2/tools/generator/internal/config/version_configuration.go @@ -22,7 +22,6 @@ import ( // │ ObjectModelConfiguration │───────│ GroupConfiguration │───────║ VersionConfiguration ║───────│ TypeConfiguration │───────│ PropertyConfiguration │ // │ │1 1..n│ │1 1..n║ ║1 1..n│ │1 1..n│ │ // └──────────────────────────┘ └────────────────────┘ ╚══════════════════════╝ └───────────────────┘ └───────────────────────┘ -// type VersionConfiguration struct { name string types map[string]*TypeConfiguration diff --git a/v2/tools/generator/internal/conversions/property_conversions.go b/v2/tools/generator/internal/conversions/property_conversions.go index 0758fcfb47..8316910cbf 100644 --- a/v2/tools/generator/internal/conversions/property_conversions.go +++ b/v2/tools/generator/internal/conversions/property_conversions.go @@ -35,10 +35,10 @@ type PropertyConversion func( // ctx contains additional information that may be needed when creating the property conversion // // The factory should return one of three result sets: -// * For a fatal error, one that guarantees no conversion can be generated, return (nil, error) -// This will abort the conversion process and return an error for logging. -// * For a valid conversion, return (conversion, nil) -// * When no conversion could be generated by this factory, return (nil, nil) to delegate to another factory +// - For a fatal error, one that guarantees no conversion can be generated, return (nil, error) +// This will abort the conversion process and return an error for logging. +// - For a valid conversion, return (conversion, nil) +// - When no conversion could be generated by this factory, return (nil, nil) to delegate to another factory // // Each conversion should be written with lead predicates to make sure that it only fires in the correct circumstances. // This requires, in particular, that most conversions check for optionality and bag items and exit early when those are @@ -47,7 +47,6 @@ type PropertyConversion func( // generate the correct code; any conversion that relies on being "protected" from particular situations by having other // conversions earlier in the list held by propertyConversionFactories is brittle and likely to generate the incorrect // code if the order of items in the list is modified. -// type PropertyConversionFactory func( source *TypedConversionEndpoint, destination *TypedConversionEndpoint, @@ -110,47 +109,48 @@ func init() { // source *string => destination *Sku // // assuming -// type Sku string +// +// type Sku string // // assignFromOptional can handle the optionality of sourceEndpoint and makes a recursive call // to CreateTypeConversion() with the simpler target: // // source string => destination *Sku // -// assignToOptional can handle the optionality of destinationEndpoint and makes a recursive -// call to CreateTypeConversion() with a simpler target: +// assignToOptional can handle the optionality of destinationEndpoint and makes a recursive +// call to CreateTypeConversion() with a simpler target: // -// source string => destination Sku +// source string => destination Sku // -// assignToAliasedPrimitive can handle the type conversion of string to Sku, and makes -// a recursive call to CreateTypeConversion() with a simpler target: +// assignToAliasedPrimitive can handle the type conversion of string to Sku, and makes +// a recursive call to CreateTypeConversion() with a simpler target: // -// source string => destination string +// source string => destination string // -// assignPrimitiveFromPrimitive can handle primitive values, and generates a -// conversion that does a simple assignment: +// assignPrimitiveFromPrimitive can handle primitive values, and generates a +// conversion that does a simple assignment: // -// destination = source +// destination = source // -// assignToAliasedPrimitive injects the necessary type conversion: +// assignToAliasedPrimitive injects the necessary type conversion: // -// destination = Sku(source) +// destination = Sku(source) // -// assignToOptional injects a local variable and takes it's address +// assignToOptional injects a local variable and takes it's address // -// sku := Sku(source) -// destination = &sku +// sku := Sku(source) +// destination = &sku // // finally, assignFromOptional injects the check to see if we have a value to assign in the // first place, assigning a suitable zero value if we don't: // -// if source != nil { -// sku := Sku(source) -// destination := &sku -// } else { -// destination := "" -// } +// if source != nil { +// sku := Sku(source) +// destination := &sku +// } else { // +// destination := "" +// } func CreateTypeConversion( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -193,26 +193,27 @@ func NameOfPropertyAssignmentFunction( // writeToBagItem will generate a conversion where the destination is in our property bag // -// For non-optional sources, the value is directly added +// # For non-optional sources, the value is directly added // // .Add(, ) // // For optional sources, the value is only added if non-nil; if nil, we remove any existing item // -// if != nil { -// .Add(, *) -// } else { -// .Remove() -// } +// if != nil { +// .Add(, *) +// } else { +// +// .Remove() +// } // // For slice and slice sources, the value is only added if it is non-empty; if empty we remove any existing item // -// if len() > 0 { -// .Add(, ) -// } else { -// .Remove() -// } +// if len() > 0 { +// .Add(, ) +// } else { // +// .Remove() +// } func writeToBagItem( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -288,7 +289,6 @@ func writeToBagItem( // underlying type of the destination is compatible with the source. // // = & -// func assignToOptional( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -348,18 +348,18 @@ func assignToOptional( // pullFromBagItem will populate a property from a property bag // -// if .Contains() { -// var -// err := .Pull(, &) -// if err != nil { -// return errors.Wrapf(err, ...) -// } +// if .Contains() { +// var +// err := .Pull(, &) +// if err != nil { +// return errors.Wrapf(err, ...) +// } // -// = -// } else { -// = -// } +// = +// } else { // +// = +// } func pullFromBagItem( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -444,15 +444,16 @@ func pullFromBagItem( // assignFromOptional will handle the case where the source type may be missing (nil) // // := -// if != nil { -// = * -// } else { -// = -// } +// +// if != nil { +// = * +// } else { +// +// = +// } // // Must trigger before assignToOptional so we generate the right zero values; to enforce this, assignToOptional includes // a predicate check that the source is NOT optional, allowing this conversion to trigger first. -// func assignFromOptional( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -528,7 +529,6 @@ func assignFromOptional( // the source is type compatible with the base type of the enumeration // // = () -// func assignToEnumeration( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -585,7 +585,6 @@ func assignToEnumeration( // same primitive type and are not optional // // = -// func assignPrimitiveFromPrimitive( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -627,7 +626,6 @@ func assignPrimitiveFromPrimitive( // definitions have the same underlying primitive type and are not optional // // = () -// func assignAliasedPrimitiveFromAliasedPrimitive( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -727,7 +725,6 @@ func assignFromAliasedPrimitive( // is not optional and we can find a conversion to give us the primitive type. // // = () -// func assignToAliasedPrimitive( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -859,13 +856,14 @@ func assignHandcraftedImplementations( // underlying definitions of the two arrays are compatible // // := make([], len()) -// for , := range { -// // Shadow the loop variable to avoid aliasing -// := -// [] := // Or other conversion as required -// } -// = // +// for , := range { +// // Shadow the loop variable to avoid aliasing +// := +// [] := // Or other conversion as required +// } +// +// = func assignArrayFromArray( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -978,16 +976,16 @@ func assignArrayFromArray( // assignMapFromMap will generate a code fragment to populate an array, assuming the // underlying definitions of the two arrays are compatible // -// if != nil { -// := make(map[]) -// for key, := range { -// [] := -// } -// = -// } else { -// = -// } +// if != nil { +// := make(map[]) +// for key, := range { +// [] := +// } +// = +// } else { // +// = +// } func assignMapFromMap( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -1176,7 +1174,6 @@ func assignEnumFromEnum( // // = () // = () -// func assignPrimitiveFromEnum( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -1223,11 +1220,12 @@ func assignPrimitiveFromEnum( // // var // err := .AssignPropertiesFrom() -// if err != nil { -// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") -// } -// = // +// if err != nil { +// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") +// } +// +// = func assignObjectDirectlyFromObject( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -1335,11 +1333,12 @@ func assignObjectDirectlyFromObject( // // var // err := .AssignPropertiesTo(&) -// if err != nil { -// return errors.Wrap(err, "while calling .AssignPropertiesTo()") -// } -// = // +// if err != nil { +// return errors.Wrap(err, "while calling .AssignPropertiesTo()") +// } +// +// = func assignObjectDirectlyToObject( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -1450,19 +1449,20 @@ func assignObjectDirectlyToObject( // // var // err := .AssignPropertiesFrom() -// if err != nil { -// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") -// } +// +// if err != nil { +// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") +// } // // var // err := .AssignPropertiesFrom() -// if err != nil { -// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") -// } +// +// if err != nil { +// return errors.Wrap(err, "while calling .AssignPropertiesFrom()") +// } // // Note the actual steps are generated by nested conversions; this handler works by finding the two conversions needed // given our intermediate type and chaining them together. -// func assignObjectsViaIntermediateObject( sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, @@ -1619,7 +1619,6 @@ const ( // copyKnownType will generate an assignment with the results of a call on the specified TypeName // // = .() -// func copyKnownType(name astmodel.TypeName, methodName string, returnKind knownTypeMethodReturn) func(*TypedConversionEndpoint, *TypedConversionEndpoint, *PropertyConversionContext) (PropertyConversion, error) { return func(sourceEndpoint *TypedConversionEndpoint, destinationEndpoint *TypedConversionEndpoint, _ *PropertyConversionContext) (PropertyConversion, error) { // Require both source and destination to not be bag items diff --git a/v2/tools/generator/internal/conversions/readable_conversion_endpoint_set.go b/v2/tools/generator/internal/conversions/readable_conversion_endpoint_set.go index a1c3ac22e1..4521701c85 100644 --- a/v2/tools/generator/internal/conversions/readable_conversion_endpoint_set.go +++ b/v2/tools/generator/internal/conversions/readable_conversion_endpoint_set.go @@ -42,7 +42,6 @@ func (set ReadableConversionEndpointSet) CreateValueFunctionEndpoints(sourceType // Background: When our source instance has a property bag, that bag might contain values we can write into properties // on our destination instance. We therefore iterate through each property on the *destination* type and create a // ReadableConversionEndpoint for each one that looks in the property bag for a value. -// func (set ReadableConversionEndpointSet) CreatePropertyBagMemberEndpoints(destinationType astmodel.Type) int { // Add a property bag item endpoint for each property we don't already support return set.addForEachProperty(destinationType, func(prop *astmodel.PropertyDefinition) *ReadableConversionEndpoint { diff --git a/v2/tools/generator/internal/conversions/writable_conversion_endpoint_set.go b/v2/tools/generator/internal/conversions/writable_conversion_endpoint_set.go index 50b6d408e8..b9181b78c3 100644 --- a/v2/tools/generator/internal/conversions/writable_conversion_endpoint_set.go +++ b/v2/tools/generator/internal/conversions/writable_conversion_endpoint_set.go @@ -32,7 +32,6 @@ func (set WritableConversionEndpointSet) CreatePropertyEndpoints(destinationType // Background: When our destination instance has a property bag, that bag can be used to stash properties from the // source where there is no matching destination property. We therefore iterate through each property on the *source* // type and create a WritableConversionEndpoint for each one so the value is stashed in the property bag. -// func (set WritableConversionEndpointSet) CreatePropertyBagMemberEndpoints(sourceType astmodel.Type) int { // Add a property bag member endpoint for each property we don't already support return set.addForEachProperty(sourceType, func(prop *astmodel.PropertyDefinition) *WritableConversionEndpoint { diff --git a/v2/tools/generator/internal/functions/chained_conversion_function.go b/v2/tools/generator/internal/functions/chained_conversion_function.go index a76668ff5a..b498028ed9 100644 --- a/v2/tools/generator/internal/functions/chained_conversion_function.go +++ b/v2/tools/generator/internal/functions/chained_conversion_function.go @@ -26,17 +26,16 @@ import ( // preexisting AssignProperties*() method. Otherwise, we chain to that type to do the conversion to an intermediate // instance and then convert using that. // -// func (r ) ConvertFrom(instance ) error { -// source, ok := instance.(*) -// if !ok { -// // Need indirect conversion -// source = &{} -// source.ConvertFrom(instance) -// } -// -// return r.AssignPropertiesFrom(source) -// } +// func (r ) ConvertFrom(instance ) error { +// source, ok := instance.(*) +// if !ok { +// // Need indirect conversion +// source = &{} +// source.ConvertFrom(instance) +// } // +// return r.AssignPropertiesFrom(source) +// } type ChainedConversionFunction struct { // name is the unique name for this function name string @@ -149,24 +148,23 @@ func (fn *ChainedConversionFunction) AsFunc( // // For ConvertFrom, we generate // -// src, ok := source.(*) -// if ok { -// // Populate our instance from source -// return s.AssignPropertiesFrom(source) -// } +// src, ok := source.(*) +// if ok { +// // Populate our instance from source +// return s.AssignPropertiesFrom(source) +// } // -// // Convert to an intermediate form -// src = &{} -// err := src.ConvertFrom(source) -// if err != nil { -// return errors.Wrapf(err, "...elided...") -// } +// // Convert to an intermediate form +// src = &{} +// err := src.ConvertFrom(source) +// if err != nil { +// return errors.Wrapf(err, "...elided...") +// } // -// // Update our instance from src -// return s.AssignPropertiesFrom(src) +// // Update our instance from src +// return s.AssignPropertiesFrom(src) // // For ConvertTo, we have essentially the same structure, but two-step conversion is done in the other order. -// func (fn *ChainedConversionFunction) bodyForConvert( receiverName string, parameterName string, generationContext *astmodel.CodeGenerationContext) []dst.Stmt { diff --git a/v2/tools/generator/internal/functions/conditions_functions.go b/v2/tools/generator/internal/functions/conditions_functions.go index 9d6f70956c..c63b90c821 100644 --- a/v2/tools/generator/internal/functions/conditions_functions.go +++ b/v2/tools/generator/internal/functions/conditions_functions.go @@ -16,9 +16,9 @@ import ( // GetConditionsFunction returns a function declaration containing the implementation of the GetConditions() function. // -// func (r *) GetConditions() genruntime.Conditions { -// return r.Status.Conditions -// } +// func (r *) GetConditions() genruntime.Conditions { +// return r.Status.Conditions +// } func GetConditionsFunction(k *ResourceFunction, codeGenerationContext *astmodel.CodeGenerationContext, receiver astmodel.TypeName, methodName string) *dst.FuncDecl { receiverIdent := k.IdFactory().CreateReceiver(receiver.Name()) receiverType := receiver.AsType(codeGenerationContext) @@ -44,9 +44,9 @@ func GetConditionsFunction(k *ResourceFunction, codeGenerationContext *astmodel. // SetConditionsFunction returns a function declaration containing the implementation of the SetConditions() function. // -// func (r *) SetConditions(conditions genruntime.Conditions) { -// r.Status.Conditions = conditions -// } +// func (r *) SetConditions(conditions genruntime.Conditions) { +// r.Status.Conditions = conditions +// } func SetConditionsFunction(k *ResourceFunction, codeGenerationContext *astmodel.CodeGenerationContext, receiver astmodel.TypeName, methodName string) *dst.FuncDecl { conditionsParameterName := k.IdFactory().CreateIdentifier(astmodel.ConditionsProperty, astmodel.NotExported) diff --git a/v2/tools/generator/internal/functions/kubernetes_admissions_validations.go b/v2/tools/generator/internal/functions/kubernetes_admissions_validations.go index 3dbea2e381..b3b84fcaba 100644 --- a/v2/tools/generator/internal/functions/kubernetes_admissions_validations.go +++ b/v2/tools/generator/internal/functions/kubernetes_admissions_validations.go @@ -64,7 +64,8 @@ func validateResourceReferences(k *ResourceFunction, codeGenerationContext *astm } // validateResourceReferencesBody helps generate the body of the validateResourceReferences function: -// refs, err := reflecthelpers.FindResourceReferences(&.Spec) +// +// refs, err := reflecthelpers.FindResourceReferences(&.Spec) // if err != nil { // return err // } @@ -123,10 +124,10 @@ func validateWriteOncePropertiesFunction(resourceFn *ResourceFunction, codeGener // validateWriteOncePropertiesFunctionBody helps generate the body of the validateWriteOncePropertiesFunctionBody function: // -// oldObj, ok := old.(*Receiver) -// if !ok { -// return nil -// } +// oldObj, ok := old.(*Receiver) +// if !ok { +// return nil +// } // // return genruntime.ValidateWriteOnceProperties(oldObj, ) func validateWriteOncePropertiesFunctionBody(receiver astmodel.TypeName, codeGenerationContext *astmodel.CodeGenerationContext, receiverIdent string) []dst.Stmt { @@ -175,7 +176,8 @@ func validateOptionalConfigMapReferences(k *ResourceFunction, codeGenerationCont } // validateOptionalConfigMapReferencesBody helps generate the body of the validateResourceReferences function: -// refs, err := reflecthelpers.FindOptionalConfigMapReferences(&.Spec) +// +// refs, err := reflecthelpers.FindOptionalConfigMapReferences(&.Spec) // if err != nil { // return err // } diff --git a/v2/tools/generator/internal/functions/kubernetes_admissions_validator.go b/v2/tools/generator/internal/functions/kubernetes_admissions_validator.go index aba86abd04..8d62bb065e 100644 --- a/v2/tools/generator/internal/functions/kubernetes_admissions_validator.go +++ b/v2/tools/generator/internal/functions/kubernetes_admissions_validator.go @@ -214,6 +214,7 @@ func (v *ValidatorBuilder) validateDelete(k *ResourceFunction, codeGenerationCon // validateBody returns the body for the generic validation function which invokes all local (code generated) validations // as well as checking if there are any handcrafted validations and invoking them too: // For example: +// // validations := .createValidations() // var temp interface{} = // if runtimeValidator, ok := temp.(genruntime.Validator); ok { @@ -326,12 +327,15 @@ func (v *ValidatorBuilder) makeLocalValidationFuncDetails(kind ValidationKind, c } // localValidationFuncBody returns the body of the local (code generated) validation functions: +// // return []func() error{ // ., // ., // ... // } +// // or in the case of update functions (that may not need the old parameter): +// // return []func(old runtime.Object) error{ // func(old runtime.Object) error { // return . @@ -361,8 +365,11 @@ func (v *ValidatorBuilder) localValidationFuncBody(kind ValidationKind, codeGene // makeLocalValidationElement creates a validation expression, automatically removing the old parameter for update // validations if it's not needed. These elements are used to build the list of validation functions. // If validation != ValidationKindUpdate or validation == ValidationKindUpdate that DOES use the old parameter: +// // . +// // If validate == ValidationKindUpdate that doesn't use the old parameter: +// // func(old runtime.Object) error { // return . // } diff --git a/v2/tools/generator/internal/functions/kubernetes_exporter_function.go b/v2/tools/generator/internal/functions/kubernetes_exporter_function.go index dad9fb5682..05544470b6 100644 --- a/v2/tools/generator/internal/functions/kubernetes_exporter_function.go +++ b/v2/tools/generator/internal/functions/kubernetes_exporter_function.go @@ -63,20 +63,21 @@ func (d *KubernetesExporterBuilder) ToInterfaceImplementation() *astmodel.Interf // exportKubernetesResource returns the body of the ExportKubernetesResources function, which implements // the genruntime.KubernetesExporter interface. // Generates code like: -// func ( *) ExportKubernetesResources(_ context.Context, _ genruntime.MetaObject, _ *genericarmclient.GenericClient, _ logr.Logger) ([]client.Object, error) { -// collector := configmaps.NewCollector(.Namespace) -// if .Spec.OperatorSpec != nil && .Spec.OperatorSpec.ConfigMaps != nil { -// if . != nil { -// collector.AddValue(.Spec.OperatorSpec.ConfigMaps., *.) +// +// func ( *) ExportKubernetesResources(_ context.Context, _ genruntime.MetaObject, _ *genericarmclient.GenericClient, _ logr.Logger) ([]client.Object, error) { +// collector := configmaps.NewCollector(.Namespace) +// if .Spec.OperatorSpec != nil && .Spec.OperatorSpec.ConfigMaps != nil { +// if . != nil { +// collector.AddValue(.Spec.OperatorSpec.ConfigMaps., *.) +// } // } +// ... +// result, err := collector.Values() +// if err != nil { +// return nil, err +// } +// return configmaps.SliceToClientObjectSlice(result), nil // } -// ... -// result, err := collector.Values() -// if err != nil { -// return nil, err -// } -// return configmaps.SliceToClientObjectSlice(result), nil -//} func (d *KubernetesExporterBuilder) exportKubernetesResources(k *ResourceFunction, codeGenerationContext *astmodel.CodeGenerationContext, receiver astmodel.TypeName, methodName string) *dst.FuncDecl { receiverIdent := k.IdFactory().CreateReceiver(receiver.Name()) receiverType := receiver.AsType(codeGenerationContext) diff --git a/v2/tools/generator/internal/functions/original_gvk_function.go b/v2/tools/generator/internal/functions/original_gvk_function.go index 0a78476d92..392b4f5e4d 100644 --- a/v2/tools/generator/internal/functions/original_gvk_function.go +++ b/v2/tools/generator/internal/functions/original_gvk_function.go @@ -16,14 +16,13 @@ import ( // We put these on our resource types, giving us a way to obtain the right type of instance when the reconciler is // working with ARM. The code differs slightly depending on whether we're injecting into an API or storage variant. // -// func (resource *SomeResource) OriginalGVK() scheme.GroupVersionKind { -// return scheme.GroupVersionKind{ -// Group: GroupVersion.Group, -// Version: resource.Spec.OriginalVersion, -// Kind: "SomeResource", -// } -// } -// +// func (resource *SomeResource) OriginalGVK() scheme.GroupVersionKind { +// return scheme.GroupVersionKind{ +// Group: GroupVersion.Group, +// Version: resource.Spec.OriginalVersion, +// Kind: "SomeResource", +// } +// } type OriginalGVKFunction struct { idFactory astmodel.IdentifierFactory hasOriginalVersionFunction bool diff --git a/v2/tools/generator/internal/functions/original_version_function.go b/v2/tools/generator/internal/functions/original_version_function.go index e3e76af84e..fceb600dcf 100644 --- a/v2/tools/generator/internal/functions/original_version_function.go +++ b/v2/tools/generator/internal/functions/original_version_function.go @@ -16,10 +16,9 @@ import ( // We put these on the *API* versions of our spec types, giving us a way to obtain the right type of instance when the // reconciler is working with ARM. // -// func (spec *SomeSpec) OriginalVersion() string { -// return GroupVersion.Version -// } -// +// func (spec *SomeSpec) OriginalVersion() string { +// return GroupVersion.Version +// } type OriginalVersionFunction struct { idFactory astmodel.IdentifierFactory } diff --git a/v2/tools/generator/internal/functions/pivot_conversion_function.go b/v2/tools/generator/internal/functions/pivot_conversion_function.go index d1d9eae8e3..ff1f790948 100644 --- a/v2/tools/generator/internal/functions/pivot_conversion_function.go +++ b/v2/tools/generator/internal/functions/pivot_conversion_function.go @@ -24,24 +24,24 @@ import ( // If the two instances involved in conversion are not in the same "spoke" leading to this "hub" version, we'll pivot to // the reverse conversion, starting at the far end of that "spoke": // -// func (s ) ConvertFrom(instance >) error { -// return instance.ConvertTo(s) -// } +// func (s ) ConvertFrom(instance >) error { +// return instance.ConvertTo(s) +// } // // The pivot is needed when following the package references from resource version to resource version won't lead us to // encounter the other type that's involved in the conversion, as we can see if we're trying to convert between v1 and // v2: // -// ################## ################# +---------------+ -// # v1 # # v2 # | v3 | -// # Person # # Person # | Person | -// ################## ################# +---------------+ -// | | | -// v v v -// +----------------+ +---------------+ +---------------+ -// | v1storage | | v2storage | | v3storage | -// | Person |----------------->| Person |----------------->| Person | -// +----------------+ +---------------+ +---------------+ +// ################## ################# +---------------+ +// # v1 # # v2 # | v3 | +// # Person # # Person # | Person | +// ################## ################# +---------------+ +// | | | +// v v v +// +----------------+ +---------------+ +---------------+ +// | v1storage | | v2storage | | v3storage | +// | Person |----------------->| Person |----------------->| Person | +// +----------------+ +---------------+ +---------------+ // // Following package references from v1 leads us, in turn, to v1storage, v2storage, and finally v3storage (our hub // version), none of is the version we need to terminate the conversion path. @@ -52,13 +52,13 @@ import ( // // v1.Person.ConvertTo(v2.Person) // --> v1storage.Person.ConvertTo(v2.Person) -// --> v2storage.Person.ConvertTo(v2.Person) -// --> v3storage.Person.ConvertTo(v2.Person) // Pivot! -// --> v2.Person.ConvertFrom(v3storage.Person) // Change of direction -// --> v2storage.Person.ConvertFrom(v3storage.Person) +// +// --> v2storage.Person.ConvertTo(v2.Person) +// --> v3storage.Person.ConvertTo(v2.Person) // Pivot! +// --> v2.Person.ConvertFrom(v3storage.Person) // Change of direction +// --> v2storage.Person.ConvertFrom(v3storage.Person) // // Note that conversions like this always pivot through the hub version. -// type PivotConversionFunction struct { // nameFrom is the name for this function when converting FROM a provided instance nameFrom string @@ -162,7 +162,6 @@ func (fn *PivotConversionFunction) AsFunc( // // Note that the method called is in the *other* *direction*; we restart the conversion at the extreme of the second // spoke, invoking conversions back towards the hub again. -// func (fn *PivotConversionFunction) bodyForPivot( receiverName string, parameterName string, diff --git a/v2/tools/generator/internal/functions/property_assignment_function.go b/v2/tools/generator/internal/functions/property_assignment_function.go index 35d904925f..cbc3c995a3 100644 --- a/v2/tools/generator/internal/functions/property_assignment_function.go +++ b/v2/tools/generator/internal/functions/property_assignment_function.go @@ -233,9 +233,11 @@ func (fn *PropertyAssignmentFunction) generateBody( // createPropertyBagPrologue creates any introductory statements needed to set up our property bag before we start doing // assignments. We need to handle three cases: -// o If our source has a property bag, we clone it. -// o If our destination has a property bag (and our source does not), we create a new one. -// o If neither source nor destination has a property bag, we don't need to do anything. +// +// o If our source has a property bag, we clone it. +// o If our destination has a property bag (and our source does not), we create a new one. +// o If neither source nor destination has a property bag, we don't need to do anything. +// // source is the name of the source to read the property bag from func (fn *PropertyAssignmentFunction) createPropertyBagPrologue( source string, @@ -289,10 +291,11 @@ func (fn *PropertyAssignmentFunction) createPropertyBagPrologue( // propertyBagEpilogue creates any concluding statements required to handle our property bag after assignments are // complete. -// o If the destination has a property bag -// > If our bag is empty, we set the destination to nil -// > Otherwise we need to store our current property bag there -// o Otherwise we do nothing +// +// o If the destination has a property bag +// > If our bag is empty, we set the destination to nil +// > Otherwise we need to store our current property bag there +// o Otherwise we do nothing func (fn *PropertyAssignmentFunction) propertyBagEpilogue( destination string, ) []dst.Stmt { diff --git a/v2/tools/generator/internal/functions/resource_conversion_function.go b/v2/tools/generator/internal/functions/resource_conversion_function.go index 0a3450b9be..23976cfc03 100644 --- a/v2/tools/generator/internal/functions/resource_conversion_function.go +++ b/v2/tools/generator/internal/functions/resource_conversion_function.go @@ -20,31 +20,30 @@ import ( // // Direct conversion from the hub type: // -// func ( ) Convert(hub conversion.Hub) error { -// source, ok := hub.(*) -// if !ok { -// return fmt.Errorf("expected but received %T instead", hub) -// } -// return .AssignProperties(source) -// } +// func ( ) Convert(hub conversion.Hub) error { +// source, ok := hub.(*) +// if !ok { +// return fmt.Errorf("expected but received %T instead", hub) +// } +// return .AssignProperties(source) +// } // // Indirect conversion, multiple steps via an intermediate instance // -// func (r ) Convert(hub conversion.Hub) error { -// var source -// err := source.Convert(hub) -// if err != nil { -// return errors.Wrap(err, "converting from hub to source") -// } +// func (r ) Convert(hub conversion.Hub) error { +// var source +// err := source.Convert(hub) +// if err != nil { +// return errors.Wrap(err, "converting from hub to source") +// } // -// err = .AssignProperties(&source) -// if err != nil { -// return errors.Wrap(err, "converting from source to ") -// } -// -// return nil -// } +// err = .AssignProperties(&source) +// if err != nil { +// return errors.Wrap(err, "converting from source to ") +// } // +// return nil +// } type ResourceConversionFunction struct { // hub is the TypeName of the canonical hub type, the final target or original source for conversion hub astmodel.TypeName @@ -141,12 +140,12 @@ func (fn *ResourceConversionFunction) Hub() astmodel.TypeName { // directConversion creates a simple direct conversion between the two types // // , ok := .() -// if !ok { -// return errors.Errorf("expected but received %T instead", ) -// } +// +// if !ok { +// return errors.Errorf("expected but received %T instead", ) +// } // // return .AssignProperties(To|From)() -// func (fn *ResourceConversionFunction) directConversion( receiverName string, generationContext *astmodel.CodeGenerationContext) []dst.Stmt { fmtPackage := generationContext.MustGetImportedPackageName(astmodel.FmtReference) @@ -182,17 +181,18 @@ func (fn *ResourceConversionFunction) directConversion( // // var source // err := source.ConvertFrom() -// if err != nil { -// return errors.Wrap(err, "converting from hub to source") -// } +// +// if err != nil { +// return errors.Wrap(err, "converting from hub to source") +// } // // err = .AssignPropertiesFrom(&source) -// if err != nil { -// return errors.Wrap(err, "converting from source to ") -// } +// +// if err != nil { +// return errors.Wrap(err, "converting from source to ") +// } // // return nil -// func (fn *ResourceConversionFunction) indirectConversionFromHub( receiverName string, generationContext *astmodel.CodeGenerationContext) []dst.Stmt { errorsPackage := generationContext.MustGetImportedPackageName(astmodel.GitHubErrorsReference) @@ -240,17 +240,18 @@ func (fn *ResourceConversionFunction) indirectConversionFromHub( // // var destination // err = .AssignPropertiesTo(&destination) -// if err != nil { -// return errors.Wrap(err, "converting to destination from ") -// } +// +// if err != nil { +// return errors.Wrap(err, "converting to destination from ") +// } // // err := destination.ConvertTo() -// if err != nil { -// return errors.Wrap(err, "converting from destination to hub") -// } +// +// if err != nil { +// return errors.Wrap(err, "converting from destination to hub") +// } // // return nil -// func (fn *ResourceConversionFunction) indirectConversionToHub( receiverName string, generationContext *astmodel.CodeGenerationContext) []dst.Stmt { errorsPackage := generationContext.MustGetImportedPackageName(astmodel.GitHubErrorsReference) diff --git a/v2/tools/generator/internal/interfaces/kubernetes_resource_interface.go b/v2/tools/generator/internal/interfaces/kubernetes_resource_interface.go index 9ff9db6f8e..d399641564 100644 --- a/v2/tools/generator/internal/interfaces/kubernetes_resource_interface.go +++ b/v2/tools/generator/internal/interfaces/kubernetes_resource_interface.go @@ -270,11 +270,14 @@ func fixedValueGetAzureNameFunction(fixedValue string) functions.ObjectFunctionH // newOwnerFunction creates the Owner function declaration. This has two possible formats. // For normal resources: +// // func ( *) Owner() *genruntime.ResourceReference { // group, kind := genruntime.LookupOwnerGroupKind(.Spec) // return &genruntime.ResourceReference{Group: group, Kind: kind, Namespace: .Namespace, Name: .Spec.Owner.Name} // } +// // For extension resources: +// // func ( *) Owner() *genruntime.ResourceReference { // return &genruntime.ResourceReference{Group: .Spec.Owner.Group, Kind: .Spec.Owner.Kind, name: .Spec.Owner.Name} // } @@ -329,6 +332,7 @@ func newOwnerFunction(r *astmodel.ResourceType) func(k *functions.ObjectFunction } // newGetResourceScopeFunction creates a function that returns the scope of the resource. +// // func ( *) GetResourceScope() genruntime.ResourceScope { // return genruntime.ResourceScopeResourceGroup // } diff --git a/v2/tools/generator/internal/jsonast/jsonast.go b/v2/tools/generator/internal/jsonast/jsonast.go index d3487fe92c..ff9f09e1e8 100644 --- a/v2/tools/generator/internal/jsonast/jsonast.go +++ b/v2/tools/generator/internal/jsonast/jsonast.go @@ -115,29 +115,30 @@ func (scanner *SchemaScanner) RunHandlerForSchema(ctx context.Context, schema Sc } // GenerateDefinitionsFromDeploymentTemplate takes in the resources section of the Azure deployment template schema and returns golang AST Packages -// containing the types described in the schema which match the {resource_type}/{version} filters provided. // -// The schema we are working with is something like the following (in yaml for brevity): +// containing the types described in the schema which match the {resource_type}/{version} filters provided. // -// resources: -// items: -// oneOf: -// allOf: -// $ref: {{ base resource schema for ARM }} -// oneOf: -// - ARM resources -// oneOf: -// allOf: -// $ref: {{ base resource for external resources, think SendGrid }} -// oneOf: -// - External ARM resources -// oneOf: -// allOf: -// $ref: {{ base resource for ARM specific stuff like locks, deployments, etc }} -// oneOf: -// - ARM specific resources. I'm not 100% sure why... +// The schema we are working with is something like the following (in yaml for brevity): // -// allOf acts like composition which composites each schema from the child oneOf with the base reference from allOf. +// resources: +// items: +// oneOf: +// allOf: +// $ref: {{ base resource schema for ARM }} +// oneOf: +// - ARM resources +// oneOf: +// allOf: +// $ref: {{ base resource for external resources, think SendGrid }} +// oneOf: +// - External ARM resources +// oneOf: +// allOf: +// $ref: {{ base resource for ARM specific stuff like locks, deployments, etc }} +// oneOf: +// - ARM specific resources. I'm not 100% sure why... +// +// allOf acts like composition which composites each schema from the child oneOf with the base reference from allOf. func (scanner *SchemaScanner) GenerateDefinitionsFromDeploymentTemplate(ctx context.Context, root Schema) (astmodel.TypeDefinitionSet, error) { ctx, span := tab.StartSpan(ctx, "GenerateDefinitionsFromDeploymentTemplate") defer span.End() diff --git a/v2/tools/generator/internal/kustomization/conversion_patch_file.go b/v2/tools/generator/internal/kustomization/conversion_patch_file.go index d91fca74f2..521ae49561 100644 --- a/v2/tools/generator/internal/kustomization/conversion_patch_file.go +++ b/v2/tools/generator/internal/kustomization/conversion_patch_file.go @@ -19,23 +19,24 @@ import ( // apiVersion: apiextensions.k8s.io/v1 // kind: CustomResourceDefinition // metadata: -// name: roleassignments.microsoft.authorization.azure.com -// annotations: -// cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +// +// name: roleassignments.microsoft.authorization.azure.com +// annotations: +// cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +// // spec: -// preserveUnknownFields: false -// conversion: -// strategy: Webhook -// webhook: -// conversionReviewVersions: -// - v1beta1 -// clientConfig: -// service: -// namespace: system -// name: webhook-service -// path: /convert -// // +// preserveUnknownFields: false +// conversion: +// strategy: Webhook +// webhook: +// conversionReviewVersions: +// - v1beta1 +// clientConfig: +// service: +// namespace: system +// name: webhook-service +// path: /convert type ConversionPatchFile struct { ApiVersion string `yaml:"apiVersion"` Kind string `yaml:"kind"` diff --git a/v2/tools/generator/internal/kustomization/crd_kustomization_file.go b/v2/tools/generator/internal/kustomization/crd_kustomization_file.go index b2ff219a28..67fe185620 100644 --- a/v2/tools/generator/internal/kustomization/crd_kustomization_file.go +++ b/v2/tools/generator/internal/kustomization/crd_kustomization_file.go @@ -25,7 +25,6 @@ import ( // - patches/webhook-conversion-microsoft.authorization.azure.com_roleassignments.yaml // - patches/webhook-conversion-microsoft.batch.azure.com_batchaccounts.yaml // ... -// type CRDKustomizeFile struct { Resources []string `yaml:"resources"` // File paths to resource CRDs Patches []string `yaml:"patches"` // File paths to patch files used to enable conversions diff --git a/v2/tools/generator/internal/testcases/resource_conversion_test_case.go b/v2/tools/generator/internal/testcases/resource_conversion_test_case.go index 6b8b2814ea..d5e538cd8c 100644 --- a/v2/tools/generator/internal/testcases/resource_conversion_test_case.go +++ b/v2/tools/generator/internal/testcases/resource_conversion_test_case.go @@ -147,7 +147,6 @@ func (tc *ResourceConversionTestCase) Equals(other astmodel.TestCase, override a // properties := gopter.NewProperties(parameters) // properties.Property("...", prop.ForAll(RunTestForX, XGenerator()) // properties.TestingRun(t, gopter.NewFormatedReporter(true, 240, os.Stdout)) -// func (tc *ResourceConversionTestCase) createTestRunner(codegenContext *astmodel.CodeGenerationContext) dst.Decl { const ( parametersLocal = "parameters" @@ -237,24 +236,26 @@ func (tc *ResourceConversionTestCase) createTestRunner(codegenContext *astmodel. // // var hub OtherType // err := subject.ConvertTo(&hub) -// if err != nil { -// return err.Error() -// } +// +// if err != nil { +// return err.Error() +// } // // var result OurType // err = result.ConvertFrom(&hub) -// if err != nil { -// return err.Error() -// } +// +// if err != nil { +// return err.Error() +// } // // match := cmp.Equal(subject, actual, cmpopts.EquateEmpty()) -// if !match { -// result := diff.Diff(subject, actual); -// return result -// } +// +// if !match { +// result := diff.Diff(subject, actual); +// return result +// } // // return "" -// func (tc *ResourceConversionTestCase) createTestMethod( subject astmodel.TypeName, codegenContext *astmodel.CodeGenerationContext) dst.Decl {