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

fix(deployments): refactor pull step payload structure #322

Merged
merged 6 commits into from
Dec 12, 2024

Conversation

mitchnielsen
Copy link
Contributor

@mitchnielsen mitchnielsen commented Dec 11, 2024

Summary

Pull steps have a specific format in the API payload
that isn't very clearly defined by the API docs, since
the payload value is an empty list.

Looking more at the source code and documentation,
I adjusted the payload sent to the API to match the
expected format.

The format of the Terraform resource stays the same.

For reference, the incorrect format we had was:

[
  {
    "type": "git_clone",
    "branch": "main",
    "repository": "https://my-git-repo.git",
    "access_token": "fake-token"
  }
]

The correct format is:

[
  {
    "prefect.deployments.steps.git_clone": {
      "branch": "main",
      "repository": "https://my-git-repo.git",
      "access_token": "fake-token"
    }
  }
]

Overall changes:

  • Introduced PullStepCommon to encapsulate shared fields across pull step types.
  • Created specific types for PullStepGitClone, PullStepSetWorkingDirectory, and PullStepPullFrom to improve clarity and maintainability. This is where we can define the correct JSON field name for the payload.
  • Updated the mapping functions to accommodate the new structure, ensuring proper handling of pull steps in both API and Terraform contexts.
  • Also added IncludeSubmodules field, which I missed on the first pass

Closes #321

Testing

Acceptance tests

Check out the acceptance tests added in the PR.

Manual tests

Also manually tested this to validate #321 is addressed:

  1. Deployed the configuration from Flow run crashed with ValueError: Step has unexpected additional keys: branch, repository, access_token #321.

  2. Confirmed the Deployment shows the correct Pull Step configuration:

    image
  3. Clicked "Quick run" and confirmed that the flow ran successfully after cloning the repository per the pull steps:

    image

Pull steps have a specific format in the API payload
that isn't very clearly defined by the API docs, since
the payload value is an empty list.

Looking more at the source code and documentation,
I adjusted the payload sent to the API to match the
expected format.

The format of the Terraform resource stays the same.

Overall changes:
* Introduced PullStepCommon to encapsulate shared fields across pull step types.
* Created specific types for PullStepGitClone,
  PullStepSetWorkingDirectory, and PullStepPullFrom to improve clarity and
  maintainability. This is where we can define the correct JSON field name
  for the payload.
* Updated the mapping functions to accommodate the new structure, ensuring proper handling of pull steps in both API and Terraform contexts.

Closes #321
Comment on lines +460 to +469
var apiPullStep api.PullStep
switch tfPullStep.Type.ValueString() {
case "git_clone":
apiPullStep.PullStepGitClone = &api.PullStepGitClone{
PullStepCommon: pullStepCommon,
Repository: tfPullStep.Repository.ValueStringPointer(),
Branch: tfPullStep.Branch.ValueStringPointer(),
AccessToken: tfPullStep.AccessToken.ValueStringPointer(),
IncludeSubmodules: tfPullStep.IncludeSubmodules.ValueBoolPointer(),
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is obviously lengthier than the logic we defined before, but because of the payload expected by the API, I have to put configuration under certain fields in the parent struct so that I can give that parent struct the correct JSON struct tag like prefect.deployments.steps.git_clone.

@@ -924,15 +1007,29 @@ func (r *DeploymentResource) ImportState(ctx context.Context, req resource.Impor
// be more concise when defining the conflicting attributes. Defining them in
// ConfigValidators instead would be much more verbose, and disconnected from
// the source of truth.
func validatorsForConflictingAttributes(attributes []string) []validator.String {
func pathExpressionsForAttributes(attributes []string) []path.Expression {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refactored this slightly - it was set up to always return string validators, but now that we have IncludeSubmodules, we need bool validators as well. So I abstracted this one to return only path expressions, then two small helpers below that wrap this function and return the desired validator type.

@@ -101,33 +101,80 @@ resource "prefect_deployment" "{{.DeploymentName}}" {
work_queue_name = "{{.WorkQueueName}}"
parameter_openapi_schema = jsonencode({{.ParameterOpenAPISchema}})
pull_steps = [
{{range .PullSteps}}
{{range .PullSteps}}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes below are a bit hard to read, and repetitive. I tried importing masterminds/sprig to give us coalesce and some other helpers, but it started escaping quotations and I couldn't find any reference as to why that was happening. I ditched that to stick with the standard library's template and use or, which seemed to work fine at giving me a context based on which field wasn't empty - but then I was getting errors that it couldn't access nested fields when they were undefined.

This may actually be doable, but to get this PR rolling I just added a little duplication for the common fields and moved on.

@@ -380,7 +436,7 @@ func testAccCheckDeploymentValues(fetchedDeployment *api.Deployment, expectedVal
}

if !reflect.DeepEqual(fetchedDeployment.PullSteps, expectedValues.pullSteps) {
return fmt.Errorf("Expected pull steps to be %v, got %v", expectedValues.pullSteps, fetchedDeployment.PullSteps)
return fmt.Errorf("Expected pull steps to be: \n%v\n got \n%v", expectedValues.pullSteps, fetchedDeployment.PullSteps)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Non-critical change, but made it much easier to read what the difference was between the two objects.

@mitchnielsen mitchnielsen marked this pull request as ready for review December 11, 2024 19:25
@mitchnielsen mitchnielsen requested a review from a team as a code owner December 11, 2024 19:25
@github-actions github-actions bot added the docs label Dec 11, 2024
Copy link
Contributor

@parkedwards parkedwards left a comment

Choose a reason for hiding this comment

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

damn, gnarly data structure to model in TF

@mitchnielsen
Copy link
Contributor Author

True, seems easier than Automations though :p

@mitchnielsen mitchnielsen merged commit 3fa3161 into main Dec 12, 2024
7 checks passed
@mitchnielsen mitchnielsen deleted the fix-pull-steps branch December 12, 2024 16:12
@mitchnielsen mitchnielsen changed the title feat(deployments): refactor pull step payload structure fix(deployments): refactor pull step payload structure Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix Fixing a bug docs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flow run crashed with ValueError: Step has unexpected additional keys: branch, repository, access_token
2 participants