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

Commit

Permalink
Apply namespaceless objects to default namespace
Browse files Browse the repository at this point in the history
In some not-so-well-defined cases, applying an object to the default namespace
can fail when its yaml doesn't explicitly specify the namespace. The simplest
way to overcome this is to separate them out and pass the namespace flag to
kubectl.
  • Loading branch information
Sam Broughton committed Dec 22, 2017
1 parent ab35632 commit 9e81f31
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 46 deletions.
11 changes: 7 additions & 4 deletions cluster/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package kubernetes
import (
"bytes"
"fmt"
"io"
"sync"

k8syaml "github.com/ghodss/yaml"
Expand Down Expand Up @@ -46,10 +45,15 @@ type apiObject struct {
bytes []byte
Kind string `yaml:"kind"`
Metadata struct {
Name string `yaml:"name"`
Name string `yaml:"name"`
Namespace string `yaml:"namespace"`
} `yaml:"metadata"`
}

func (o *apiObject) hasNamespace() bool {
return o.Metadata.Namespace != ""
}

// --- add-ons

// Kubernetes has a mechanism of "Add-ons", whereby manifest files
Expand Down Expand Up @@ -82,8 +86,7 @@ func isAddon(obj namespacedLabeled) bool {
// --- /add ons

type Applier interface {
doCommand(log.Logger, string, io.Reader) error
stage(string, string, *apiObject)
stage(id, cmd string, obj *apiObject)
execute(log.Logger, cluster.SyncError)
}

Expand Down
23 changes: 3 additions & 20 deletions cluster/kubernetes/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package kubernetes
// adequate. Starting with Sync.

import (
"io"
"testing"

"github.com/go-kit/kit/log"
Expand All @@ -14,30 +13,14 @@ import (

type mockApplier struct {
commandRun bool
applyErr error
deleteErr error

changeSet
}

func (m *mockApplier) doCommand(_ log.Logger, command string, _ io.Reader) error {
m.commandRun = true
switch command {
case "apply":
return m.applyErr
case "delete":
return m.deleteErr
default:
return nil
}
}

func (m *mockApplier) execute(_ log.Logger, errs cluster.SyncError) {
func (m *mockApplier) execute(_ log.Logger, _ cluster.SyncError) {
for _, cmd := range cmds {
if len(m.objs[cmd]) > 0 {
if err := m.doCommand(nil, cmd, nil); err != nil {
errs[cmd] = err
}
if len(m.objs[cmd]) != 0 {
m.commandRun = true
}
}
}
Expand Down
66 changes: 44 additions & 22 deletions cluster/kubernetes/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,30 @@ func (c *Kubectl) execute(logger log.Logger, errs cluster.SyncError) {
defer c.changeSet.clear()

for _, cmd := range cmds {
buf := &bytes.Buffer{}
for _, obj := range c.objs[cmd] {
fmt.Fprintln(buf, "---")
fmt.Fprintln(buf, string(obj.bytes))
}
noNsObjs := c.noNsObjs[cmd]
nsObjs := c.nsObjs[cmd]

if err := c.doCommand(logger, cmd, buf); err != nil {
for _, obj := range c.objs[cmd] {
if err := c.doCommand(logger, makeMultidoc(noNsObjs), cmd, "--namespace", "default"); err != nil {
for _, obj := range noNsObjs {
r := bytes.NewReader(obj.bytes)
if err := c.doCommand(logger, cmd, r); err != nil {
errs[obj.Metadata.Name] = err
if err := c.doCommand(logger, r, cmd, "--namespace", "default"); err != nil {
errs[obj.id] = err
}
}
}
if err := c.doCommand(logger, makeMultidoc(nsObjs), cmd); err != nil {
for _, obj := range nsObjs {
r := bytes.NewReader(obj.bytes)
if err := c.doCommand(logger, r, cmd); err != nil {
errs[obj.id] = err
}
}
}
}
}

func (c *Kubectl) doCommand(logger log.Logger, command string, r io.Reader) error {
args := []string{command, "-f", "-"}
func (c *Kubectl) doCommand(logger log.Logger, r io.Reader, args ...string) error {
args = append(args, "-f", "-")
cmd := c.kubectlCommand(args...)
cmd.Stdin = r
stderr := &bytes.Buffer{}
Expand All @@ -98,29 +103,46 @@ func (c *Kubectl) doCommand(logger log.Logger, command string, r io.Reader) erro
return err
}

func makeMultidoc(objs []obj) *bytes.Buffer {
buf := &bytes.Buffer{}
for _, obj := range objs {
fmt.Fprintln(buf, "---")
fmt.Fprintln(buf, obj.bytes)
}
return buf
}

func (c *Kubectl) kubectlCommand(args ...string) *exec.Cmd {
return exec.Command(c.exe, append(c.connectArgs(), args...)...)
}

type changeSet struct {
objs map[string][]obj
nsObjs map[string][]obj
noNsObjs map[string][]obj
}

func (c *changeSet) init() {
if c.nsObjs == nil {
c.nsObjs = make(map[string][]obj)
}
if c.noNsObjs == nil {
c.noNsObjs = make(map[string][]obj)
}
}

func (c *changeSet) stage(cmd, id string, o *apiObject) {
if c.objs == nil {
c.objs = make(map[string][]obj)
c.init()
if o.hasNamespace() {
c.nsObjs[cmd] = append(c.nsObjs[cmd], obj{id, o})
} else {
c.noNsObjs[cmd] = append(c.noNsObjs[cmd], obj{id, o})
}
c.objs[cmd] = append(c.objs[cmd], obj{id, o})
}

func (c *changeSet) clear() {
if c.objs == nil {
c.objs = make(map[string][]obj)
return
}
for cmd := range c.objs {
c.objs[cmd] = nil
}
c.nsObjs = nil
c.noNsObjs = nil
c.init()
}

type obj struct {
Expand Down

0 comments on commit 9e81f31

Please sign in to comment.