Skip to content

Commit

Permalink
Add 'skaffold render' for kubectl deployer
Browse files Browse the repository at this point in the history
  • Loading branch information
nkubala committed Sep 25, 2019
1 parent 667bd76 commit e31af85
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 53 deletions.
125 changes: 125 additions & 0 deletions integration/render_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
Copyright 2019 The Skaffold Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package integration

import (
"bytes"
"context"
"testing"

"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext"
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestKubectlRender(t *testing.T) {
tests := []struct {
description string
builds []build.Artifact
input string
expectedOut string
}{
{
description: "normal render",
builds: []build.Artifact{
{
ImageName: "gcr.io/k8s-skaffold/skaffold",
Tag: "gcr.io/k8s-skaffold/skaffold:test",
},
},
input: `apiVersion: v1
kind: Pod
spec:
containers:
- image: gcr.io/k8s-skaffold/skaffold
name: skaffold
`,
expectedOut: `apiVersion: v1
kind: Pod
metadata:
namespace: default
spec:
containers:
- image: gcr.io/k8s-skaffold/skaffold:test
name: skaffold
`,
},
{
description: "two artifacts",
builds: []build.Artifact{
{
ImageName: "gcr.io/project/image1",
Tag: "gcr.io/project/image1:tag1",
},
{
ImageName: "gcr.io/project/image2",
Tag: "gcr.io/project/image2:tag2",
},
},
input: `apiVersion: v1
kind: Pod
spec:
containers:
- image: gcr.io/project/image1
name: image1
- image: gcr.io/project/image2
name: image2
`,
expectedOut: `apiVersion: v1
kind: Pod
metadata:
namespace: default
spec:
containers:
- image: gcr.io/project/image1:tag1
name: image1
- image: gcr.io/project/image2:tag2
name: image2
`,
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
t.NewTempDir().
Write("deployment.yaml", test.input).
Chdir()

deployer := deploy.NewKubectlDeployer(&runcontext.RunContext{
WorkingDir: ".",
Cfg: latest.Pipeline{
Deploy: latest.DeployConfig{
DeployType: latest.DeployType{
KubectlDeploy: &latest.KubectlDeploy{
Manifests: []string{"deployment.yaml"},
},
},
},
},
})
var b bytes.Buffer
err := deployer.Render(context.Background(), &b, test.builds, "")
t.CheckErrorAndDeepEqual(false, err, test.expectedOut, b.String())
})
}
}
125 changes: 79 additions & 46 deletions pkg/skaffold/deploy/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ limitations under the License.
package deploy

