Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[kpt deployer] Add "local-config" annotation to kpt fn configs. #4803

Merged
merged 2 commits into from
Sep 19, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ require (
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c
k8s.io/api v0.18.1
k8s.io/apiextensions-apiserver v0.18.1 // indirect
k8s.io/apimachinery v0.18.1
k8s.io/apimachinery v0.19.2
k8s.io/client-go v0.18.1
k8s.io/kubectl v0.0.0-20190831163037-3b58a944563f
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89
knative.dev/pkg v0.0.0-20200416021448-f68639f04b39 // indirect
sigs.k8s.io/yaml v1.2.0
)
51 changes: 50 additions & 1 deletion pkg/skaffold/deploy/kpt.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,16 @@ import (
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/event"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
k8syaml "sigs.k8s.io/yaml"
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
)

var (
const (
inventoryTemplate = "inventory-template.yaml"
kptHydrated = ".kpt-hydrated"
pipeline = ".pipeline"
kptFnAnnotation = "config.kubernetes.io/function"
kptFnLocalConfig = "config.kubernetes.io/local-config"
)

// KptDeployer deploys workflows with kpt CLI
Expand Down Expand Up @@ -186,6 +190,12 @@ func (k *KptDeployer) renderManifests(ctx context.Context, _ io.Writer, builds [
return nil, nil
}

// Remove the kpt function from the manipulated resources.
manifests, err = k.ExcludeKptFn(manifests)
if err != nil {
return nil, fmt.Errorf("exclude kpt fn from manipulated resources: %w", err)
}

manifests, err = manifests.ReplaceImages(builds)
if err != nil {
return nil, fmt.Errorf("replacing images in manifests: %w", err)
Expand Down Expand Up @@ -270,6 +280,45 @@ func (k *KptDeployer) kptFnRun(ctx context.Context) (deploy.ManifestList, error)
return manifests, nil
}

// ExcludeKptFn adds an annotation "config.kubernetes.io/local-config: 'true'" to kpt function.
// This will exclude kpt functions from deployed to the cluster in kpt live apply.
func (k *KptDeployer) ExcludeKptFn(manifest deploy.ManifestList) (deploy.ManifestList, error) {
yuwenma marked this conversation as resolved.
Show resolved Hide resolved
var newManifest deploy.ManifestList
for _, yByte := range manifest {
// Convert yaml byte config to unstructured.Unstructured
jByte, _ := k8syaml.YAMLToJSON(yByte)
var obj unstructured.Unstructured
if err := obj.UnmarshalJSON(jByte); err != nil {
return nil, fmt.Errorf("unmarshaling config: %w", err)
}
// skip if the resource is not kpt fn config.
if _, ok := obj.GetAnnotations()[kptFnAnnotation]; !ok {
newManifest = append(newManifest, yByte)
continue
}
// skip if the kpt fn has local-config annotation specified.
if _, ok := obj.GetAnnotations()[kptFnLocalConfig]; ok {
newManifest = append(newManifest, yByte)
continue
}

// Add "local-config" annotation to kpt fn config.
anns := obj.GetAnnotations()
anns[kptFnLocalConfig] = "true"
obj.SetAnnotations(anns)
jByte, err := obj.MarshalJSON()
if err != nil {
return nil, fmt.Errorf("marshaling to json: %w", err)
}
newYByte, err := k8syaml.JSONToYAML(jByte)
if err != nil {
return nil, fmt.Errorf("converting json to yaml: %w", err)
}
newManifest.Append(newYByte)
}
return newManifest, nil
}

// getApplyDir returns the path to applyDir if specified by the user. Otherwise, getApplyDir
// creates a hidden directory named .kpt-hydrated in place of applyDir.
func (k *KptDeployer) getApplyDir(ctx context.Context) (string, error) {
Expand Down
100 changes: 100 additions & 0 deletions pkg/skaffold/deploy/kpt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
"strings"
"testing"

deploy "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/kubectl"

"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
Expand Down Expand Up @@ -889,6 +891,104 @@ func TestKpt_KptCommandArgs(t *testing.T) {
}
}

// TestKpt_ExcludeKptFn checks the declarative kpt fn has expected annotations added.
func TestKpt_ExcludeKptFn(t *testing.T) {
// A declarative fn.
testFn1 := []byte(`apiVersion: v1
data:
annotation_name: k1
annotation_value: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake`)
// A declarative fn which has `local-config` annotation specified.
testFn2 := []byte(`apiVersion: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake
config.kubernetes.io/local-config: "false"
data:
annotation_name: k2
annotation_value: v2`)
testPod := []byte(`apiVersion: v1
kind: Pod
metadata:
namespace: default
spec:
containers:
- image: gcr.io/project/image1
name: image1`)
tests := []struct {
description string
manifests deploy.ManifestList
expected deploy.ManifestList
}{
{
description: "Add `local-config` annotation to kpt fn",
manifests: deploy.ManifestList{testFn1},
expected: deploy.ManifestList{[]byte(`apiVersion: v1
data:
annotation_name: k1
annotation_value: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake
config.kubernetes.io/local-config: "true"`)},
},
{
description: "Skip preset `local-config` annotation",
manifests: deploy.ManifestList{testFn2},
expected: deploy.ManifestList{[]byte(`apiVersion: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake
config.kubernetes.io/local-config: "false"
data:
annotation_name: k2
annotation_value: v2`)},
},
{
description: "Valid in kpt fn pipeline.",
manifests: deploy.ManifestList{testFn1, testFn2, testPod},
expected: deploy.ManifestList{[]byte(`apiVersion: v1
data:
annotation_name: k1
annotation_value: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake
config.kubernetes.io/local-config: "true"`), []byte(`apiVersion: v1
kind: ConfigMap
metadata:
annotations:
config.kubernetes.io/function: fake
config.kubernetes.io/local-config: "false"
data:
annotation_name: k2
annotation_value: v2`), []byte(`apiVersion: v1
kind: Pod
metadata:
namespace: default
spec:
containers:
- image: gcr.io/project/image1
name: image1`)},
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
k := NewKptDeployer(&kptConfig{}, nil)
actualManifest, err := k.ExcludeKptFn(test.manifests)
t.CheckErrorAndDeepEqual(false, err, test.expected.String(), actualManifest.String())
})
}
}

type kptConfig struct {
runcontext.RunContext // Embedded to provide the default values.
workingDir string
Expand Down
3 changes: 2 additions & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ k8s.io/api/storage/v1alpha1
k8s.io/api/storage/v1beta1
# k8s.io/apiextensions-apiserver v0.18.1
## explicit
# k8s.io/apimachinery v0.18.1 => k8s.io/apimachinery v0.17.4
# k8s.io/apimachinery v0.19.2 => k8s.io/apimachinery v0.17.4
## explicit
k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/errors
Expand Down Expand Up @@ -1131,6 +1131,7 @@ knative.dev/pkg/kmeta
knative.dev/pkg/kmp
knative.dev/pkg/tracker
# sigs.k8s.io/yaml v1.2.0
## explicit
sigs.k8s.io/yaml
# github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.0.1+incompatible
# github.com/containerd/containerd => github.com/containerd/containerd v1.3.4
Expand Down