-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Feature/enforced provisioner #13591
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
Merged
Merged
Feature/enforced provisioner #13591
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
91cae75
added the parser for the enforced block
Madhav008 5b68357
Enhance enforced provisioner parsing to support HCL and JSON formats
Madhav008 1e15d1b
Remove PublishEnforcedBlocks function from Bucket struct
Madhav008 cfc0ae5
Remove ExtractBuildProvisionerHCL function and unused imports
Madhav008 edf09ee
Reverted the version upgrade
hariom-hashicorp da35405
Added the internal-sdk for the enforcedProvsioner api changes
hariom-hashicorp 60132b9
Enhance enforced provisioner handling and error reporting
hariom-hashicorp 21472e6
Implement enforced provisioner parsing and handling
hariom-hashicorp 2f502bc
Add test case for -skip-enforcement flag in BuildArgs
hariom-hashicorp 6217443
Refactor sensitive variable handling in provisioners and add related …
hariom-hashicorp 84f0e02
Refactor enforced provisioner handling: remove internal parser, updat…
hariom-hashicorp 60c3f47
Enhance provisioner block parsing: add error handling for invalid com…
hariom-hashicorp 9e28996
Remove internal SDK replacement for enforced block types in go.mod
hariom-hashicorp 9ca75b7
Update dependencies in go.mod and go.sum: bump hcp-sdk-go and packer-…
hariom-hashicorp 47fbe18
Update hcp-sdk-go dependency to v0.172.0 in go.mod and go.sum
hariom-hashicorp c7d5d55
Fix formatting in TestBuildCommand_ParseArgs and add newline at end o…
hariom-hashicorp e0a12d0
Refactor testJSONRegistryWithBuilds: remove environment variable setu…
hariom-hashicorp 6dedc5f
Rename injected variable for clarity in InjectEnforcedProvisioners fu…
hariom-hashicorp f21d7b1
Merge branch 'main' into feature/enforcedProvisioner
hariom-hashicorp 9f75e39
Merge branch 'main' into feature/enforcedProvisioner
hariom-hashicorp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // Copyright IBM Corp. 2013, 2025 | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
|
|
||
| package hcl2template | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strconv" | ||
|
|
||
| "github.com/hashicorp/hcl/v2" | ||
| "github.com/hashicorp/packer/packer" | ||
| ) | ||
|
|
||
| // GetCoreBuildProvisionerFromBlock converts a ProvisionerBlock to a CoreBuildProvisioner. | ||
| // This is used for enforced provisioners that need to be injected into builds. | ||
| func (cfg *PackerConfig) GetCoreBuildProvisionerFromBlock(pb *ProvisionerBlock, buildName string) (packer.CoreBuildProvisioner, hcl.Diagnostics) { | ||
| var diags hcl.Diagnostics | ||
|
|
||
| // Get the provisioner plugin | ||
| provisioner, err := cfg.parser.PluginConfig.Provisioners.Start(pb.PType) | ||
| if err != nil { | ||
| diags = append(diags, &hcl.Diagnostic{ | ||
| Severity: hcl.DiagError, | ||
| Summary: fmt.Sprintf("Failed to start enforced provisioner %q", pb.PType), | ||
| Detail: fmt.Sprintf("The provisioner plugin could not be loaded: %s", err.Error()), | ||
| }) | ||
| return packer.CoreBuildProvisioner{}, diags | ||
| } | ||
|
|
||
| // Create basic builder variables | ||
| builderVars := map[string]interface{}{ | ||
| "packer_core_version": cfg.CorePackerVersionString, | ||
| "packer_debug": strconv.FormatBool(cfg.debug), | ||
| "packer_force": strconv.FormatBool(cfg.force), | ||
| "packer_on_error": cfg.onError, | ||
| "packer_sensitive_variables": cfg.sensitiveInputVariableKeys(), | ||
| } | ||
|
hariom-hashicorp marked this conversation as resolved.
|
||
|
|
||
| // Create evaluation context | ||
| ectx := cfg.EvalContext(BuildContext, nil) | ||
|
|
||
| // Create the HCL2Provisioner wrapper | ||
| hclProvisioner := &HCL2Provisioner{ | ||
| Provisioner: provisioner, | ||
| provisionerBlock: pb, | ||
| evalContext: ectx, | ||
| builderVariables: builderVars, | ||
| } | ||
|
|
||
| if pb.Override != nil { | ||
| if override, ok := pb.Override[buildName]; ok { | ||
| if typedOverride, ok := override.(map[string]interface{}); ok { | ||
| hclProvisioner.override = typedOverride | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Prepare the provisioner | ||
| err = hclProvisioner.HCL2Prepare(nil) | ||
| if err != nil { | ||
| diags = append(diags, &hcl.Diagnostic{ | ||
| Severity: hcl.DiagError, | ||
| Summary: fmt.Sprintf("Failed to prepare enforced provisioner %q", pb.PType), | ||
| Detail: err.Error(), | ||
| }) | ||
| return packer.CoreBuildProvisioner{}, diags | ||
| } | ||
|
|
||
| // Wrap provisioner with any special behavior (pause, timeout, retry) | ||
| wrappedProvisioner := packer.WrapProvisionerWithOptions(hclProvisioner, packer.ProvisionerWrapOptions{ | ||
| PauseBefore: pb.PauseBefore, | ||
| Timeout: pb.Timeout, | ||
| MaxRetries: pb.MaxRetries, | ||
| }) | ||
|
|
||
| return packer.CoreBuildProvisioner{ | ||
| PType: pb.PType, | ||
| PName: pb.PName, | ||
| Provisioner: wrappedProvisioner, | ||
| }, diags | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| // Copyright IBM Corp. 2013, 2025 | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
|
|
||
| package hcl2template | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "log" | ||
|
|
||
| "github.com/hashicorp/hcl/v2" | ||
| "github.com/hashicorp/hcl/v2/hclparse" | ||
| "github.com/zclconf/go-cty/cty" | ||
| ) | ||
|
|
||
| var standaloneProvisionerSchema = &hcl.BodySchema{ | ||
| Blocks: []hcl.BlockHeaderSchema{ | ||
| {Type: buildProvisionerLabel, LabelNames: []string{"type"}}, | ||
| }, | ||
| } | ||
|
|
||
| // ParseProvisionerBlocks parses raw provisioner block content into ProvisionerBlocks. | ||
| // It accepts HCL, HCL JSON, and the legacy JSON payload used for enforced provisioners. | ||
| func ParseProvisionerBlocks(blockContent string) ([]*ProvisionerBlock, hcl.Diagnostics) { | ||
| parser := &Parser{Parser: hclparse.NewParser()} | ||
| return parser.parseProvisionerBlocks(blockContent) | ||
| } | ||
|
|
||
| func (p *Parser) parseProvisionerBlocks(blockContent string) ([]*ProvisionerBlock, hcl.Diagnostics) { | ||
| hclParser := p.Parser | ||
| if hclParser == nil { | ||
| hclParser = hclparse.NewParser() | ||
| } | ||
|
|
||
| log.Printf("[DEBUG] parsing provisioner block content as HCL") | ||
|
|
||
| file, diags := hclParser.ParseHCL([]byte(blockContent), "provisioner.pkr.hcl") | ||
| if !diags.HasErrors() { | ||
| provisioners, provisionerDiags := p.parseProvisionerBlocksFromFile(file, diags) | ||
| if provisionerDiags.HasErrors() { | ||
| return nil, provisionerDiags | ||
| } | ||
| log.Printf("[DEBUG] parsed provisioner block content as HCL") | ||
| return provisioners, provisionerDiags | ||
| } | ||
| log.Printf("[DEBUG] failed to parse provisioner block content as HCL, trying JSON fallback") | ||
|
|
||
| jsonFile, jsonDiags := hclParser.ParseJSON([]byte(blockContent), "provisioner.pkr.json") | ||
| if jsonDiags.HasErrors() { | ||
| log.Printf("[DEBUG] failed to parse provisioner block content as JSON") | ||
| return nil, append(diags, jsonDiags...) | ||
| } | ||
|
|
||
| provisioners, provisionerDiags := p.parseProvisionerBlocksFromFile(jsonFile, jsonDiags) | ||
| if !provisionerDiags.HasErrors() && len(provisioners) > 0 { | ||
| log.Printf("[DEBUG] parsed provisioner block content as JSON") | ||
| return provisioners, provisionerDiags | ||
| } | ||
|
|
||
| legacyJSON, ok, err := normalizeLegacyProvisionersJSON(blockContent) | ||
| if err == nil && ok { | ||
| legacyFile, legacyDiags := hclParser.ParseJSON([]byte(legacyJSON), "provisioner_legacy.pkr.json") | ||
| if !legacyDiags.HasErrors() { | ||
| legacyProvisioners, legacyProvisionerDiags := p.parseProvisionerBlocksFromFile(legacyFile, legacyDiags) | ||
| if !legacyProvisionerDiags.HasErrors() && len(legacyProvisioners) > 0 { | ||
| log.Printf("[DEBUG] parsed provisioner block content as legacy JSON") | ||
| return legacyProvisioners, legacyProvisionerDiags | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if provisionerDiags.HasErrors() { | ||
| return nil, provisionerDiags | ||
| } | ||
| log.Printf("[DEBUG] parsed provisioner block content as JSON but found no valid provisioner blocks") | ||
| return provisioners, provisionerDiags | ||
| } | ||
|
|
||
| func normalizeLegacyProvisionersJSON(blockContent string) (string, bool, error) { | ||
| type legacyPayload struct { | ||
| Provisioners []map[string]interface{} `json:"provisioners"` | ||
| } | ||
|
|
||
| var payload legacyPayload | ||
| if err := json.Unmarshal([]byte(blockContent), &payload); err != nil { | ||
| return "", false, err | ||
| } | ||
|
|
||
| if len(payload.Provisioners) == 0 { | ||
| return "", false, nil | ||
| } | ||
|
|
||
| normalized := make([]map[string]interface{}, 0, len(payload.Provisioners)) | ||
| for _, provisioner := range payload.Provisioners { | ||
| typeName, ok := provisioner["type"].(string) | ||
| if !ok || typeName == "" { | ||
| continue | ||
| } | ||
|
|
||
| cfg := make(map[string]interface{}) | ||
| for key, value := range provisioner { | ||
| if key == "type" { | ||
| continue | ||
| } | ||
| cfg[key] = value | ||
| } | ||
|
|
||
| normalized = append(normalized, map[string]interface{}{typeName: cfg}) | ||
| } | ||
|
|
||
| if len(normalized) == 0 { | ||
| return "", false, nil | ||
| } | ||
|
|
||
| out := map[string]interface{}{ | ||
| buildProvisionerLabel: normalized, | ||
| } | ||
|
|
||
| b, err := json.Marshal(out) | ||
| if err != nil { | ||
| return "", false, err | ||
| } | ||
|
|
||
| return string(b), true, nil | ||
| } | ||
|
|
||
| func (p *Parser) parseProvisionerBlocksFromFile(file *hcl.File, diags hcl.Diagnostics) ([]*ProvisionerBlock, hcl.Diagnostics) { | ||
| content, moreDiags := file.Body.Content(standaloneProvisionerSchema) | ||
| diags = append(diags, moreDiags...) | ||
| if diags.HasErrors() { | ||
| return nil, diags | ||
| } | ||
|
|
||
| ectx := &hcl.EvalContext{Variables: map[string]cty.Value{}} | ||
| provisioners := make([]*ProvisionerBlock, 0, len(content.Blocks)) | ||
|
|
||
| for _, block := range content.Blocks { | ||
| provisioner, moreDiags := p.decodeProvisioner(block, ectx) | ||
| diags = append(diags, moreDiags...) | ||
| if moreDiags.HasErrors() { | ||
| continue | ||
| } | ||
| provisioners = append(provisioners, provisioner) | ||
| } | ||
|
|
||
| return provisioners, diags | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.