Skip to content

Commit

Permalink
Merge pull request #2943 from nkubala/render-kubectl
Browse files Browse the repository at this point in the history
Implement 'skaffold render' for kubectl deployer
  • Loading branch information
nkubala authored Oct 2, 2019
2 parents a4bdbbc + 9331930 commit 08551a7
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 53 deletions.
168 changes: 168 additions & 0 deletions integration/render_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
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
`,
},
{
description: "two artifacts, combined manifests",
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
---
apiVersion: v1
kind: Pod
spec:
containers:
- 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
---
apiVersion: v1
kind: Pod
metadata:
namespace: default
spec:
containers:
- 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())
})
}
}
121 changes: 75 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,68 @@ 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)
}

fmt.Fprintln(manifestOut, manifests.String())
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
Loading

0 comments on commit 08551a7

Please sign in to comment.