Skip to content

Commit

Permalink
fix: implement support for multiple local ska-config.yaml
Browse files Browse the repository at this point in the history
this is done by moving from single yaml file to directory with list of yamls
  • Loading branch information
gchiesa committed Sep 25, 2024
1 parent 3b711e1 commit af43a23
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 28 deletions.
2 changes: 2 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
type CreateCmd struct {
TemplateURI string `arg:"-b,--blueprint,required" help:"URI of the template blueprint to use"`
DestinationPath string `arg:"-o,--output,required" help:"Destination path where to expand the blueprint"`
NamedConfig string `arg:"-n,--name" help:"The ska configuration name in case there are multiple templates configurations in the same root"`
Variables map[string]string `arg:"-v,separate" help:"Variables to use in the template. Can be specified multiple times"`
NonInteractive bool `arg:"-n,--non-interactive" help:"Run in non-interactive mode"`
}
Expand All @@ -21,6 +22,7 @@ func (c *CreateCmd) Execute(ctx context.Context) error {
ska := skaffolder.NewSkaCreate(
c.TemplateURI,
c.DestinationPath,
c.NamedConfig,
c.Variables,
*options,
)
Expand Down
2 changes: 1 addition & 1 deletion cmd/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

const programName = "ska"
const githubRepo = "https://gchiesa/ska"
const githubRepo = "https://github.com/gchiesa/ska"

var commandVersion = "development"

Expand Down
2 changes: 2 additions & 0 deletions cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

type UpdateCmd struct {
FolderPath string `arg:"-p,--path,required" help:"Local path where the .ska-config.yml file is located"`
NamedConfig string `arg:"-n,--name" help:"The ska configuration name in case there are multiple templates configurations in the same root"`
Variables map[string]string `arg:"-v,separate" help:"Variables to use in the template. Can be specified multiple times"`
NonInteractive bool `arg:"-n,--non-interactive" help:"Run in non-interactive mode"`
}
Expand All @@ -19,6 +20,7 @@ func (c *UpdateCmd) Execute(ctx context.Context) error {
}
ska := skaffolder.NewSkaUpdate(
c.FolderPath,
c.NamedConfig,
c.Variables,
*options,
)
Expand Down
8 changes: 0 additions & 8 deletions internal/configuration/configfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,13 @@ package configuration
import (
"github.com/apex/log"
"os"
"path/filepath"
)

type ConfigFile struct {
filePath string
log *log.Entry
}

const configFileName = ".ska-config.yml"

func NewConfigFromDirectory(dirPath string) *ConfigFile {
filePath := filepath.Join(dirPath, configFileName)
return NewConfigFromFile(filePath)
}

func NewConfigFromFile(filePath string) *ConfigFile {
logCtx := log.WithFields(log.Fields{
"pkg": "configuration",
Expand Down
81 changes: 75 additions & 6 deletions internal/configuration/localconfigservice.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
package configuration

import (
"errors"
"fmt"
"github.com/huandu/xstrings"
"gopkg.in/yaml.v2"
"os"
"path/filepath"
"slices"
"time"
)

var ErrNoConfigSpecified = errors.New("no configuration specified and multiple configurations present")
var ErrConfigAlreadyExists = errors.New("configuration already exists")

const (
localConfigDirName = ".ska-config"
localConfigFileNameDefault = "default"
localConfigFileNameExt = "yaml"
)

type ConfigBlock struct {
BlueprintURI string `yaml:"blueprintURI"`
IgnorePaths []string `yaml:"ignorePaths"`
Expand All @@ -21,17 +36,25 @@ type appCfg struct {
}

type LocalConfigService struct {
app *appCfg
namedConfig string
app *appCfg
}

func NewLocalConfigService() *LocalConfigService {
func NewLocalConfigService(namedConfig string) *LocalConfigService {
configBlock := &ConfigBlock{}
stateBlock := &StateBlock{}
appConfiguration := &appCfg{
Config: *configBlock,
State: *stateBlock,
}
return &LocalConfigService{app: appConfiguration}
return &LocalConfigService{namedConfig: namedConfig, app: appConfiguration}
}

func (cs *LocalConfigService) NamedConfig() string {
if cs.namedConfig != "" {
return cs.namedConfig
}
return localConfigFileNameDefault
}

func (cs *LocalConfigService) BlueprintUpstream() string {
Expand Down Expand Up @@ -66,7 +89,11 @@ func (cs *LocalConfigService) WithVariables(variables map[string]interface{}) *L
}

func (cs *LocalConfigService) WriteConfig(dirPath string) error {
cf := NewConfigFromDirectory(dirPath)
if err := os.MkdirAll(makeConfigPath(dirPath), 0o755); err != nil {
return err
}

cf := NewConfigFromFile(filepath.Join(makeConfigPath(dirPath), makeConfigFileName(cs.namedConfig)))

// get the time utc now in format "2006-01-02 15:04:05.999999999 -0700 MST"
cs.app.State.LastUpdate = TimeNowUTC()
Expand All @@ -82,9 +109,16 @@ func (cs *LocalConfigService) WriteConfig(dirPath string) error {
return nil
}

func (cs *LocalConfigService) ReadConfig(dirPath string) error {
cf := NewConfigFromDirectory(dirPath)
func (cs *LocalConfigService) ReadValidConfig(dirPath string) error {
if hasMultipleConfigurations(makeConfigPath(dirPath)) && cs.namedConfig == "" {
return ErrNoConfigSpecified
}

cf := NewConfigFromFile(filepath.Join(makeConfigPath(dirPath), makeConfigFileName(cs.namedConfig)))
return cs.LoadConfig(cf)
}

func (cs *LocalConfigService) LoadConfig(cf *ConfigFile) error {
configData, err := cf.ReadConfig()
if err != nil {
return err
Expand All @@ -99,8 +133,43 @@ func (cs *LocalConfigService) ReadConfig(dirPath string) error {
return nil
}

func (cs *LocalConfigService) ConfigExists(dirPath string) bool {
configFileName := makeConfigFileName(cs.namedConfig)
existingConfigs, _ := configEntries(makeConfigPath(dirPath))
return slices.Contains(existingConfigs, configFileName)
}

func TimeNowUTC() string {
utcTime := time.Now().UTC()
timeFormat := "2006-01-02 15:04:05 -0700 MST"
return utcTime.Format(timeFormat)
}

func makeConfigPath(dirPath string) string {
return filepath.Join(dirPath, localConfigDirName)
}

func makeConfigFileName(namedConfig string) string {
if namedConfig == "" {
namedConfig = localConfigFileNameDefault
}
return fmt.Sprintf("%s.%s", namedConfig, localConfigFileNameExt)
}

func hasMultipleConfigurations(dirPath string) bool {
entries, _ := configEntries(dirPath)
return len(entries) > 1
}

func configEntries(dirPath string) ([]string, error) {
entries, err := filepath.Glob(dirPath + "/*.yaml")
if err != nil {
return nil, err
}
result := make([]string, 0)
for _, entry := range entries {
_, _, filename := xstrings.LastPartition(entry, "/")
result = append(result, filename)
}
return result, nil
}
12 changes: 10 additions & 2 deletions pkg/skaffolder/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
type SkaCreate struct {
TemplateURI string
DestinationPath string
NamedConfig string
Variables map[string]string
Options *SkaOptions
Log *log.Entry
Expand All @@ -23,13 +24,14 @@ type SkaOptions struct {
Engine templateprovider.TemplateType // jinja or sprig
}

func NewSkaCreate(templateURI, destinationPath string, variables map[string]string, options SkaOptions) *SkaCreate {
func NewSkaCreate(templateURI, destinationPath, namedConfig string, variables map[string]string, options SkaOptions) *SkaCreate {
logCtx := log.WithFields(log.Fields{
"pkg": "skaffolder",
})
return &SkaCreate{
TemplateURI: templateURI,
DestinationPath: destinationPath,
NamedConfig: namedConfig,
Variables: variables,
Options: &options,
Log: logCtx,
Expand All @@ -48,7 +50,13 @@ func (s *SkaCreate) Create() error {
}(blueprintProvider)

// configservice
localConfig := configuration.NewLocalConfigService()
localConfig := configuration.NewLocalConfigService(s.NamedConfig)

// check if localconfig already exist, if yes we fail
if localConfig.ConfigExists(s.DestinationPath) {
log.Infof("Default config or specified named config already exists, please use a different name for the configuration")
return fmt.Errorf("configuration already exists")
}

if err = blueprintProvider.DownloadContent(); err != nil { //nolint:govet //not a bit deal
return err
Expand Down
24 changes: 13 additions & 11 deletions pkg/skaffolder/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,31 @@ import (
)

type SkaUpdate struct {
BaseURI string
Variables map[string]string
Options *SkaOptions
Log *log.Entry
BaseURI string
NamedConfig string
Variables map[string]string
Options *SkaOptions
Log *log.Entry
}

func NewSkaUpdate(baseURI string, variables map[string]string, options SkaOptions) *SkaUpdate {
func NewSkaUpdate(baseURI, namedConfig string, variables map[string]string, options SkaOptions) *SkaUpdate {
logCtx := log.WithFields(log.Fields{
"pkg": "skaffolder",
})
return &SkaUpdate{
BaseURI: baseURI,
Variables: variables,
Options: &options,
Log: logCtx,
BaseURI: baseURI,
NamedConfig: namedConfig,
Variables: variables,
Options: &options,
Log: logCtx,
}
}

func (s *SkaUpdate) Update() error {
localConfig := configuration.NewLocalConfigService()
localConfig := configuration.NewLocalConfigService(s.NamedConfig)

// read the config from the folder
if err := localConfig.ReadConfig(s.BaseURI); err != nil {
if err := localConfig.ReadValidConfig(s.BaseURI); err != nil {
return err
}

Expand Down

0 comments on commit af43a23

Please sign in to comment.