Skip to content

Commit

Permalink
add --tile-name flag to simplfy bake from configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
crhntr committed Mar 21, 2024
1 parent af985c5 commit f1957df
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 17 deletions.
60 changes: 44 additions & 16 deletions internal/commands/bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ func NewBake(fs billy.Filesystem, releasesService baking.ReleasesService, outLog
}
}

// WithKilnfileFunc overrides the funcion used to parse the Kilnfile.
// It is for setting up tests.
func (bake Bake) WithKilnfileFunc(fn func(string) (cargo.Kilnfile, error)) Bake {
bake.loadKilnfile = fn
return bake
Expand Down Expand Up @@ -205,6 +207,8 @@ type BakeOptions struct {
Version string `short:"v" long:"version" description:"version of the tile"`
SkipFetchReleases bool `short:"sfr" long:"skip-fetch" description:"skips the automatic release fetch for all release directories" alias:"skip-fetch-directories"`

TileName string `short:"t" long:"tile-name" description:"select the bake_configuration matching the tile-name from the Kilnfile"`

IsFinal bool `long:"final" description:"this flag causes build metadata to be written to bake_records"`
}

Expand Down Expand Up @@ -440,15 +444,23 @@ func (b Bake) Execute(args []string) error {
b.errLogger.Println("warning: --stemcell-tarball is being deprecated in favor of --stemcells-directory")
}

templateVariables, err := b.templateVariables.FromPathsAndPairs(b.Options.VariableFiles, b.Options.Variables)
if err != nil {
return fmt.Errorf("failed to parse template variables: %s", err)
var templateVariables map[string]any
if b.Options.TileName != "" {
if templateVariables == nil {
templateVariables = make(map[string]any)
}
templateVariables[builder.TileNameVariable] = b.Options.TileName
}

if err := BakeArgumentsFromKilnfileConfiguration(&b.Options, templateVariables, b.loadKilnfile); err != nil {
return fmt.Errorf("failed to load bake configuration from Kilnfile: %w", err)
}

templateVariables, err = b.templateVariables.FromPathsAndPairs(b.Options.VariableFiles, b.Options.Variables)
if err != nil {
return fmt.Errorf("failed to parse template variables: %s", err)
}

releaseManifests, err := b.releases.FromDirectories(b.Options.ReleaseDirectories)
if err != nil {
return fmt.Errorf("failed to parse releases: %s", err)
Expand Down Expand Up @@ -609,29 +621,45 @@ func BakeArgumentsFromKilnfileConfiguration(options *BakeOptions, variables map[
if err != nil {
return err
}
if len(kf.BakeConfigurations) == 0 {
return nil
}
if tileName, ok := variables[builder.TileNameVariable]; ok {
name, ok := tileName.(string)

if variableValue, ok := variables[builder.TileNameVariable]; ok {
variableString, ok := variableValue.(string)
if !ok {
return fmt.Errorf("%s value must be a string got value %#[2]v with type %[2]T", builder.TileNameVariable, tileName)
}
if index := slices.IndexFunc(kf.BakeConfigurations, func(configuration cargo.BakeConfiguration) bool {
return configuration.TileName == name
}); index >= 0 {
fromConfiguration(options, kf.BakeConfigurations[index])
return fmt.Errorf("%s value must be a string got value %#[2]v with type %[2]T", builder.TileNameVariable, variableValue)
}
options.TileName = variableString
}

if len(kf.BakeConfigurations) == 0 {
return nil
} else if len(kf.BakeConfigurations) == 1 {
configuration := kf.BakeConfigurations[0]
if options.TileName != "" && options.TileName != configuration.TileName {
return fmt.Errorf("the provided tile_name %q does not match the configuration %q", options.TileName, configuration.TileName)
}
fromConfiguration(options, configuration)
if configuration.TileName != "" {
variables[builder.TileNameVariable] = configuration.TileName
} else if _, ok := variables[builder.TileNameVariable]; ok {
index := slices.IndexFunc(kf.BakeConfigurations, func(configuration cargo.BakeConfiguration) bool {
return configuration.TileName == options.TileName
})
if index < 0 {
return errorBakeConfigurationNotFound(options, kf)
}
fromConfiguration(options, kf.BakeConfigurations[index])
}
return nil
}

func errorBakeConfigurationNotFound(options *BakeOptions, kf cargo.Kilnfile) error {
names := make([]string, 0, len(kf.BakeConfigurations))
for _, config := range kf.BakeConfigurations {
names = append(names, config.TileName)
}
slices.Sort(names)
names = slices.Compact(names)
return fmt.Errorf("the provided tile_name %q does not match any configuration. The available names are: %v", options.TileName, names)
}

func fromConfiguration(b *BakeOptions, configuration cargo.BakeConfiguration) {
if len(configuration.Metadata) > 0 {
b.Metadata = configuration.Metadata
Expand Down
70 changes: 70 additions & 0 deletions internal/commands/bake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,37 @@ var _ = Describe("Bake", func() {
})
})
})
Context("when bake configuration has multiple options", func() {
BeforeEach(func() {
bake = bake.WithKilnfileFunc(func(s string) (cargo.Kilnfile, error) {
return cargo.Kilnfile{
BakeConfigurations: []cargo.BakeConfiguration{
{
TileName: "p-each",
Metadata: "peach.yml",
},
{
TileName: "p-air",
Metadata: "pair.yml",
},
{
TileName: "p-lum",
Metadata: "plum.yml",
},
},
}, nil
})
})
When("a the tile flag is passed", func() {
It("it uses the value from the bake configuration with the correct name", func() {
err := bake.Execute([]string{
"--tile-name=p-each",
})
Expect(err).To(Not(HaveOccurred()))
Expect(fakeMetadataService.ReadArgsForCall(0)).To(Equal("peach.yml"))
})
})
})
Context("when --stub-releases is specified", func() {
It("doesn't fetch releases", func() {
err := bake.Execute([]string{
Expand Down Expand Up @@ -1017,6 +1048,34 @@ var _ = Describe("BakeArgumentsFromKilnfileConfiguration", func() {
Expect(kilnfilePathArg).To(Equal(kilnfilePath))
})

When("there is one tile configuration", func() {
var loadKilnfile func(string) (cargo.Kilnfile, error)
BeforeEach(func() {
loadKilnfile = func(s string) (cargo.Kilnfile, error) {
return cargo.Kilnfile{
BakeConfigurations: []cargo.BakeConfiguration{
{TileName: "peach", Metadata: "peach.yml"},
},
}, nil
}
})
When("tile_name is unset", func() {
It("handles getting the first configuration", func() {
variables := make(map[string]any)
err := commands.BakeArgumentsFromKilnfileConfiguration(opts, variables, loadKilnfile)
Expect(err).NotTo(HaveOccurred())
Expect(opts.Metadata).To(Equal("peach.yml"))
})
})
When("a tile_name is a variable and does not match the bake configuration", func() {
It("handles getting the first configuration", func() {
variables := map[string]any{builder.TileNameVariable: "banana"}
err := commands.BakeArgumentsFromKilnfileConfiguration(opts, variables, loadKilnfile)
Expect(err).To(HaveOccurred())
})
})
})

When("there are multiple tile configurations", func() {
var loadKilnfile func(string) (cargo.Kilnfile, error)
BeforeEach(func() {
Expand Down Expand Up @@ -1065,6 +1124,17 @@ var _ = Describe("BakeArgumentsFromKilnfileConfiguration", func() {
})
Expect(err).To(MatchError("tile_name value must be a string got value 8675309 with type int"))
})

It("returns an error for unexpected tile_name type", func() {
variables := map[string]any{"tile_name": 8675309}

err := commands.BakeArgumentsFromKilnfileConfiguration(opts, variables, func(s string) (cargo.Kilnfile, error) {
return cargo.Kilnfile{
BakeConfigurations: []cargo.BakeConfiguration{{TileName: "apple"}},
}, nil
})
Expect(err).To(MatchError("tile_name value must be a string got value 8675309 with type int"))
})
})

})
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/rebake.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (cmd ReBake) Execute(args []string) error {
}

if !record.IsEquivalent(newRecord, log.New(os.Stderr, "bake record diff: ", 0)) {
return fmt.Errorf("expected tile bake records to be equivilant")
return fmt.Errorf("expected tile bake records to be equivalent")
}

return nil
Expand Down

0 comments on commit f1957df

Please sign in to comment.