Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions pkg/pipelines/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/windsorcli/cli/pkg/artifact"
"github.com/windsorcli/cli/pkg/blueprint"
"github.com/windsorcli/cli/pkg/config"
"github.com/windsorcli/cli/pkg/constants"
"github.com/windsorcli/cli/pkg/di"
"github.com/windsorcli/cli/pkg/env"
"github.com/windsorcli/cli/pkg/generators"
Expand Down Expand Up @@ -302,6 +303,30 @@ func (p *InitPipeline) Execute(ctx context.Context) error {
return nil
}

// prepareTemplateData sets the fallbackBlueprintURL if the default blueprint URL is used.
// It calls the base pipeline's prepareTemplateData, checks for explicit blueprint context and local templates,
// and assigns the fallback URL for blueprint processing if necessary.
// Returns the prepared template data or an error.
func (p *InitPipeline) prepareTemplateData(ctx context.Context) (map[string][]byte, error) {
templateData, err := p.BasePipeline.prepareTemplateData(ctx)
if err != nil {
return nil, err
}
if ctx.Value("blueprint") == nil && p.artifactBuilder != nil {
blueprintHandler := p.withBlueprintHandler()
hasLocalTemplates := false
if blueprintHandler != nil {
if localTemplateData, err := blueprintHandler.GetLocalTemplateData(); err == nil && len(localTemplateData) > 0 {
hasLocalTemplates = true
}
}
if !hasLocalTemplates {
p.fallbackBlueprintURL = constants.GetEffectiveBlueprintURL()
}
}
return templateData, nil
}

// =============================================================================
// Private Methods
// =============================================================================
Expand Down
15 changes: 0 additions & 15 deletions pkg/pipelines/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,3 @@ func (p *InstallPipeline) Execute(ctx context.Context) error {

return nil
}

// processTemplateData renders and processes template data for the InstallPipeline.
// Unlike the base pipeline, this method does not handle blueprint data extraction
// as blueprint loading is handled separately in the Execute method.
func (p *InstallPipeline) processTemplateData(templateData map[string][]byte) (map[string]any, error) {
if p.templateRenderer == nil || len(templateData) == 0 {
return nil, nil
}

renderedData := make(map[string]any)
if err := p.templateRenderer.Process(templateData, renderedData); err != nil {
return nil, fmt.Errorf("failed to process template data: %w", err)
}
return renderedData, nil
}
155 changes: 0 additions & 155 deletions pkg/pipelines/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -745,158 +745,3 @@ func TestInstallPipeline_Execute(t *testing.T) {
}
})
}

// =============================================================================
// processTemplateData Tests
// =============================================================================

