Skip to content

Commit

Permalink
Merge pull request #271 from utilitywarehouse/decomission-cue
Browse files Browse the repository at this point in the history
Decomission cue
  • Loading branch information
hectorhuertas committed Sep 28, 2022
2 parents c36c7af + 0e15b87 commit 31e9193
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 106 deletions.
9 changes: 0 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@ WORKDIR /src
RUN apk --no-cache add git gcc make musl-dev curl bash openssh-client

ENV \
CUE_VERSION=v0.4.2 \
HOF_VERSION=0.6.1 \
STRONGBOX_VERSION=1.0.0 \
KUBECTL_VERSION=v1.24.4 \
KUSTOMIZE_VERSION=v4.5.5

RUN os=$(go env GOOS) && arch=$(go env GOARCH) \
&& curl -Ls https://github.com/cue-lang/cue/releases/download/${CUE_VERSION}/cue_${CUE_VERSION}_${os}_${arch}.tar.gz \
| tar xz -C /usr/local/bin/ \
&& chmod +x /usr/local/bin/cue \
&& curl -Ls -o /usr/local/bin/hof https://github.com/hofstadter-io/hof/releases/download/v${HOF_VERSION}/hof_${HOF_VERSION}_$(uname)_$(uname -m) \
&& chmod +x /usr/local/bin/hof \
&& curl -Ls -o /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/${os}/${arch}/kubectl \
&& chmod +x /usr/local/bin/kubectl \
&& curl -Ls https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_${os}_${arch}.tar.gz \
Expand All @@ -39,8 +32,6 @@ RUN apk --no-cache add git openssh-client tini
COPY templates/ /templates/
COPY static/ /static/
COPY --from=build \
/usr/local/bin/cue \
/usr/local/bin/hof \
/usr/local/bin/kubectl \
/usr/local/bin/kustomize \
/usr/local/bin/strongbox \
Expand Down
9 changes: 0 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,6 @@ reliably if you aren't using the RBAC
[authorization module](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#authorization-modules).
In which case, the prune whitelist may be empty or incomplete.

## CUE integration
In addition to plain yaml and [Kustomize](https://kustomize.io/), kube-applier can also apply [CUE](https://cuelang.org/) configurations.

If a namespace contains .cue files, kube-applier will run `cue build .` and apply the output of the command, that should produce valid kubernetes manifests.

It is up to the namespace to define how the cue files are organized and to provide a custom `build` command that converts them to yaml. Some documentation about how to it can be found in the [tool](https://pkg.go.dev/cuelang.org/go/pkg/tool) pkg documentation and in [cuetorials](https://cuetorials.com/first-steps/scripting/)

Until cue implements a native dependency manager, kube-applier uses [hof](https://github.com/hofstadter-io/hof) to define and pull external modules. Documentation on how it works can be found in [cuetorials](https://cuetorials.com/first-steps/modules-and-packages/)

## Deploying

Included is a Kustomize (https://kustomize.io/) base you can reference in your
Expand Down
109 changes: 21 additions & 88 deletions kubectl/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import (
"context"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"

Expand Down Expand Up @@ -103,16 +101,6 @@ func NewClient(host, label, kubeCtlPath string, kubeCtlOpts []string) *Client {
}
}

func detectCue(path string) bool {
files, _ := ioutil.ReadDir(path)
for _, file := range files {
if filepath.Ext(file.Name()) == ".cue" {
return true
}
}
return false
}

// Apply attempts to "kubectl apply" the files located at path. It returns the
// full apply command and its output.
func (c *Client) Apply(ctx context.Context, path string, options ApplyOptions) (string, string, error) {
Expand All @@ -124,11 +112,8 @@ func (c *Client) Apply(ctx context.Context, path string, options ApplyOptions) (
} else if _, err := os.Stat(path + "/Kustomization"); err == nil {
kustomize = true
}

cue := detectCue(path)

if kustomize || cue {
cmd, out, err := c.applyFromBuilders(ctx, path, options, kustomize, cue)
if kustomize {
cmd, out, err := c.applyKustomize(ctx, path, options)
return sanitiseCmdStr(cmd), out, err
}
cmd, out, err := c.applyPath(ctx, path, options)
Expand Down Expand Up @@ -158,86 +143,34 @@ func (c *Client) applyPath(ctx context.Context, path string, options ApplyOption
return cmdStr, out, nil
}

// applyFromBuilders runs kustomize and cue on the path, merges the resulting manifests and pipes them to `kubectl apply -f -`
func (c *Client) applyFromBuilders(ctx context.Context, path string, options ApplyOptions, kustomize, cue bool) (string, string, error) {
var kustomizeBytes, cueBytes []byte
var cmdStr, kustomizeCmdStr, cueCmdStr string
// applyKustomize does a `kustomize build | kubectl apply -f -` on the path
func (c *Client) applyKustomize(ctx context.Context, path string, options ApplyOptions) (string, string, error) {
var kustomizeStdout, kustomizeStderr bytes.Buffer

if kustomize {
var kustomizeStdout, kustomizeStderr bytes.Buffer
kustomizeCmd := exec.CommandContext(ctx, "kustomize", "build", path)
options.setCommandEnvironment(kustomizeCmd)
kustomizeCmd.Stdout = &kustomizeStdout
kustomizeCmd.Stderr = &kustomizeStderr

kustomizeCmd := exec.CommandContext(ctx, "kustomize", "build", path)
options.setCommandEnvironment(kustomizeCmd)
kustomizeCmd.Stdout = &kustomizeStdout
kustomizeCmd.Stderr = &kustomizeStderr

err := kustomizeCmd.Run()
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
err = errors.Wrap(ctx.Err(), err.Error())
}
return kustomizeCmd.String(), kustomizeStderr.String(), err
}
kustomizeBytes = kustomizeStdout.Bytes()
kustomizeCmdStr = kustomizeCmd.String()
}

if cue {
if _, err := os.Stat(path + "/cue.mods"); err == nil {
var hofStdout, hofStderr bytes.Buffer
hofCmd := exec.CommandContext(ctx, "hof", "mod", "vendor", "cue")
hofCmd.Dir = path
options.setCommandEnvironment(hofCmd)
hofCmd.Stdout = &hofStdout
hofCmd.Stderr = &hofStderr

err := hofCmd.Run()
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
err = errors.Wrap(ctx.Err(), err.Error())
}
return hofCmd.String(), hofStderr.String(), err
}
}

var cueStdout, cueStderr bytes.Buffer

cueCmd := exec.CommandContext(ctx, "cue", "build", ".")
cueCmd.Dir = path
options.setCommandEnvironment(cueCmd)
cueCmd.Stdout = &cueStdout
cueCmd.Stderr = &cueStderr

err := cueCmd.Run()
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
err = errors.Wrap(ctx.Err(), err.Error())
}
return cueCmd.String(), cueStderr.String(), err
err := kustomizeCmd.Run()
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
err = errors.Wrap(ctx.Err(), err.Error())
}
cueBytes = cueStdout.Bytes()
cueCmdStr = cueCmd.String() + " @ " + path
}

if kustomize && cue {
cmdStr = "(`" + kustomizeCmdStr + "` + `" + cueCmdStr + "`)"
} else if kustomize {
cmdStr = kustomizeCmdStr
} else {
cmdStr = cueCmdStr
return kustomizeCmd.String(), kustomizeStderr.String(), err
}

// Combine cue and kustomize
stdout := append(kustomizeBytes, []byte("\n---\n")...)
stdout = append(stdout, cueBytes...)

// Split the stdout into secrets and other resources
stdout, err := io.ReadAll(&kustomizeStdout)
if err != nil {
return kustomizeCmd.String(), "error reading kustomize output", err
}
resources, secrets, err := splitSecrets(stdout)
if err != nil {
return cmdStr, "error extracting secrets from builders output", err
return kustomizeCmd.String(), "error extracting secrets from kustomize output", err
}
if len(resources) == 0 && len(secrets) == 0 {
return cmdStr, "", fmt.Errorf("No resources were extracted from the builders output")
return kustomizeCmd.String(), "", fmt.Errorf("No resources were extracted from the kustomize output")
}

// This is the command we are effectively applying. In actuality we're splitting it into two
Expand All @@ -252,7 +185,7 @@ func (c *Client) applyFromBuilders(ctx context.Context, path string, options App
// Add opts that are specific to this client
displayArgs = append(c.KubeCtlOpts, displayArgs...)
kubectlCmd := exec.Command(c.KubeCtlPath, displayArgs...)
cmdStr = cmdStr + " | " + kubectlCmd.String()
cmdStr := kustomizeCmd.String() + " | " + kubectlCmd.String()

var kubectlOut string

Expand Down

0 comments on commit 31e9193

Please sign in to comment.