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

Delete resources no longer in git #1442

Merged
merged 24 commits into from
Feb 27, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
21f04ce
feat: annotate stack with label and checksum
Timer Oct 10, 2018
41a6d38
Scan cluster stack and compare hash during sync
Timer Oct 11, 2018
0840915
feat: delete orphaned resources
Timer Oct 12, 2018
f76156e
Move garbage collection into cluster implementation
squaremo Oct 18, 2018
e2b140f
Bring tests up to date with sync changes
squaremo Nov 8, 2018
9fd2441
Clear up use of annotations and labels for sync
squaremo Nov 26, 2018
9c15d5c
Avoid deleting resources that did not apply OK
squaremo Nov 26, 2018
5810dd2
Respect "ignore" when syncing and GCing
squaremo Dec 19, 2018
6173f6b
Move kubernetes Sync code into sync.go
squaremo Dec 20, 2018
b26ad33
Use checksum per resource
squaremo Dec 20, 2018
d52f799
Rationalise logging of sync ignore annotation
squaremo Jan 10, 2019
1ed6e23
Remove Manifests#ParseManifests
squaremo Jan 14, 2019
a6238ba
Account for namespace defaulting
squaremo Jan 16, 2019
d48609a
Assign namespaces after parsing
squaremo Feb 4, 2019
ce36998
Invalidate discovery cache when custom resources change
squaremo Feb 7, 2019
927f9f3
Simplify sync structures
squaremo Feb 20, 2019
60346ef
Use cached discovery client in sync too
squaremo Feb 21, 2019
692a96b
Separate cached discovery code (and testing)
squaremo Feb 21, 2019
145fabe
Tidy kuberesource methods
squaremo Feb 21, 2019
93bccbf
Use git repo config to identify SyncSet
squaremo Feb 25, 2019
1d86d57
Delegate GroupVersion parsing to schema.ParseGroupVersion
2opremio Feb 26, 2019
aeef2c6
Obtain the default namespace directly from kubeconfig
2opremio Feb 26, 2019
c6e2c4e
Factor out garbage-collection code
2opremio Feb 26, 2019
e949383
Document the experimental garbage collection feature
squaremo Feb 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Obtain the default namespace directly from kubeconfig
  • Loading branch information