func TestInstallPipeline_processTemplateData(t *testing.T) {
setup := func(t *testing.T, opts ...*SetupOptions) (*InstallPipeline, *InstallMocks) {
t.Helper()
pipeline := NewInstallPipeline()
mocks := setupInstallMocks(t, opts...)
return pipeline, mocks
}

t.Run("ProcessesTemplateDataSuccessfully", func(t *testing.T) {
// Given a pipeline with template renderer and template data
pipeline, _ := setup(t)
mockTemplateRenderer := &MockTemplate{
ProcessFunc: func(templateData map[string][]byte, renderedData map[string]any) error {
renderedData["test"] = "processed"
return nil
},
}
pipeline.templateRenderer = mockTemplateRenderer

templateData := map[string][]byte{
"test.jsonnet": []byte(`{"key": "value"}`),
}

// When processTemplateData is called
result, err := pipeline.processTemplateData(templateData)

// Then no error should be returned
if err != nil {
t.Errorf("Expected no error, got %v", err)
}

// And template processing should be called
if !mockTemplateRenderer.ProcessCalled {
t.Error("Expected template processing to be called")
}

// And result should contain processed data
if result["test"] != "processed" {
t.Errorf("Expected processed data, got %v", result)
}
})

t.Run("ReturnsErrorWhenTemplateProcessingFails", func(t *testing.T) {
// Given a pipeline with failing template renderer
pipeline, _ := setup(t)
mockTemplateRenderer := &MockTemplate{
ProcessFunc: func(templateData map[string][]byte, renderedData map[string]any) error {
return fmt.Errorf("template processing failed")
},
}
pipeline.templateRenderer = mockTemplateRenderer

templateData := map[string][]byte{
"test.jsonnet": []byte(`{"key": "value"}`),
}

// When processTemplateData is called
result, err := pipeline.processTemplateData(templateData)

// Then an error should be returned
if err == nil {
t.Fatal("Expected error, got nil")
}
if err.Error() != "failed to process template data: template processing failed" {
t.Errorf("Expected template processing error, got %q", err.Error())
}

// And result should be nil
if result != nil {
t.Errorf("Expected nil result, got %v", result)
}
})

t.Run("ReturnsNilWhenNoTemplateRenderer", func(t *testing.T) {
// Given a pipeline with no template renderer
pipeline, _ := setup(t)
pipeline.templateRenderer = nil

templateData := map[string][]byte{
"test.jsonnet": []byte(`{"key": "value"}`),
}

// When processTemplateData is called
result, err := pipeline.processTemplateData(templateData)

// Then no error should be returned
if err != nil {
t.Errorf("Expected no error, got %v", err)
}

// And result should be nil
if result != nil {
t.Errorf("Expected nil result, got %v", result)
}
})

t.Run("ReturnsNilWhenNoTemplateData", func(t *testing.T) {
// Given a pipeline with template renderer but no template data
pipeline, _ := setup(t)
mockTemplateRenderer := &MockTemplate{}
pipeline.templateRenderer = mockTemplateRenderer

templateData := make(map[string][]byte)

// When processTemplateData is called
result, err := pipeline.processTemplateData(templateData)

// Then no error should be returned
if err != nil {
t.Errorf("Expected no error, got %v", err)
}

// And result should be nil
if result != nil {
t.Errorf("Expected nil result, got %v", result)
}

// And template processing should not be called
if mockTemplateRenderer.ProcessCalled {
t.Error("Expected template processing to not be called")
}
})

t.Run("ReturnsNilWhenEmptyTemplateData", func(t *testing.T) {
// Given a pipeline with template renderer but empty template data
pipeline, _ := setup(t)
mockTemplateRenderer := &MockTemplate{}
pipeline.templateRenderer = mockTemplateRenderer

templateData := map[string][]byte{}

// When processTemplateData is called
result, err := pipeline.processTemplateData(templateData)

// Then no error should be returned
if err != nil {
t.Errorf("Expected no error, got %v", err)
}

// And result should be nil
if result != nil {
t.Errorf("Expected nil result, got %v", result)
}

// And template processing should not be called
if mockTemplateRenderer.ProcessCalled {
t.Error("Expected template processing to not be called")
}
})
}
12 changes: 10 additions & 2 deletions pkg/pipelines/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -866,8 +866,9 @@ func (p *BasePipeline) processTemplateData(templateData map[string][]byte) (map[
return renderedData, nil
}

// loadBlueprintFromTemplate loads blueprint data from rendered template data. If the "blueprint" key exists
// in renderedData and is a map, attempts to parse OCI artifact info from the context's "blueprint" value.
// loadBlueprintFromTemplate loads blueprint data from rendered template data.
// If the "blueprint" key exists in renderedData and is a map, attempts to parse OCI artifact info
// from the context's "blueprint" value or falls back to the default blueprint URL if artifactBuilder is set.
// Delegates loading to blueprintHandler.LoadData with the parsed blueprint map and optional OCI info.
func (p *BasePipeline) loadBlueprintFromTemplate(ctx context.Context, renderedData map[string]any) error {
if blueprintData, exists := renderedData["blueprint"]; exists {
Expand All @@ -893,6 +894,13 @@ func (p *BasePipeline) loadBlueprintFromTemplate(ctx context.Context, renderedDa
return err
}
}
} else if p.artifactBuilder != nil {
effectiveBlueprintURL := constants.GetEffectiveBlueprintURL()
var err error
ociInfo, err = bundler.ParseOCIReference(effectiveBlueprintURL)
if err != nil {
return fmt.Errorf("failed to parse default blueprint reference: %w", err)
}
}

blueprintHandler := p.withBlueprintHandler()
Expand Down
Loading