Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring and cleanup in preparation for changing namespaces #2139

Merged
merged 44 commits into from
Mar 11, 2022

Conversation

theunrepentantgeek
Copy link
Member

What this PR does / why we need it:

Refactoring and cleanup in preparation for changing our namespace prefixes from from v1alpha1api to v1beta.

To avoid having to mess around with string manipulation when creating compatibility types (coming in a future PR), changed LocalPackageReference to explicitly receive the prefix as a separate parameter.

  • Updated the config file to use versions that aren't prefix specific
  • Updated most tests to use the prefix v so they won't change when the production prefix is changed
  • Updated StoragePackageReference to more consistently defer to the wrapped LocalPackageReference
  • No longer need to special case containsPreviewVersionLabel() to skip our fixed prefix
  • Consistently use test.MakeLocalPackageReference() from tests

Conversion graph generation was prevously driven by the API types - but we don't have those available for generation of compatibility types.

  • generate the conversion graph from the storage types (since each StoragePackageReference contains within it the linked LocalPackagReference`).

  • Remove dependency of CreateStorageTypes on the conversion graph

Moving CreateStorageTypes ahead of CreateConversionGraph in the pipeline unearthed a number of problems with our pipeline and it's testing. Verification of pre- and post-requisities wasn't being done for tests, resulting in some tests having incorrect object structures

  • Moved verification of pre- and post-requisites into pipeline.Stage, including tests.
  • Moved tracking of seen/expected stages into pipeline.State.
  • Fix code generation panic caused by presence of types from multiple packages when creating golden test file output
  • Fix dependencies of pipeline stages during testing.
  • Use RunTestPipeline() more consistently when testing pipeline stages

Code gardening and diagnostics

  • For both ResourceType and ObjectType, added context to any panic that occurs during code generation of a func so we know which one failed
  • Strip functions and interface implementations from golden file output so the data structures are more easily seen

Special notes for your reviewer:

How does this PR make you feel:
gif

If applicable:

  • this PR contains documentation
  • this PR contains tests

@theunrepentantgeek theunrepentantgeek self-assigned this Mar 6, 2022
@theunrepentantgeek theunrepentantgeek added this to the codegen-beta-0 milestone Mar 6, 2022
@theunrepentantgeek theunrepentantgeek marked this pull request as ready for review March 6, 2022 21:38
v2/tools/generator/internal/astmodel/resource_type.go Outdated Show resolved Hide resolved
//
// func(this *TypeVisitor, it *ResourceType, ctx interface{}) (Type, error)
// func(it *ResourceType) (Type, error)
// func(it *ResourceType) Type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads sorta weird to me. Up above we list (basically) these same signatures, then down here we repeat them? It might make more sense to put this example up above with the TypeName example? Not that another example hurts but it's not super clear to me how this example is different than what line 17 is already saying, which is "Any of these formats can work but replace TypeName with any supported type?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got confused by the comment and used the wrong kind of signature; will try another way to clarify.

v2/tools/generator/internal/astmodel/types.go Show resolved Hide resolved
v2/tools/generator/internal/codegen/code_generator.go Outdated Show resolved Hide resolved
v2/tools/generator/internal/codegen/golden_files_test.go Outdated Show resolved Hide resolved
// functions) from the golden test output.
// These golden tests are looking at the structure of the generated structs; including all the code for functions in
// the output is just noise that makes the golden files hard to review.
func stripFunctionsPipelineStage() *pipeline.Stage {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this is true. Look at https://github.com/Azure/azure-service-operator/tree/main/v2/tools/generator/internal/codegen/testdata/ArmResource for example. These tests expect to include the various validation functions and ARM conversion functions. This stage seems to leave most of those (I'm not entirely sure why - maybe has to do with where the stage is injected into the pipeline?) It does seem to remove some stuff about // +kubebuilder:rbac:groups=test.azure.com,resources=fakeresources,verbs=get;list;watch;create;update;patch;delete, which I think we want in the golden files as (AFAIK) there is no other place that is tested?

If the objective here is just to remove certain interfaces/functions because they're already tested elsewhere, wouldn't it be easier to just remove the select set of stages we know weve tested? That allows us per-stage control here and we can just prune the stages we've already tested elsewhere and leave the rest?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't just pull those stages.

For one, they're often prerequisites of other stages that we do want to test.

For another, a lot of our stages are ONLY tested by these golden tests (they don't have isolated unit tests of their own). The more our test pipeline resembles the actual one we use for code generation the better, because we rule out unexpected interactions between the stages.

As discussed offline, I'll remove the filtering for now, and have logged #2150 so we remember to circle back and make things better.

// We do this by constructing a local package reference because this avoids replicating the logic here and risking
// inconsistency if things are changed in the future.
local := astmodel.MakeLocalPackageReference("prefix", "group", astmodel.GeneratorVersionPrefix, version.name)
_, lv, _ := local.GroupVersion()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we panic rather than discard here? And below?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, though I don't see how it would ever fire.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah agreed, neither do I. It pays to be paranoid sometimes though - who knows in the future when "That cannot possibly happen" can actually start happening because of some other refactor.

Thanks for adding!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reactivating as I don't think you actually did this at this location? (You did it below though I see)

@theunrepentantgeek theunrepentantgeek force-pushed the feature/back-compat-refactoring branch from b562dd9 to 6b91a0f Compare March 10, 2022 01:47
Copy link
Member

@babbageclunk babbageclunk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - slight complaining about the loss of fail-fast checking notwithstanding! But I definitely take your point about the benefit of having the check on all pipelines, rather than just the production one.

v2/tools/generator/internal/astmodel/object_type.go Outdated Show resolved Hide resolved
v2/tools/generator/internal/codegen/code_generator.go Outdated Show resolved Hide resolved
func (stage *Stage) checkPostrequisites(state *State) error {
var errs []error
for _, postreq := range stage.postrequisites {
early := state.stagesSeen.Contains(postreq)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also check stagesExpected?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline; we check stagesExpected at the end of the pipeline, to check there are no further stages pending.

// func(this *TypeVisitor, it TypeName, ctx interface{}) (Type, error)
// func(it TypeName) (Type, error)
// func(it TypeName) Type
// func(this *TypeVisitor, it <sometype>, ctx interface{}) (Type, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha, I had a comment suggesting this!

@theunrepentantgeek theunrepentantgeek force-pushed the feature/back-compat-refactoring branch from 0b49d4a to 4ba23c1 Compare March 10, 2022 22:29
@codecov-commenter
Copy link

codecov-commenter commented Mar 10, 2022

Codecov Report

Merging #2139 (d8c8b0e) into main (04cef84) will increase coverage by 0.02%.
The diff coverage is 76.75%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2139      +/-   ##
==========================================
+ Coverage   57.16%   57.18%   +0.02%     
==========================================
  Files         591      591              
  Lines      109522   109591      +69     
==========================================
+ Hits        62609    62675      +66     
- Misses      39369    39372       +3     
  Partials     7544     7544              
Impacted Files Coverage Δ
v2/tools/generator/internal/astmodel/string_set.go 70.58% <0.00%> (-29.42%) ⬇️
...enerator/internal/astmodel/type_visitor_builder.go 65.21% <ø> (ø)
...degen/pipeline/inject_original_version_property.go 81.81% <ø> (-0.80%) ⬇️
...r/internal/codegen/pipeline/status_from_swagger.go 12.59% <0.00%> (ø)
v2/tools/generator/internal/config/type_matcher.go 59.09% <0.00%> (-2.82%) ⬇️
...2/tools/generator/internal/astmodel/object_type.go 80.37% <20.00%> (-1.21%) ⬇️
...tools/generator/internal/astmodel/resource_type.go 82.88% <28.57%> (-1.35%) ⬇️
...tools/generator/internal/codegen/code_generator.go 89.17% <37.50%> (-1.34%) ⬇️
...s/generator/internal/config/group_configuration.go 65.33% <53.84%> (-5.26%) ⬇️
...rator/internal/astmodel/local_package_reference.go 88.63% <82.35%> (-6.49%) ⬇️
... and 34 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 04cef84...d8c8b0e. Read the comment docs.

@@ -133,7 +133,7 @@ typeTransformers:
property: Copy
ifType:
group: deploymenttemplate
version: v1alpha1api20190401
version: "2019-04-01"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: Can this just be 2019-04-01? Does it need the quotes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs the quotes, else it seems to get interpreted as a date.

//
// Some examples:
//
// VisitTypeName = func(it TypeName) Type // Works
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: Maybe include 1 more // Works example too at the bottom? Possibly that's one of the larger format ones like
func(it *ObjectType) (Type, error) or func(this *TypeVisitor, it *ObjectType, ctx interface{}) (Type, error). I think that helps accomplished what you were going for before of showing examples for TypeName and other fields. One that is a ptr (since TypeName isn't) probably?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

//
// For example, InjectJsonSerializationTests creates round trip serialization tests for any object types that have
// properties. It's not correct to give InjectJsonSerializationTests a prerequisite on every earlier stage that creates
// new object types becauses it isn't concerned with where those object came from. However, but those earlier stages DO
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor/wording: However, but on this line is phrased strangely? maybe just:

Suggested change
// new object types becauses it isn't concerned with where those object came from. However, but those earlier stages DO
// new object types becauses it isn't concerned with where those object came from. However, those earlier stages DO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

// We do this by constructing a local package reference because this avoids replicating the logic here and risking
// inconsistency if things are changed in the future.
local := astmodel.MakeLocalPackageReference("prefix", "group", astmodel.GeneratorVersionPrefix, version.name)
_, lv, _ := local.GroupVersion()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reactivating as I don't think you actually did this at this location? (You did it below though I see)

@theunrepentantgeek theunrepentantgeek merged commit 7866b35 into main Mar 11, 2022
@theunrepentantgeek theunrepentantgeek deleted the feature/back-compat-refactoring branch March 11, 2022 01:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants