Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Wire kubeyaml into the fluxd deployment
Browse files Browse the repository at this point in the history
To be able to use kubeyaml from within a pod, fluxd must have access
to the binaries. This requires a bit of a highwire performance:

 - use an initContainer in the Deployment to copy the files over to a
   shared volume
 - use an env entry to tell fluxd where to look for the binary

I took the opportunity to factor out the code that executes
`kubeyaml`.
  • Loading branch information
squaremo committed Mar 9, 2018
1 parent 8d63434 commit f34c43f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 43 deletions.
47 changes: 47 additions & 0 deletions cluster/kubernetes/kubeyaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package kubernetes

import (
"bytes"
"errors"
"os"
"os/exec"
"strings"
)

// KubeYAML is a placeholder value for calling the helper executable
// `kubeyaml`.
type KubeYAML struct {
}

// Image calls the kubeyaml subcommand `image` with the arguments given.
func (k KubeYAML) Image(in []byte, ns, kind, name, container, image string) ([]byte, error) {
args := []string{"image", "--namespace", ns, "--kind", kind, "--name", name}
args = append(args, "--container", container, "--image", image)
return execKubeyaml(in, args)
}

// Annotate calls the kubeyaml subcommand `annotate` with the arguments as given.
func (k KubeYAML) Annotate(in []byte, ns, kind, name string, policies ...string) ([]byte, error) {
args := []string{"annotate", "--namespace", ns, "--kind", kind, "--name", name}
args = append(args, policies...)
return execKubeyaml(in, args)
}

func execKubeyaml(in []byte, args []string) ([]byte, error) {
kubeyaml, err := exec.LookPath("kubeyaml")
if err != nil {
kubeyaml = os.ExpandEnv("${PLUGINS_PATH}/kubeyaml/kubeyaml")
}
cmd := exec.Command(kubeyaml, args...)
out := &bytes.Buffer{}
errOut := &bytes.Buffer{}
cmd.Stdin = bytes.NewBuffer(in)
cmd.Stdout = out
cmd.Stderr = errOut

err = cmd.Run()
if err != nil {
return nil, errors.New(strings.TrimSpace(errOut.String()))
}
return out.Bytes(), nil
}
17 changes: 2 additions & 15 deletions cluster/kubernetes/policies.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package kubernetes

import (
"bytes"
"fmt"
"os/exec"

"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
Expand Down Expand Up @@ -39,26 +37,15 @@ func (m *Manifests) UpdatePolicies(in []byte, resourceID flux.ResourceID, update
}
}

args := []string{"annotate", "--namespace", ns, "--kind", kind, "--name", name}

args := []string{}
for pol, val := range add {
args = append(args, fmt.Sprintf("%s%s=%s", resource.PolicyPrefix, pol, val))
}
for pol, _ := range del {
args = append(args, fmt.Sprintf("%s%s=", resource.PolicyPrefix, pol))
}

cmd := exec.Command("kubeyaml", args...)
out := &bytes.Buffer{}
errOut := &bytes.Buffer{}
cmd.Stdin = bytes.NewBuffer(in)
cmd.Stdout = out
cmd.Stderr = errOut
err := cmd.Run()
if err != nil {
return nil, errors.Wrap(err, errOut.String())
}
return out.Bytes(), nil
return (KubeYAML{}).Annotate(in, ns, kind, name, args...)
}

type containerManifest struct {
Expand Down
35 changes: 7 additions & 28 deletions cluster/kubernetes/update.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,21 @@
package kubernetes

import (
"bytes"
"os/exec"
"strings"

"github.com/pkg/errors"

"github.com/weaveworks/flux"
"github.com/weaveworks/flux/image"
)

// updatePodController takes the body of a Deployment resource definition
// (specified in YAML) and the name of the new image that should be put in the
// definition (in the format "repo.org/group/name:tag"). It returns a new
// resource definition body where all references to the old image have been
// replaced with the new one.
//
// This function has many additional requirements that are likely in flux. Read
// the source to learn about them.
func updatePodController(file []byte, resource flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) {
// updatePodController takes a YAML document stream (one or more YAML
// docs, as bytes), a resource ID referring to a controller, a
// container name, and the name of the new image that should be used
// for the container. It returns a new YAML stream where the image for
// the container has been replaced with the imageRef supplied.
func updatePodController(in []byte, resource flux.ResourceID, container string, newImageID image.Ref) ([]byte, error) {
namespace, kind, name := resource.Components()
if _, ok := resourceKinds[strings.ToLower(kind)]; !ok {
return nil, UpdateNotSupportedError(kind)
}

args := []string{"image", "--namespace", namespace, "--kind", kind, "--name", name}
args = append(args, "--container", container, "--image", newImageID.String())

println("TRACE:", "kubeyaml", strings.Join(args, " "))
cmd := exec.Command("kubeyaml", args...)
out := &bytes.Buffer{}
errOut := &bytes.Buffer{}
cmd.Stdin = bytes.NewBuffer(file)
cmd.Stdout = out
cmd.Stderr = errOut
if err := cmd.Run(); err != nil {
return nil, errors.New(strings.TrimSpace(errOut.String()))
}
return out.Bytes(), nil
return (KubeYAML{}).Image(in, namespace, kind, name, container, newImageID.String())
}
16 changes: 16 additions & 0 deletions deploy/flux-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,37 @@ spec:
spec:
serviceAccount: flux
volumes:
- name: plugins
emptyDir: {}
- name: git-key
secret:
secretName: flux-git-deploy
initContainers:
- name: kubeyaml
image: squaremo/kubeyaml:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: plugins
mountPath: /plugins
command: ["cp"]
args: ["-R", "/usr/lib/kubeyaml", "/plugins/"]
containers:
- name: flux
# There are no ":latest" images for flux. Find the most recent
# release or image version at https://quay.io/weaveworks/flux
# and replace the tag here.
image: quay.io/weaveworks/flux:1.2.3
imagePullPolicy: IfNotPresent
env:
- name: PLUGINS_PATH
value: /home/flux/plugins
ports:
- containerPort: 3030 # informational
volumeMounts:
- name: git-key
mountPath: /etc/fluxd/ssh
- name: plugins
mountPath: /home/flux/plugins
args:

# if you deployed memcached in a different namespace to flux,
Expand Down

0 comments on commit f34c43f

Please sign in to comment.