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

refactor: adds support for different types of deployment modules #135

Merged
merged 1 commit into from
Feb 6, 2025
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
2 changes: 1 addition & 1 deletion cli/cmd/cmds/module/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (c *DeployCmd) Run(ctx run.RunContext) error {
dryrun = true
}

d := deployer.NewDeployer(&project, ctx.ManifestGenerator, ctx.Logger, dryrun)
d := deployer.NewDeployer(&project, ctx.ManifestGeneratorStore, ctx.Logger, dryrun)
if err := d.Deploy(); err != nil {
if err == deployer.ErrNoChanges {
ctx.Logger.Warn("no changes to deploy")
Expand Down
4 changes: 3 additions & 1 deletion cli/cmd/cmds/module/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/generator"
"github.com/input-output-hk/catalyst-forge/lib/project/schema"
)

Expand Down Expand Up @@ -40,7 +41,8 @@ func (c *TemplateCmd) Run(ctx run.RunContext) error {
}
}

result, err := ctx.DeploymentGenerator.GenerateBundle(bundle)
gen := generator.NewGenerator(ctx.ManifestGeneratorStore, ctx.Logger)
result, err := gen.GenerateBundle(bundle)
if err != nil {
return fmt.Errorf("failed to generate manifests: %w", err)
}
Expand Down
21 changes: 9 additions & 12 deletions cli/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import (
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds"
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds/module"
"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/generator"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/providers/kcl"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/project"
"github.com/input-output-hk/catalyst-forge/lib/project/schema"
"github.com/input-output-hk/catalyst-forge/lib/project/secrets"
Expand Down Expand Up @@ -93,17 +92,15 @@ func Run() int {
logger := slog.New(handler)
store := secrets.NewDefaultSecretStore()
loader := project.NewDefaultProjectLoader(store, logger)
gen := generator.NewGenerator(kcl.NewKCLManifestGenerator(logger), logger)
runctx := run.RunContext{
CI: cli.GlobalArgs.CI,
DeploymentGenerator: gen,
FSWalker: walker.NewDefaultFSWalker(logger),
Local: cli.GlobalArgs.Local,
Logger: logger,
ManifestGenerator: kcl.NewKCLManifestGenerator(logger),
ProjectLoader: &loader,
SecretStore: store,
Verbose: cli.GlobalArgs.Verbose,
CI: cli.GlobalArgs.CI,
FSWalker: walker.NewDefaultFSWalker(logger),
Local: cli.GlobalArgs.Local,
Logger: logger,
ManifestGeneratorStore: deployment.NewDefaultManifestGeneratorStore(),
ProjectLoader: &loader,
SecretStore: store,
Verbose: cli.GlobalArgs.Verbose,
}
ctx.Bind(runctx)

Expand Down
8 changes: 2 additions & 6 deletions cli/pkg/run/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"log/slog"

"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/generator"
"github.com/input-output-hk/catalyst-forge/lib/project/project"
"github.com/input-output-hk/catalyst-forge/lib/project/secrets"
"github.com/input-output-hk/catalyst-forge/lib/tools/walker"
Expand All @@ -15,9 +14,6 @@ type RunContext struct {
// CI is true if the run is happening in a CI environment.
CI bool

// DeploymentGenerator is the deployment generator to use for generating deployments.
DeploymentGenerator generator.Generator

// FSWalker is the walker to use for walking the filesystem.
FSWalker walker.FSWalker

Expand All @@ -27,8 +23,8 @@ type RunContext struct {
// Logger is the logger to use for logging.
Logger *slog.Logger

// ManifestGenerator is the manifest generator to use for generating manifests.
ManifestGenerator deployment.ManifestGenerator
// ManifestGeneratorStore is the manifest generator store to use for storing manifest generators.
ManifestGeneratorStore deployment.ManifestGeneratorStore

// ProjectLoader is the project loader to use for loading projects.
ProjectLoader project.ProjectLoader
Expand Down
4 changes: 2 additions & 2 deletions lib/project/deployment/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ func (d *Deployer) clone() (repo.GitRepo, error) {
}

// NewDeployer creates a new Deployer.
func NewDeployer(project *project.Project, mg deployment.ManifestGenerator, logger *slog.Logger, dryrun bool) Deployer {
gen := generator.NewGenerator(mg, logger)
func NewDeployer(project *project.Project, store deployment.ManifestGeneratorStore, logger *slog.Logger, dryrun bool) Deployer {
gen := generator.NewGenerator(store, logger)
remote := remote.GoGitRemoteInteractor{}

return Deployer{
Expand Down
19 changes: 14 additions & 5 deletions lib/project/deployment/deployer/deployer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/storage"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/generator"
dm "github.com/input-output-hk/catalyst-forge/lib/project/deployment/mocks"
"github.com/input-output-hk/catalyst-forge/lib/project/project"
Expand Down Expand Up @@ -85,6 +86,7 @@ func TestDeployerDeploy(t *testing.T) {
Name: utils.StringPtr("module"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: map[string]string{"key": "value"},
Version: utils.StringPtr("v1.0.0"),
},
Expand Down Expand Up @@ -113,6 +115,7 @@ func TestDeployerDeploy(t *testing.T) {
name: "module"
namespace: "default"
registry: "registry"
type: "kcl"
values: {
key: "value"
}
Expand Down Expand Up @@ -148,6 +151,7 @@ func TestDeployerDeploy(t *testing.T) {
Name: utils.StringPtr("module"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: map[string]string{"key": "value"},
Version: utils.StringPtr("v1.0.0"),
},
Expand Down Expand Up @@ -233,14 +237,19 @@ func TestDeployerDeploy(t *testing.T) {
},
}
gen := generator.NewGenerator(
&dm.ManifestGeneratorMock{
GenerateFunc: func(mod schema.DeploymentModule) ([]byte, error) {
return []byte("manifest"), nil
deployment.NewManifestGeneratorStore(
map[deployment.Provider]func(*slog.Logger) deployment.ManifestGenerator{
deployment.ProviderKCL: func(logger *slog.Logger) deployment.ManifestGenerator {
return &dm.ManifestGeneratorMock{
GenerateFunc: func(mod schema.DeploymentModule) ([]byte, error) {
return []byte("manifest"), nil
},
}
},
},
},
),
testutils.NewNoopLogger(),
)

provider := func(logger *slog.Logger) (secrets.SecretProvider, error) {
return &sm.SecretProviderMock{
GetFunc: func(key string) (string, error) {
Expand Down
13 changes: 9 additions & 4 deletions lib/project/deployment/generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type GeneratorResult struct {
// Generator is a deployment generator.
type Generator struct {
logger *slog.Logger
mg deployment.ManifestGenerator
store deployment.ManifestGeneratorStore
}

// GenerateBundle generates manifests for a deployment bundle.
Expand Down Expand Up @@ -51,7 +51,12 @@ func (d *Generator) Generate(m schema.DeploymentModule) ([]byte, error) {
return nil, fmt.Errorf("failed to validate module: %w", err)
}

manifests, err := d.mg.Generate(m)
mg, err := d.store.NewGenerator(d.logger, deployment.Provider(m.Type))
if err != nil {
return nil, fmt.Errorf("failed to get generator for module: %w", err)
}

manifests, err := mg.Generate(m)
if err != nil {
return nil, fmt.Errorf("failed to generate manifest for module: %w", err)
}
Expand All @@ -60,13 +65,13 @@ func (d *Generator) Generate(m schema.DeploymentModule) ([]byte, error) {
}

// NewGenerator creates a new deployment generator.
func NewGenerator(mg deployment.ManifestGenerator, logger *slog.Logger) Generator {
func NewGenerator(store deployment.ManifestGeneratorStore, logger *slog.Logger) Generator {
if logger == nil {
logger = slog.New(slog.NewTextHandler(io.Discard, nil))
}

return Generator{
logger: logger,
mg: mg,
store: store,
}
}
30 changes: 28 additions & 2 deletions lib/project/deployment/generator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package generator

import (
"fmt"
"log/slog"
"testing"

"cuelang.org/go/cue/cuecontext"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment/mocks"
"github.com/input-output-hk/catalyst-forge/lib/project/schema"
"github.com/input-output-hk/catalyst-forge/lib/project/utils"
Expand All @@ -30,6 +32,7 @@ func TestGeneratorGenerateBundle(t *testing.T) {
Name: utils.StringPtr("test"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: ctx.CompileString(`foo: "bar"`),
Version: utils.StringPtr("1.0.0"),
},
Expand All @@ -45,6 +48,7 @@ func TestGeneratorGenerateBundle(t *testing.T) {
name: "test"
namespace: "default"
registry: "registry"
type: "kcl"
values: {
foo: "bar"
}
Expand All @@ -63,6 +67,7 @@ func TestGeneratorGenerateBundle(t *testing.T) {
Name: utils.StringPtr("test"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: ctx.CompileString(`foo: "bar"`),
Version: utils.StringPtr("1.0.0"),
},
Expand All @@ -81,6 +86,7 @@ func TestGeneratorGenerateBundle(t *testing.T) {
Name: utils.StringPtr("test"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: fmt.Errorf("error"),
Version: utils.StringPtr("1.0.0"),
},
Expand All @@ -104,9 +110,18 @@ func TestGeneratorGenerateBundle(t *testing.T) {
return []byte(tt.yaml), nil
},
}

store := deployment.NewManifestGeneratorStore(
map[deployment.Provider]func(*slog.Logger) deployment.ManifestGenerator{
deployment.ProviderKCL: func(logger *slog.Logger) deployment.ManifestGenerator {
return mg
},
},
)

gen := Generator{
mg: mg,
logger: testutils.NewNoopLogger(),
store: store,
}

result, err := gen.GenerateBundle(tt.bundle)
Expand All @@ -131,6 +146,7 @@ func TestGeneratorGenerate(t *testing.T) {
Name: utils.StringPtr("test"),
Namespace: "default",
Registry: utils.StringPtr("registry"),
Type: "kcl",
Values: ctx.CompileString(`foo: "bar"`),
Version: utils.StringPtr("1.0.0"),
},
Expand All @@ -146,6 +162,7 @@ func TestGeneratorGenerate(t *testing.T) {
module: schema.DeploymentModule{
Name: utils.StringPtr("test"),
Namespace: "default",
Type: "kcl",
Values: ctx.CompileString(`foo: "bar"`),
Version: utils.StringPtr("1.0.0"),
},
Expand All @@ -168,9 +185,18 @@ func TestGeneratorGenerate(t *testing.T) {
return []byte(tt.yaml), nil
},
}

store := deployment.NewManifestGeneratorStore(
map[deployment.Provider]func(*slog.Logger) deployment.ManifestGenerator{
deployment.ProviderKCL: func(logger *slog.Logger) deployment.ManifestGenerator {
return mg
},
},
)

gen := Generator{
mg: mg,
logger: testutils.NewNoopLogger(),
store: store,
}

result, err := gen.Generate(tt.module)
Expand Down
46 changes: 46 additions & 0 deletions lib/project/deployment/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package deployment

import (
"fmt"
"log/slog"

"github.com/input-output-hk/catalyst-forge/lib/project/deployment/providers/kcl"
)

// Provider represents a manifest generator provider.
type Provider string

const (
// ProviderKCL represents the KCL manifest generator provider.
ProviderKCL Provider = "kcl"
)

// ManifestGeneratorStore is a store of manifest generator providers.
type ManifestGeneratorStore struct {
store map[Provider]func(*slog.Logger) ManifestGenerator
}

// NewDefaultManifestGeneratorStore returns a new ManifestGeneratorStore with the default providers.
func NewDefaultManifestGeneratorStore() ManifestGeneratorStore {
return ManifestGeneratorStore{
store: map[Provider]func(*slog.Logger) ManifestGenerator{
ProviderKCL: func(logger *slog.Logger) ManifestGenerator {
return kcl.NewKCLManifestGenerator(logger)
},
},
}
}

// NewManifestGeneratorStore returns a new ManifestGeneratorStore with the given providers.
func NewManifestGeneratorStore(store map[Provider]func(*slog.Logger) ManifestGenerator) ManifestGeneratorStore {
return ManifestGeneratorStore{store: store}
}

// NewGenerator returns a new ManifestGenerator client for the given provider.
func (s ManifestGeneratorStore) NewGenerator(logger *slog.Logger, p Provider) (ManifestGenerator, error) {
if f, ok := s.store[p]; ok {
return f(logger), nil
}

return nil, fmt.Errorf("unknown deployment module type: %s", p)
}
11 changes: 8 additions & 3 deletions lib/project/schema/_embed/schema.cue
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ version: "1.0"

// Name contains the name of the module to deploy.
// +optional
name?: string @go(Name)
name?: null | string @go(Name,*string)

// Namespace contains the namespace to deploy the module to.
namespace: (_ | *"default") & {
Expand All @@ -256,14 +256,19 @@ version: "1.0"

// Registry contains the registry to pull the module from.
// +optional
registry?: string @go(Registry)
registry?: null | string @go(Registry,*string)

// Type contains the type of the module.
type: (_ | *"kcl") & {
string
} @go(Type)

// Values contains the values to pass to the deployment module.
values: _ @go(Values,any)

// Version contains the version of the deployment module.
// +optional
version?: string @go(Version)
version?: null | string @go(Version,*string)
}

// Project contains the configuration for the project.
Expand Down
3 changes: 3 additions & 0 deletions lib/project/schema/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type DeploymentModule struct {
// +optional
Registry *string `json:"registry"`

// Type contains the type of the module.
Type string `json:"type"`

// Values contains the values to pass to the deployment module.
Values any `json:"values"`

Expand Down
Loading