142 lines
3.6 KiB
Go
142 lines
3.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"kforge/internal/config"
|
|
"kforge/internal/generator"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
generateEnvs []string
|
|
generateOutput string
|
|
generateDry bool
|
|
)
|
|
|
|
var generateCmd = &cobra.Command{
|
|
Use: "generate",
|
|
Short: "Generate Kubernetes manifests from kforge.yml",
|
|
Long: `Reads kforge.yml (or the file specified with --config), resolves
|
|
each requested environment, and writes flat Kubernetes manifest
|
|
files to the output directory.
|
|
|
|
If no --env flags are given, manifests are generated for all
|
|
environments defined in kforge.yml.
|
|
|
|
Examples:
|
|
kforge generate
|
|
kforge generate --env staging
|
|
kforge generate --env staging --env production
|
|
kforge generate --env production --output .kube/
|
|
kforge generate --dry-run`,
|
|
RunE: runGenerate,
|
|
}
|
|
|
|
func init() {
|
|
generateCmd.Flags().StringArrayVarP(&generateEnvs, "env", "e", nil,
|
|
"Environment(s) to generate (default: all)")
|
|
generateCmd.Flags().StringVarP(&generateOutput, "output", "o", ".kforge-out",
|
|
"Directory to write generated manifests into")
|
|
generateCmd.Flags().BoolVar(&generateDry, "dry-run", false,
|
|
"Print manifests to stdout instead of writing files")
|
|
rootCmd.AddCommand(generateCmd)
|
|
}
|
|
|
|
func runGenerate(cmd *cobra.Command, args []string) error {
|
|
cfg, err := loadConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
envKeys := generateEnvs
|
|
if len(envKeys) == 0 {
|
|
envKeys = config.EnvironmentKeys(cfg)
|
|
}
|
|
|
|
if !generateDry {
|
|
if err := os.MkdirAll(generateOutput, 0o755); err != nil {
|
|
return fmt.Errorf("creating output directory: %w", err)
|
|
}
|
|
}
|
|
|
|
for _, envKey := range envKeys {
|
|
if err := generateForEnv(cfg, envKey); err != nil {
|
|
return fmt.Errorf("env %q: %w", envKey, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func generateForEnv(cfg *config.KforgeConfig, envKey string) error {
|
|
env, err := config.ResolveEnvironment(cfg, envKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Core manifests (Service, Deployment, Ingress, Certs).
|
|
coreYAML, err := generator.GenerateAll(&env, cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("generating core manifests: %w", err)
|
|
}
|
|
|
|
// Infrastructure manifests.
|
|
infraManifests, err := generator.GenerateInfrastructure(&env)
|
|
if err != nil {
|
|
return fmt.Errorf("generating infrastructure manifests: %w", err)
|
|
}
|
|
|
|
// Collect all infrastructure env vars and append to deployment.
|
|
// We re-generate core manifests after injecting infra env vars.
|
|
var infraEnvVars []config.EnvVarConfig
|
|
for _, m := range infraManifests {
|
|
infraEnvVars = append(infraEnvVars, m.EnvVars...)
|
|
}
|
|
if len(infraEnvVars) > 0 {
|
|
env.EnvVars = config.MergeEnvVars(env.EnvVars, infraEnvVars)
|
|
coreYAML, err = generator.GenerateAll(&env, cfg)
|
|
if err != nil {
|
|
return fmt.Errorf("re-generating core manifests with infra vars: %w", err)
|
|
}
|
|
}
|
|
|
|
if generateDry {
|
|
printDryRun(envKey, "core", coreYAML)
|
|
for _, m := range infraManifests {
|
|
printDryRun(envKey, m.Name, m.Content)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Write core manifest.
|
|
coreFile := filepath.Join(generateOutput, envKey+"-core.yaml")
|
|
if err := os.WriteFile(coreFile, []byte(coreYAML), 0o644); err != nil {
|
|
return fmt.Errorf("writing core manifest: %w", err)
|
|
}
|
|
fmt.Printf(" ✓ %s\n", coreFile)
|
|
|
|
// Write infra manifests.
|
|
for _, m := range infraManifests {
|
|
infraFile := filepath.Join(generateOutput, envKey+"-infra-"+m.Name+".yaml")
|
|
if err := os.WriteFile(infraFile, []byte(m.Content), 0o644); err != nil {
|
|
return fmt.Errorf("writing %s manifest: %w", m.Name, err)
|
|
}
|
|
fmt.Printf(" ✓ %s\n", infraFile)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func printDryRun(envKey, name, content string) {
|
|
fmt.Printf("\n%s\n# --- %s / %s ---\n%s\n",
|
|
generator.Separator,
|
|
strings.ToUpper(envKey),
|
|
name,
|
|
content,
|
|
)
|
|
}
|