2opremio committed Feb 26, 2019
commit aeef2c6a3bea1804180c4917fba3e1f941987ad4
5 changes: 4 additions & 1 deletion cluster/kubernetes/cached_disco_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ func TestCachedDiscovery(t *testing.T) {

cachedDisco, store, _ := makeCachedDiscovery(coreClient.Discovery(), crdClient, shutdown, makeHandler)

namespacer, err := NewNamespacer(namespaceDefaulterFake("bar-ns"), cachedDisco)
saved := getDefaultNamespace
getDefaultNamespace = func() (string, error) { return "bar-ns", nil }
defer func() { getDefaultNamespace = saved }()
namespacer, err := NewNamespacer(cachedDisco)
if err != nil {
t.Fatal(err)
}
Expand Down
38 changes: 32 additions & 6 deletions cluster/kubernetes/namespacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,54 @@ import (
"fmt"

"k8s.io/client-go/discovery"
"k8s.io/client-go/tools/clientcmd"

kresource "github.com/weaveworks/flux/cluster/kubernetes/resource"
)

// The namespace to presume if something doesn't have one, and we
// haven't been told what to use as a fallback. This is what
// `kubectl` uses when there's no config setting the fallback
// namespace.
const defaultFallbackNamespace = "default"

type namespaceViaDiscovery struct {
fallbackNamespace string
disco discovery.DiscoveryInterface
}

type namespaceDefaulter interface {
GetDefaultNamespace() (string, error)
}

// NewNamespacer creates an implementation of Namespacer
func NewNamespacer(ns namespaceDefaulter, d discovery.DiscoveryInterface) (*namespaceViaDiscovery, error) {
fallback, err := ns.GetDefaultNamespace()
func NewNamespacer(d discovery.DiscoveryInterface) (*namespaceViaDiscovery, error) {
fallback, err := getDefaultNamespace()
if err != nil {
return nil, err
}
return &namespaceViaDiscovery{fallbackNamespace: fallback, disco: d}, nil
}

// getDefaultNamespace returns the fallback namespace used by the
// when a namespaced resource doesn't have one specified. This is
// used when syncing to anticipate the identity of a resource in the
// cluster given the manifest from a file (which may be missing the
// namespace).
// A variable is used for mocking in tests.
var getDefaultNamespace = func() (string, error) {
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{},
).RawConfig()
if err != nil {
return "", err
}

cc := config.CurrentContext
if c, ok := config.Contexts[cc]; ok && c.Namespace != "" {
return c.Namespace, nil
}

return defaultFallbackNamespace, nil
}

// effectiveNamespace yields the namespace that would be used for this
// resource were it applied, taking into account the kind of the
// resource, and local configuration.
Expand Down
42 changes: 34 additions & 8 deletions cluster/kubernetes/namespacer_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package kubernetes

import (
"io/ioutil"
"os"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -9,12 +11,6 @@ import (
kresource "github.com/weaveworks/flux/cluster/kubernetes/resource"
)

type namespaceDefaulterFake string

func (ns namespaceDefaulterFake) GetDefaultNamespace() (string, error) {
return string(ns), nil
}

var getAndList = metav1.Verbs([]string{"get", "list"})

func makeFakeClient() *corefake.Clientset {
Expand All @@ -39,8 +35,38 @@ func makeFakeClient() *corefake.Clientset {
}

func TestNamespaceDefaulting(t *testing.T) {
testKubeconfig := `apiVersion: v1
clusters: []
contexts:
- context:
cluster: cluster
namespace: namespace
user: user
name: context
current-context: context
kind: Config
preferences: {}
users: []
`
err := ioutil.WriteFile("testkubeconfig", []byte(testKubeconfig), 0600)
if err != nil {
t.Fatal("cannot create test kubeconfig file")
}
defer os.Remove("testkubeconfig")

os.Setenv("KUBECONFIG", "testkubeconfig")
defer os.Unsetenv("KUBECONFIG")
coreClient := makeFakeClient()
nser, err := NewNamespacer(namespaceDefaulterFake("fallback-ns"), coreClient.Discovery())

ns, err := getDefaultNamespace()
if err != nil {
t.Fatal("cannot get default namespace")
}
if ns != "namespace" {
t.Fatal("unexpected default namespace", ns)
}

nser, err := NewNamespacer(coreClient.Discovery())
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -86,6 +112,6 @@ metadata:
}

assertEffectiveNamespace("foo-ns:deployment/hasNamespace", "foo-ns")
assertEffectiveNamespace("<cluster>:deployment/noNamespace", "fallback-ns")
assertEffectiveNamespace("<cluster>:deployment/noNamespace", "namespace")
assertEffectiveNamespace("spurious:namespace/notNamespaced", "")
}
29 changes: 0 additions & 29 deletions cluster/kubernetes/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ import (
const (
syncSetLabel = kresource.PolicyPrefix + "sync-set"
checksumAnnotation = kresource.PolicyPrefix + "sync-checksum"

// The namespace to presume if something doesn't have one, and we
// haven't been told what to use as a fallback. This is what
// `kubectl` uses when there's no config setting the fallback
// namespace.
DefaultFallbackNamespace = "default"
)

// Sync takes a definition of what should be running in the cluster,
Expand Down Expand Up @@ -334,29 +328,6 @@ func (c *Kubectl) connectArgs() []string {
return args
}

// GetDefaultNamespace returns the fallback namespace used by the
// applied when a namespaced resource doesn't have one specified. This
// is used when syncing to anticipate the identity of a resource in
// the cluster given the manifest from a file (which may be missing
// the namespace).
func (k *Kubectl) GetDefaultNamespace() (string, error) {
cmd := k.kubectlCommand("config", "get-contexts", "--no-headers")
out, err := cmd.Output()
if err != nil {
return "", err
}
lines := bytes.Split(out, []byte("\n"))
for _, line := range lines {
words := bytes.Fields(line)
if len(words) > 1 && string(words[0]) == "*" {
if len(words) == 5 {
return string(words[4]), nil
}
}
}
return DefaultFallbackNamespace, nil
}

// rankOfKind returns an int denoting the position of the given kind
// in the partial ordering of Kubernetes resources, according to which
// kinds depend on which (derived by hand).
Expand Down
5 changes: 4 additions & 1 deletion cluster/kubernetes/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,10 @@ metadata:
}

test := func(t *testing.T, kube *Cluster, defs, expectedAfterSync string, expectErrors bool) {
namespacer, err := NewNamespacer(namespaceDefaulterFake(defaultTestNamespace), kube.client.coreClient.Discovery())
saved := getDefaultNamespace
getDefaultNamespace = func() (string, error) { return defaultTestNamespace, nil }
defer func() { getDefaultNamespace = saved }()
namespacer, err := NewNamespacer(kube.client.coreClient.Discovery())
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/fluxd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func main() {
// There is only one way we currently interpret a repo of
// files as manifests, and that's as Kubernetes yamels.
k8sManifests = &kubernetes.Manifests{}
k8sManifests.Namespacer, err = kubernetes.NewNamespacer(kubectlApplier, discoClientset)
k8sManifests.Namespacer, err = kubernetes.NewNamespacer(discoClientset)

if err != nil {
logger.Log("err", err)
Expand Down