import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"os"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -73,65 +76,29 @@ func (k *KubectlDeployer) Labels() map[string]string {
// Deploy templates the provided manifests with a simple `find and replace` and
// runs `kubectl apply` on those manifests
func (k *KubectlDeployer) Deploy(ctx context.Context, out io.Writer, builds []build.Artifact, labellers []Labeller) *Result {
if err := k.kubectl.CheckVersion(ctx); err != nil {
color.Default.Fprintln(out, "kubectl client version:", k.kubectl.Version(ctx))
color.Default.Fprintln(out, err)
}
event.DeployInProgress()
manifests, err := k.renderManifests(ctx, out, builds)

manifests, err := k.readManifests(ctx)
if err != nil {
event.DeployFailed(err)
return NewDeployErrorResult(errors.Wrap(err, "reading manifests"))
return NewDeployErrorResult(err)
}

for _, m := range k.RemoteManifests {
manifest, err := k.readRemoteManifest(ctx, m)
if err != nil {
return NewDeployErrorResult(errors.Wrap(err, "get remote manifests"))
}

manifests = append(manifests, manifest)
}

if len(k.originalImages) == 0 {
k.originalImages, err = manifests.GetImages()
if err != nil {
return NewDeployErrorResult(errors.Wrap(err, "get images from manifests"))
}
}

logrus.Debugln("manifests", manifests.String())

if len(manifests) == 0 {
event.DeployComplete()
return NewDeploySuccessResult(nil)
}

event.DeployInProgress()

namespaces, err := manifests.CollectNamespaces()
if err != nil {
event.DeployInfoEvent(errors.Wrap(err, "could not fetch deployed resource namespace. "+
"This might cause port-forward and deploy health-check to fail."))
}

manifests, err = manifests.ReplaceImages(builds, k.defaultRepo)
if err != nil {
event.DeployFailed(err)
return NewDeployErrorResult(errors.Wrap(err, "replacing images in manifests"))
}

manifests, err = manifests.SetLabels(merge(labellers...))
if err != nil {
event.DeployFailed(err)
return NewDeployErrorResult(errors.Wrap(err, "setting labels in manifests"))
}

for _, transform := range manifestTransforms {
manifests, err = transform(manifests, builds, k.insecureRegistries)
if err != nil {
event.DeployFailed(err)
return NewDeployErrorResult(errors.Wrap(err, "unable to transform manifests"))
}
namespaces, err := manifests.CollectNamespaces()
if err != nil {
event.DeployInfoEvent(errors.Wrap(err, "could not fetch deployed resource namespace. "+
"This might cause port-forward and deploy health-check to fail."))
}

if err := k.kubectl.Apply(ctx, textio.NewPrefixWriter(out, " - "), manifests); err != nil {
Expand Down Expand Up @@ -252,6 +219,72 @@ func (k *KubectlDeployer) readRemoteManifest(ctx context.Context, name string) (
return manifest.Bytes(), nil
}

func (k *KubectlDeployer) Render(context.Context, io.Writer, []build.Artifact, string) error {
return errors.New("not yet implemented")
func (k *KubectlDeployer) Render(ctx context.Context, out io.Writer, builds []build.Artifact, filepath string) error {
manifests, err := k.renderManifests(ctx, out, builds)

if err != nil {
return err
}

manifestOut := out
if filepath != "" {
f, err := os.Open(filepath)
if err != nil {
return errors.Wrap(err, "opening file for writing manifests")
}
manifestOut = bufio.NewWriter(f)
}

for _, m := range manifests {
if _, err := fmt.Fprintln(manifestOut, string(m)); err != nil {
return errors.Wrap(err, "writing manifests")
}
}
return nil
}

func (k *KubectlDeployer) renderManifests(ctx context.Context, out io.Writer, builds []build.Artifact) (deploy.ManifestList, error) {
if err := k.kubectl.CheckVersion(ctx); err != nil {
color.Default.Fprintln(out, "kubectl client version:", k.kubectl.Version(ctx))
color.Default.Fprintln(out, err)
}

manifests, err := k.readManifests(ctx)
if err != nil {
return nil, errors.Wrap(err, "reading manifests")
}

for _, m := range k.RemoteManifests {
manifest, err := k.readRemoteManifest(ctx, m)
if err != nil {
return nil, errors.Wrap(err, "get remote manifests")
}

manifests = append(manifests, manifest)
}

if len(k.originalImages) == 0 {
k.originalImages, err = manifests.GetImages()
if err != nil {
return nil, errors.Wrap(err, "get images from manifests")
}
}

if len(manifests) == 0 {
return nil, nil
}

manifests, err = manifests.ReplaceImages(builds, k.defaultRepo)
if err != nil {
return nil, errors.Wrap(err, "replacing images in manifests")
}

for _, transform := range manifestTransforms {
manifests, err = transform(manifests, builds, k.insecureRegistries)
if err != nil {
return nil, errors.Wrap(err, "unable to transform manifests")
}
}

return manifests, nil
}
1 change: 0 additions & 1 deletion pkg/skaffold/deploy/kubectl/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ func (c *CLI) ReadManifests(ctx context.Context, manifests []string) (ManifestLi

var manifestList ManifestList
manifestList.Append(buf)
logrus.Debugln("manifests", manifestList.String())

return manifestList, nil
}
Expand Down
55 changes: 49 additions & 6 deletions pkg/skaffold/deploy/kubectl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package deploy

import (
"bytes"
"context"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -461,28 +462,70 @@ func TestDependencies(t *testing.T) {
func TestKubectlRender(t *testing.T) {
tests := []struct {
description string
shouldErr bool
builds []build.Artifact
input string
}{
{
description: "calling render returns error",
shouldErr: true,
description: "normal render",
builds: []build.Artifact{
{
ImageName: "gcr.io/k8s-skaffold/skaffold",
Tag: "gcr.io/k8s-skaffold/skaffold:test",
},
},
input: `apiVersion: v1
kind: Pod
spec:
containers:
- image: gcr.io/k8s-skaffold/skaffold
name: skaffold
`,
},
{
description: "two artifacts",
builds: []build.Artifact{
{
ImageName: "gcr.io/project/image1",
Tag: "gcr.io/project/image1:tag1",
},
{
ImageName: "gcr.io/project/image2",
Tag: "gcr.io/project/image2:tag2",
},
},
input: `apiVersion: v1
kind: Pod
spec:
containers:
- image: gcr.io/project/image1
name: image1
- image: gcr.io/project/image2
name: image2
`,
},
}
for _, test := range tests {
testutil.Run(t, test.description, func(t *testutil.T) {
t.Override(&util.DefaultExecCommand, testutil.
CmdRunOut("kubectl version --client -ojson", kubectlVersion).
AndRunOut("kubectl --context kubecontext create --dry-run -oyaml -f deployment.yaml", test.input))

deployer := NewKubectlDeployer(&runcontext.RunContext{
WorkingDir: ".",
Cfg: latest.Pipeline{
Deploy: latest.DeployConfig{
DeployType: latest.DeployType{
KubectlDeploy: &latest.KubectlDeploy{
Manifests: []string{},
Manifests: []string{"deployment.yaml"},
},
},
},
},
KubeContext: testKubeContext,
})
actual := deployer.Render(context.Background(), ioutil.Discard, []build.Artifact{}, "tmp/dir")
t.CheckError(test.shouldErr, actual)
var b bytes.Buffer
err := deployer.Render(context.Background(), &b, test.builds, "")
t.CheckError(false, err)
})
}
}

0 comments on commit e31af85

Please sign in to comment.