kargo

package module
v0.12.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 2, 2024 License: Apache-2.0 Imports: 10 Imported by: 3

README

kargo

kargo is a command-line application to deploy your Kubernetes application directly and indirectly.

By "direct", it means kargo is able to deploy the app by directly calling popular commands like kubectl, kustomize, helm, kompose.

By "indirect", it means kargo can let ArgoCD deploy your application using kustomize/helm/kompose by setting up ArgoCD on behalf of you.

Everyone in your team is able to trigger deployments via kargo, no matter which Kubernetes deployment tool you or your teammate is using. That's the benefit of introducing kargo into your environment.

If you're a part of the platform team, you'll probably want to encourage or enforce use of kargo, so that you can standardize deployments without forcing your team to use kubectl/kustomize/helm/argocd.

Usage

Standalone

kargo has two commands, kargo plan and kargo apply.

plan outputs the diff between the current state and the desired state of your application deployment, so that you can review changes before they are applied.

apply runs the deployment`

Embedded

kargo can be embedded into your own Go application.

You instantiate a kargo.Config and a kargo.Generator, and let the generator generates the commands to be executed to either "plan" or "apply" the config changes you made.

import (
  "github.com/mumoshu/kargo"
)

func yourAppDeploymentTool() error {
  c := &kargo.Config{
    Name:    "myapp",
    Path:    "testdata/compose",
    Kompose: &kargo.Kompose{},
    ArgoCD:  &kargo.ArgoCD{},
  }

  g := &kargo.Generator{
    GetValue: func(key string) (string, error) {
      return yourSecretManager.Get(key)
    },
    TailLogs: false,
  }

  cmds, err := g.ExecCmds(c, targ)
  if err != nil {
    return err
  }

  // Run the cmds with your favorite command runner.
}

See generator.go and generator_*_test.go files for more information.

Configuration

The below is the reference configuration that covers all the required and optional fields available for this provider:

# This maps to --plugin-env in case you're going to uses the `argocd` option below.
# Otherwise all the envs are set before calling commands (like kompose, kustomize, kubectl, helm, etc.)
env:
- name: STAGE
  value: prod
- name: FOO
  valueFrom: component_name.foo
# kustomize instructs kargo to deploy the app using `kustomize`.
# It has two major modes. The first mode directly calls `kustomize`, whereas
# the second indirectly call it via `argocd`.
# The first mode is triggered by setting only `helm`.
# The second is enabled when you set `argocd` along with `kustomize`.
kustomize:
  # kustomize.image maps to --kustomize-image of argocd-app-create.
  image:
# helm instructs kargo to deploy the app using `helm`.
# It has two major modes. The first mode directly calls `helm`, whereas
# the second indirectly call it via `argocd`.
# The first mode is triggered by setting only `helm`.
# The second is enabled when you set `argocd` along with `helm`.
helm:
  # helm.repo maps to --repo of argocd-app-create
  # in case kubernetes.argocd is not empty.
  repo: https://charts.helm.sh/stable
  # --helm-chart
  chart: mychart
  # --revision
  version: 1.2.3
  # helm.set corresponds to `--helm-set $name=$value` flags of `argocd app create` command
  set:
  - name: foo
    value: foo
  - name: bar
    valueFrom: component_name.bar
  valuesFiles:
  - path/to/values.yaml
argocd:
  # argocd.repo maps to --repo of argocd-app-create.
  repo: github.com/myorg/myrepo.git
  # argocd.path maps to --path of argocd-app-create.
  # Note: In case you had kubernetes.dir along with argocd.path,
  # kargo automatically git-push the content of dir to $argocd_repo/$argocd_path.
  # To opt-out of it, set `push: false`.
  path: path/to/dir/in/repo
  # --dir-recurse
  dirRecurse: true
  # --dest-namespace
  namespace: default
  # serverFrom maps to --dest-server where the flag value is take from the output of another kargo component
  serverFrom: component_name.k8s_endpoint
  # Note that the config management plugin definition in the configmap
  # and the --config-management-plugin flag passed to argocd-app-create # command is auto-generated.

Deploying to multiple environments

kargo does not have a "environments" concept or any feature related to that. It's intentionally out of the scope of this project to keep it simple.

However, you can still support multiple environments just by creating one kargo.yaml per environment.

Let's suppose you are deploying to two environments, production and preview. You start by creating production.kargo.yaml and preview.kargo.yaml.

When you want kargo to deploy to a specific environment, just give the corresponding kargo config file via the -f flag.

That is, you'll run kargo like kargo -f production.kargo.yaml apply for a production deployment, whereas it would be kargo -f preview.kargo.yaml apply for a preview deployment.

You'll ask how one could reduce the duplications and boilerplates in the two config files.

kargo assumes you would like to use a tool like cue or jsonnnet to produce the kargo config files. That way, you can use advanded features provided in those tools to reduce boiler plates and introduce any abstractions to compose your kargo config files in a maintainable manner.

Documentation

Index

Constants

View Source
const (
	// FieldTagKargo is used to defining kargo flags.
	// Currently, this is used to exclude the field from the field-to-flag conversion.
	// Example: Name `yaml:"name" kargo:""`
	FieldTagKargo = "kargo"

	// FieldTagArgoCD is used to defining helm-upgrade flags
	FieldTagCompose   = "compose"
	FieldTagHelm      = "helm"
	FieldTagKustomize = "kustomize"
	FieldTagKompose   = "kompose"
	// FieldTagArgoCDApp is used to defining argocd-app-create flags
	FieldTagArgoCDApp = "argocd-app"
)
View Source
const (
	KustomizeStrategyBuildAndKubectlApply = "BuildAndKubectlApply"
	KustomizeStrategySetImageAndCreatePR  = "SetImageAndCreatePullRequest"
)
View Source
const (
	Plan = iota
	Apply
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ArgoCD

type ArgoCD struct {
	Repo string `yaml:"repo" kargo:""`
	// Branch is the branch to be used for the deployment.
	// This isn't part of the arguments for argocd-repo-add because
	// it doesn't support branch.
	// However, we use it when you want to push manifests to a branch
	// and trigger a deployment.
	Branch   string `yaml:"branch" kargo:""`
	RepoFrom string `yaml:"repoFrom" kargo:""`

	RepoSSHPrivateKeyPath     string `yaml:"repoSSHPrivateKeyPath" kargo:""`
	RepoSSHPrivateKeyPathFrom string `yaml:"repoSSHPrivateKeyPathFrom" kargo:""`

	Path     string `yaml:"path" kargo:""`
	PathFrom string `yaml:"pathFrom" kargo:""`

	Upload []Upload `yaml:"upload" kargo:""`

	DirRecurse bool `yaml:"dirRecurse" argocd-app:"directory-recurse,paramless"`

	// Server is the ArgoCD server to be used for the deployment.
	Server string `yaml:"server" kargo:""`
	// ServerFrom is the key to be used to get the ArgoCD server from the environment.
	ServerFrom string `yaml:"serverFrom" kargo:""`
	// Username is the username to be used for the deployment.
	Username string `yaml:"username" kargo:""`
	// UsernameFrom is the key to be used to get the username from the environment.
	UsernameFrom string `yaml:"usernameFrom" kargo:""`
	// Password is the password to be used for the deployment.
	Password string `yaml:"password" kargo:""`
	// PasswordFrom is the key to be used to get the password from the environment.
	PasswordFrom string `yaml:"passwordFrom" kargo:""`
	// Insecure is set to true if the user wants to skip TLS verification.
	Insecure bool `yaml:"insecure" kargo:""`
	// InsecureFrom is the key to be used to get the insecure flag from the environment.
	InsecureFrom string `yaml:"insecureFrom" kargo:""`

	// Project is the ArgoCD project to be used for the deployment.
	Project string `yaml:"project" argocd-app:"project"`
	// Push is set to true if the user wants kargo to automatically
	// - git-clone the repo
	// - git-add the files in the config.Path
	// - git-commit
	// - git-push
	// so that it triggers the deployment.
	Push bool `yaml:"push" kargo:""`

	// DestName is the name of the K8s cluster where the deployment is to be done.
	DestName string `yaml:"name" kargo:""`
	// DestNameFrom is the key to be used to get the target K8s cluster name from the environment.
	DestNameFrom string `yaml:"nameFrom" kargo:""`

	// DestNamespace is the namespace to be used for the deployment.
	DestNamespace string `yaml:"namespace" kargo:""`
	// DestServer is the Kubernetes API endpoint of the cluster where the deployment is to be done.
	DestServer string `yaml:"destServer" kargo:""`
	// DestServerFrom is the key to be used to get the target Kubernetes API endpoint from the environment.
	DestServerFrom string `yaml:"destServerFrom" kargo:""`
	// ConfigManagementPlugin is the config management plugin to be used.
	ConfigManagementPlugin string `yaml:"configManagementPlugin" argocd-app:"config-management-plugin"`
}

type Args

type Args struct {
	// contains filtered or unexported fields
}

func AppendArgs

func AppendArgs(args *Args, i any, key string) (*Args, error)

func NewArgs

func NewArgs(vs ...interface{}) *Args

func (*Args) Append

func (a *Args) Append(vs ...interface{}) *Args

func (*Args) AppendStrings

func (a *Args) AppendStrings(s ...string) *Args

func (*Args) AppendValueFromOutput

func (a *Args) AppendValueFromOutput(ref string) *Args

func (*Args) AppendValueFromOutputWithPrefix

func (a *Args) AppendValueFromOutputWithPrefix(prefix, ref string) *Args

func (*Args) AppendValueIfOutput

func (a *Args) AppendValueIfOutput(v, ref string) *Args

func (*Args) Collect

func (a *Args) Collect(get func(string) (string, error)) ([]string, error)

func (*Args) CopyFrom

func (a *Args) CopyFrom(other *Args) *Args

func (*Args) Len

func (a *Args) Len() int

func (*Args) MustCollect

func (a *Args) MustCollect(get func(string) (string, error)) []string

func (*Args) String

func (a *Args) String() string

func (*Args) Visit

func (a *Args) Visit(str func(string), out func(DynArg), flag func(KargoValueProvider))

type BashScript

type BashScript struct {
	Script *Args
}

func NewBashScript

func NewBashScript(args *Args) *BashScript

func (*BashScript) KargoValue

func (b *BashScript) KargoValue(get GetValue) (string, error)

type Cmd

type Cmd struct {
	ID   string
	Name string
	Args *Args
	Dir  string
	// AddEnv is a map of environment variables to add to the command.
	// That is, the command will be run with the environment variables
	// specified in AddEnv in addition to the environment variables provided
	// by the current process(os.Environ).
	AddEnv map[string]string
}

func (*Cmd) String added in v0.2.0

func (c *Cmd) String() string

func (Cmd) ToArgs added in v0.2.0

func (c Cmd) ToArgs() *Args

type Compose

type Compose struct {
	EnableVals bool `yaml:"enableVals" kargo:""`
}

type Config

type Config struct {
	// Name is the application name.
	// It defaults to the basename of the path if
	// kargo is run as a command.
	Name      string     `yaml:"name" argocd-app:",arg"`
	Path      string     `yaml:"path" kargo:""`
	PathFrom  string     `yaml:"pathFrom" kargo:""`
	Env       []Env      `yaml:"env" argocd-app:"plugin-env"`
	Compose   *Compose   `yaml:"compose"`
	Kompose   *Kompose   `yaml:"kompose"`
	Kustomize *Kustomize `yaml:"kustomize"`
	Helm      *Helm      `yaml:"helm"`
	ArgoCD    *ArgoCD    `yaml:"argocd"`
}

type DynArg

type DynArg struct {
	// Prefix is a prefix to be prepended to the value of FromOutput.
	// For example, Prefix=foo= and FromOutput=bar will result in foo=$bar.
	// This is handy when you need to compose a command-line argument like --foo=$bar,
	// instead of --foo bar.
	Prefix string

	// FromOutput is a reference to an output of another kargo command.
	FromOutput string

	// Value is the value used when the FromOutput is provided and the output is non-empty.
	Value string
}

DynArg is a dynamic argument that is resolved at runtime. It is used to compose a command-line argument like --foo=$bar, where $bar is a value of another kargo command.

type Env

type Env struct {
	Name      string `yaml:"name"`
	Value     string `yaml:"value"`
	ValueFrom string `yaml:"valueFrom"`
}

func (Env) KargoValue

func (e Env) KargoValue(get GetValue) (string, error)

type Generator

type Generator struct {
	GetValue GetValue
	// TempDir is the directory to write kustomize-build output
	// for use by kubectl-apply.
	TempDir string
	// TailLogs is set to true if you want kargo to tail the logs
	TailLogs bool

	// ToolsCommand is the command to run kargo tools.
	//
	// If you set this to e.g. `mycmd tools`, kargo will run
	// `mycmd tools <tool> <args...>` if needed.
	//
	// An example of a tool is `create-pullrequest`, whose command becomes
	// `mycmd tools create-pullrequest <args...>`.
	//
	// This needs to be set if you want to use kargo tools.
	// If this is not set and kargo required to run a tool,
	// kargo will return an error.
	ToolsCommand []string

	// ToolName is the name of the tool to be used for gitops.
	// It becomes the prefix of the branch name to be created,
	// and the prefix of the environment variable name to be used.
	ToolName string

	// PullRequestOutputFile is the path to the file to write the pull request info to.
	PullRequestOutputFile string
}

Generator generates commands and config files required to plan and apply the deployment denoted by Config. This and Config is usually the two most interesting structs when you are going to use kargo as a Go library.

func (*Generator) ExecCmds

func (g *Generator) ExecCmds(c *Config, t Target) ([]Cmd, error)

type GetValue

type GetValue func(key string) (string, error)

type Helm

type Helm struct {
	Repo        string   `yaml:"repo" helm:""`
	Chart       string   `yaml:"chart" helm:"" argocd-app:"helm-chart"`
	Version     string   `yaml:"version" argocd-app:"revision"`
	Set         []Set    `yaml:"set" helm:"set" argocd-app:"helm-set"`
	ValuesFiles []string `yaml:"valuesFiles" helm:"values" argocd-app:"values"`
}

type Join

type Join struct {
	Args *Args
}

func NewJoin

func NewJoin(args *Args) *Join

func (*Join) KargoValue

func (b *Join) KargoValue(get GetValue) (string, error)

type KargoArgsAppender

type KargoArgsAppender interface {
	// KargoAppendArgs produces the arguments for the command
	// to plan and apply the configuration.
	KargoAppendArgs(args *Args, key string) (*Args, error)
}

type KargoValueProvider

type KargoValueProvider interface {
	// KargoValue returns the value of the flag
	KargoValue(get GetValue) (string, error)
}

type Kompose

type Kompose struct {
	EnableVals bool `yaml:"enableVals" kargo:""`
}

type Kustomize

type Kustomize struct {
	// Strategy is the strategy to be used for the deployment.
	//
	// The supported values are:
	// - BuildAndKubectlApply
	// - SetImageAndCreatePullRequest
	//
	// BuildAndKubectlApply is the default strategy.
	// It runs kustomize build and kubectl apply to deploy the application.
	//
	// SetImageAndCreatePullRequest runs kustomize edit set image and creates a pull request.
	// It's useful to trigger a deployment workflow in CI/CD.
	Strategy string          `yaml:"strategy" kargo:""`
	Images   KustomizeImages `yaml:"images" argocd-app:"kustomize-image"`
	Git      KustomizeGit    `yaml:"git" kargo:""`
}

type KustomizeGit added in v0.2.0

type KustomizeGit struct {
	Repo   string `yaml:"repo" kargo:""`
	Branch string `yaml:"branch" kargo:""`
	Path   string `yaml:"path" kargo:""`
}

type KustomizeImage

type KustomizeImage struct {
	Name          string `yaml:"name"`
	NewName       string `yaml:"newName"`
	NewTag        string `yaml:"newTag"`
	NewTagFrom    string `yaml:"newTagFrom"`
	NewDigestFrom string `yaml:"newDigestFrom"`
}

type KustomizeImages

type KustomizeImages []KustomizeImage

func (KustomizeImages) KargoAppendArgs

func (i KustomizeImages) KargoAppendArgs(args *Args, key string) (*Args, error)

type PullRequestOptions added in v0.8.1

type PullRequestOptions struct {
	// AssigneeIDs is the list of GitHub user IDs to assign to the pull request.
	// Each ID can be either an integer or a string.
	AssigneeIDs []string

	// OutputFile is the path to the file to write the pull request info to.
	OutputFile string

	// GitUserName is the name of the user to use for git commits.
	GitUserName string

	// GitUserEmail is the email of the user to use for git commits.
	GitUserEmail string
}

type Set

type Set struct {
	Name      string `yaml:"name"`
	Value     string `yaml:"value"`
	ValueFrom string `yaml:"valueFrom"`
}

func (Set) AppendArgoCDAppArgs

func (s Set) AppendArgoCDAppArgs(args []string, get GetValue) ([]string, error)

func (Set) AppendArgs

func (s Set) AppendArgs(args []string, get GetValue) ([]string, error)

func (Set) KargoValue

func (s Set) KargoValue(get GetValue) (string, error)

type Target

type Target int

type Upload

type Upload struct {
	Local  string `yaml:"local" kargo:""`
	Remote string `yaml:"remote" kargo:""`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL