From 0cd091ce73aeda5200352e8bda9a9a23979373e8 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Wed, 13 Mar 2019 15:13:41 +0100 Subject: [PATCH 01/14] Those tests rely on a remote service Signed-off-by: David Gageot --- integration/run_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/integration/run_test.go b/integration/run_test.go index 6ac40309124..10c9a7bc05d 100644 --- a/integration/run_test.go +++ b/integration/run_test.go @@ -98,6 +98,7 @@ func TestRun(t *testing.T) { description: "docker plugin in gcb exec environment", dir: "testdata/plugin/gcb", deployments: []string{"leeroy-app", "leeroy-web"}, + remoteOnly: true, }, { description: "bazel plugin in local exec environment", dir: "testdata/plugin/local/bazel", @@ -111,6 +112,7 @@ func TestRun(t *testing.T) { dir: "examples/jib", args: []string{"-p", "gcb"}, deployments: []string{"web"}, + remoteOnly: true, }, } From e187ea31861081ffcb2b4de7953bc2d670327e64 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Wed, 13 Mar 2019 13:00:06 +0100 Subject: [PATCH 02/14] Add more logs in integration tests Signed-off-by: David Gageot --- integration/skaffold/helper.go | 18 +++++++++++++++++- integration/util.go | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/integration/skaffold/helper.go b/integration/skaffold/helper.go index 904d0e31840..c1070cd194c 100644 --- a/integration/skaffold/helper.go +++ b/integration/skaffold/helper.go @@ -23,6 +23,9 @@ import ( "os/exec" "strings" "testing" + "time" + + "github.com/sirupsen/logrus" ) // RunBuilder is used to build a command line to run `skaffold`. @@ -120,6 +123,11 @@ func (b *RunBuilder) RunBackground(t *testing.T) context.CancelFunc { t.Fatalf("skaffold %s: %v", b.command, err) } + go func() { + cmd.Wait() + logrus.Infoln("Ran in", time.Since(start)) + }() + return func() { cancel() cmd.Wait() @@ -129,7 +137,15 @@ func (b *RunBuilder) RunBackground(t *testing.T) context.CancelFunc { // Run runs the skaffold command and returns its output. func (b *RunBuilder) Run(t *testing.T) ([]byte, error) { t.Helper() - return b.cmd(context.Background()).Output() + + cmd := b.cmd(context.Background()) + logrus.Infoln(cmd.Args) + + start := time.Now() + out, err := cmd.Output() + logrus.Infoln("Ran in", time.Since(start)) + + return out, err } // RunOrFail runs the skaffold command and fails the test diff --git a/integration/util.go b/integration/util.go index 7a318b68eb3..dcd10e0d314 100644 --- a/integration/util.go +++ b/integration/util.go @@ -18,12 +18,12 @@ package integration import ( "context" - "fmt" "os/exec" "testing" "time" kubernetesutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" + "github.com/sirupsen/logrus" apps_v1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -54,7 +54,7 @@ func SetupNamespace(t *testing.T) (*v1.Namespace, *NSKubernetesClient, func()) { t.Fatalf("creating namespace: %s", err) } - fmt.Println("Namespace:", ns.Name) + logrus.Infoln("Namespace:", ns.Name) nsClient := &NSKubernetesClient{ t: t, From 458bd8aab70e4c5642235aa66d09930ca0fe31df Mon Sep 17 00:00:00 2001 From: David Gageot Date: Wed, 13 Mar 2019 14:25:41 +0100 Subject: [PATCH 03/14] Watch for pods to be ready and deployments to stabilize Signed-off-by: David Gageot --- integration/util.go | 92 +++++++++++++++--- pkg/skaffold/kubernetes/wait.go | 29 ------ pkg/skaffold/kubernetes/wait_test.go | 133 --------------------------- 3 files changed, 80 insertions(+), 174 deletions(-) delete mode 100644 pkg/skaffold/kubernetes/wait_test.go diff --git a/integration/util.go b/integration/util.go index dcd10e0d314..9a8adedaf58 100644 --- a/integration/util.go +++ b/integration/util.go @@ -24,7 +24,7 @@ import ( kubernetesutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/kubernetes" "github.com/sirupsen/logrus" - apps_v1 "k8s.io/api/apps/v1" + appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -76,24 +76,47 @@ type NSKubernetesClient struct { // WaitForPodsReady waits for a list of pods to become ready. func (k *NSKubernetesClient) WaitForPodsReady(podNames ...string) { - for _, podName := range podNames { - if err := kubernetesutil.WaitForPodReady(context.Background(), k.client.CoreV1().Pods(k.ns), podName); err != nil { - k.t.Fatalf("Timed out waiting for pod %s ready in namespace %s", podName, k.ns) - } + if len(podNames) == 0 { + return } -} -// WaitForDeploymentsToStabilize waits for a list of deployments to become stable. -func (k *NSKubernetesClient) WaitForDeploymentsToStabilize(depNames ...string) { - for _, depName := range depNames { - if err := kubernetesutil.WaitForDeploymentToStabilize(context.Background(), k.client, k.ns, depName, 10*time.Minute); err != nil { - k.t.Fatalf("Timed out waiting for deployment %s to stabilize in namespace %s", depName, k.ns) + ctx, cancelTimeout := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelTimeout() + + w, err := k.client.CoreV1().Pods(k.ns).Watch(meta_v1.ListOptions{}) + if err != nil { + k.t.Fatalf("Unable to watch pods: %v", err) + } + defer w.Stop() + + phases := map[string]v1.PodPhase{} + + for { + waitLoop: + select { + case <-ctx.Done(): + k.t.Fatalf("Timed out waiting for pods %v ready in namespace %s", podNames, k.ns) + + case event := <-w.ResultChan(): + pod := event.Object.(*v1.Pod) + logrus.Infoln("Pod", pod.Name, "is", pod.Status.Phase) + + phases[pod.Name] = pod.Status.Phase + + for _, podName := range podNames { + if phases[podName] != v1.PodRunning { + break waitLoop + } + } + + logrus.Infoln("Pods", podNames, "ready") + return } } } // GetDeployment gets a deployment by name. -func (k *NSKubernetesClient) GetDeployment(depName string) *apps_v1.Deployment { +func (k *NSKubernetesClient) GetDeployment(depName string) *appsv1.Deployment { k.WaitForDeploymentsToStabilize(depName) dep, err := k.client.AppsV1().Deployments(k.ns).Get(depName, meta_v1.GetOptions{}) @@ -102,3 +125,48 @@ func (k *NSKubernetesClient) GetDeployment(depName string) *apps_v1.Deployment { } return dep } + +// WaitForDeploymentsToStabilize waits for a list of deployments to become stable. +func (k *NSKubernetesClient) WaitForDeploymentsToStabilize(depNames ...string) { + if len(depNames) == 0 { + return + } + + ctx, cancelTimeout := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelTimeout() + + w, err := k.client.AppsV1().Deployments(k.ns).Watch(meta_v1.ListOptions{}) + if err != nil { + k.t.Fatalf("Unable to watch deployments: %v", err) + } + defer w.Stop() + + deployments := map[string]*appsv1.Deployment{} + + for { + waitLoop: + select { + case <-ctx.Done(): + k.t.Fatalf("Timed out waiting for deployments %v to stabilize in namespace %s", depNames, k.ns) + + case event := <-w.ResultChan(): + dp := event.Object.(*appsv1.Deployment) + logrus.Infof("Deployment %s: Generation %d/%d, Replicas %d/%d", dp.Name, dp.Status.ObservedGeneration, dp.Generation, dp.Status.Replicas, *(dp.Spec.Replicas)) + + deployments[dp.Name] = dp + + for _, depName := range depNames { + if d, present := deployments[depName]; !present || !isStable(d) { + break waitLoop + } + } + + logrus.Infoln("Deployments", depNames, "are stable") + return + } + } +} + +func isStable(dp *appsv1.Deployment) bool { + return dp.Generation <= dp.Status.ObservedGeneration && *(dp.Spec.Replicas) == dp.Status.Replicas +} diff --git a/pkg/skaffold/kubernetes/wait.go b/pkg/skaffold/kubernetes/wait.go index 9db7c0588ff..c0f269ef0a9 100644 --- a/pkg/skaffold/kubernetes/wait.go +++ b/pkg/skaffold/kubernetes/wait.go @@ -53,35 +53,6 @@ func WaitForPodScheduled(ctx context.Context, pods corev1.PodInterface, podName }, ctx.Done()) } -func WaitForPodReady(ctx context.Context, pods corev1.PodInterface, podName string) error { - if err := WaitForPodScheduled(ctx, pods, podName); err != nil { - return err - } - - logrus.Infof("Waiting for %s to be ready", podName) - - ctx, cancelTimeout := context.WithTimeout(ctx, 10*time.Minute) - defer cancelTimeout() - - return wait.PollImmediateUntil(time.Millisecond*500, func() (bool, error) { - pod, err := pods.Get(podName, meta_v1.GetOptions{ - IncludeUninitialized: true, - }) - if err != nil { - return false, fmt.Errorf("not found: %s", podName) - } - switch pod.Status.Phase { - case v1.PodRunning: - return true, nil - case v1.PodSucceeded, v1.PodFailed: - return false, fmt.Errorf("pod already in terminal phase: %s", pod.Status.Phase) - case v1.PodUnknown, v1.PodPending: - return false, nil - } - return false, fmt.Errorf("unknown phase: %s", pod.Status.Phase) - }, ctx.Done()) -} - func WaitForPodComplete(ctx context.Context, pods corev1.PodInterface, podName string, timeout time.Duration) error { logrus.Infof("Waiting for %s to be ready", podName) diff --git a/pkg/skaffold/kubernetes/wait_test.go b/pkg/skaffold/kubernetes/wait_test.go deleted file mode 100644 index b74a2afbea8..00000000000 --- a/pkg/skaffold/kubernetes/wait_test.go +++ /dev/null @@ -1,133 +0,0 @@ -/* -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 kubernetes - -import ( - "context" - "testing" - "time" - - "github.com/GoogleContainerTools/skaffold/testutil" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/fake" -) - -var podReadyState = &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "podname", - }, - Status: v1.PodStatus{ - Phase: v1.PodRunning, - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "container_name", - Image: "image_name", - }, - }, - }, -} - -var podUnitialized = &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "podname", - }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ - { - Type: v1.PodScheduled, - }, - }, - Phase: v1.PodPending, - }, -} - -var podBadPhase = &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "podname", - }, - Status: v1.PodStatus{ - Conditions: []v1.PodCondition{ - { - Type: v1.PodScheduled, - }, - }, - Phase: "not a real phase", - }, - Spec: v1.PodSpec{ - Containers: []v1.Container{ - { - Name: "container_name", - Image: "image_name", - }, - }, - }, -} - -func TestWaitForPodReady(t *testing.T) { - var tests = []struct { - description string - initialObj *v1.Pod - phases []v1.PodPhase - timeout time.Duration - - shouldErr bool - }{ - { - description: "pod already ready", - initialObj: podReadyState, - }, - { - description: "pod uninitialized to succeed without running", - initialObj: podUnitialized, - phases: []v1.PodPhase{v1.PodUnknown, v1.PodSucceeded}, - shouldErr: true, - }, - { - description: "pod bad phase", - initialObj: podBadPhase, - shouldErr: true, - }, - } - for _, test := range tests { - t.Run(test.description, func(t *testing.T) { - client := fake.NewSimpleClientset(test.initialObj) - pods := client.CoreV1().Pods("") - errCh := make(chan error, 1) - done := make(chan struct{}, 1) - go func() { - errCh <- WaitForPodReady(context.Background(), pods, "podname") - done <- struct{}{} - }() - for _, p := range test.phases { - time.Sleep(501 * time.Millisecond) - test.initialObj.Status.Phase = p - pods.UpdateStatus(test.initialObj) - } - <-done - var err error - select { - case waitErr := <-errCh: - err = waitErr - default: - } - testutil.CheckError(t, test.shouldErr, err) - }) - } -} From d259c9b34d6e3afcbeeb065aeedf3fe05768f7d5 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Wed, 13 Mar 2019 22:40:22 +0100 Subject: [PATCH 04/14] Avoid a test hanging forever Signed-off-by: David Gageot --- integration/skaffold/helper.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/integration/skaffold/helper.go b/integration/skaffold/helper.go index c1070cd194c..e55c77b6ab4 100644 --- a/integration/skaffold/helper.go +++ b/integration/skaffold/helper.go @@ -19,6 +19,7 @@ package skaffold import ( "bytes" "context" + "io" "os" "os/exec" "strings" @@ -113,12 +114,25 @@ func (b *RunBuilder) WithEnv(env []string) *RunBuilder { // This also returns a teardown function that stops skaffold. func (b *RunBuilder) RunBackground(t *testing.T) context.CancelFunc { t.Helper() - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(context.Background()) cmd := b.cmd(ctx) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + // If the test is killed by a timeout, go test will wait for + // os.Stderr and os.Stdout to close as a result. + // + // However, the `cmd` will stil run in the background + // and hold those descriptors open. + // As a result, go test will hang forever. + // + // Avoid that by wrapping stderr and stdout, breaking the short + // circuit and forcing cmd.Run to use another pipe and goroutine + // to pass along stderr and stdout. + // See https://github.com/golang/go/issues/23019 + cmd.Stdout = struct{ io.Writer }{os.Stdout} + cmd.Stderr = struct{ io.Writer }{os.Stderr} + + start := time.Now() if err := cmd.Start(); err != nil { t.Fatalf("skaffold %s: %v", b.command, err) } From 88b4e68a6dda8f89a284c4bb2fd4247dc0a466ad Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 07:33:56 +0100 Subject: [PATCH 05/14] Print k8s pods if a poller times out Signed-off-by: David Gageot --- integration/util.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/integration/util.go b/integration/util.go index 9a8adedaf58..3ca378a3093 100644 --- a/integration/util.go +++ b/integration/util.go @@ -18,6 +18,7 @@ package integration import ( "context" + "fmt" "os/exec" "testing" "time" @@ -95,6 +96,7 @@ func (k *NSKubernetesClient) WaitForPodsReady(podNames ...string) { waitLoop: select { case <-ctx.Done(): + k.debug("pods") k.t.Fatalf("Timed out waiting for pods %v ready in namespace %s", podNames, k.ns) case event := <-w.ResultChan(): @@ -147,6 +149,8 @@ func (k *NSKubernetesClient) WaitForDeploymentsToStabilize(depNames ...string) { waitLoop: select { case <-ctx.Done(): + k.debug("deployments.apps") + k.debug("pods") k.t.Fatalf("Timed out waiting for deployments %v to stabilize in namespace %s", depNames, k.ns) case event := <-w.ResultChan(): @@ -167,6 +171,16 @@ func (k *NSKubernetesClient) WaitForDeploymentsToStabilize(depNames ...string) { } } +// debug is used to print all the details about pods or deployments +func (k *NSKubernetesClient) debug(entities string) { + cmd := exec.Command("kubectl", "-n", k.ns, "get", entities, "-oyaml") + out, _ := cmd.CombinedOutput() + + logrus.Warnln(cmd.Args) + // Use fmt.Println, not logrus, for prettier output + fmt.Println(string(out)) +} + func isStable(dp *appsv1.Deployment) bool { return dp.Generation <= dp.Status.ObservedGeneration && *(dp.Spec.Replicas) == dp.Status.Replicas } From e89b7db5ddd0910ed560c73e72021e2b0ce15953 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 10:33:54 +0100 Subject: [PATCH 06/14] Use the same code/config as other samples This makes it faster to build on the CI Signed-off-by: David Gageot --- examples/compose/main.go | 1 + examples/kaniko-local/Dockerfile | 9 +++++---- examples/kaniko-local/main.go | 1 + examples/kaniko/Dockerfile | 9 +++++---- examples/kaniko/main.go | 1 + examples/tagging-with-environment-variables/Dockerfile | 8 +++++--- examples/tagging-with-environment-variables/k8s-pod.yaml | 1 - examples/tagging-with-environment-variables/main.go | 1 + integration/examples/compose/main.go | 1 + integration/examples/kaniko-local/Dockerfile | 9 +++++---- integration/examples/kaniko-local/main.go | 1 + integration/examples/kaniko/Dockerfile | 9 +++++---- integration/examples/kaniko/main.go | 1 + .../tagging-with-environment-variables/Dockerfile | 8 +++++--- .../tagging-with-environment-variables/k8s-pod.yaml | 1 - .../examples/tagging-with-environment-variables/main.go | 1 + integration/testdata/fix/Dockerfile | 9 +++++---- integration/testdata/fix/main.go | 1 + integration/testdata/init/compose/main.go | 1 + integration/testdata/kaniko-sub-folder/sub/Dockerfile | 9 +++++---- integration/testdata/kaniko-sub-folder/sub/main.go | 1 + 21 files changed, 51 insertions(+), 32 deletions(-) diff --git a/examples/compose/main.go b/examples/compose/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/examples/compose/main.go +++ b/examples/compose/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/examples/kaniko-local/Dockerfile b/examples/kaniko-local/Dockerfile index 2d107918ad0..184d6cce3e3 100644 --- a/examples/kaniko-local/Dockerfile +++ b/examples/kaniko-local/Dockerfile @@ -1,6 +1,7 @@ -FROM gcr.io/google-appengine/golang +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleCloudPlatform/skaffold +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/examples/kaniko-local/main.go b/examples/kaniko-local/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/examples/kaniko-local/main.go +++ b/examples/kaniko-local/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/examples/kaniko/Dockerfile b/examples/kaniko/Dockerfile index 2d107918ad0..184d6cce3e3 100644 --- a/examples/kaniko/Dockerfile +++ b/examples/kaniko/Dockerfile @@ -1,6 +1,7 @@ -FROM gcr.io/google-appengine/golang +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleCloudPlatform/skaffold +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/examples/kaniko/main.go b/examples/kaniko/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/examples/kaniko/main.go +++ b/examples/kaniko/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/examples/tagging-with-environment-variables/Dockerfile b/examples/tagging-with-environment-variables/Dockerfile index bf21da631a5..184d6cce3e3 100644 --- a/examples/tagging-with-environment-variables/Dockerfile +++ b/examples/tagging-with-environment-variables/Dockerfile @@ -1,5 +1,7 @@ -FROM golang:1.10.1-alpine3.7 +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/examples/tagging-with-environment-variables/k8s-pod.yaml b/examples/tagging-with-environment-variables/k8s-pod.yaml index 846600e0a43..14cc6911607 100644 --- a/examples/tagging-with-environment-variables/k8s-pod.yaml +++ b/examples/tagging-with-environment-variables/k8s-pod.yaml @@ -6,4 +6,3 @@ spec: containers: - name: getting-started image: gcr.io/k8s-skaffold/skaffold-example - imagePullPolicy: IfNotPresent diff --git a/examples/tagging-with-environment-variables/main.go b/examples/tagging-with-environment-variables/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/examples/tagging-with-environment-variables/main.go +++ b/examples/tagging-with-environment-variables/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/examples/compose/main.go b/integration/examples/compose/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/examples/compose/main.go +++ b/integration/examples/compose/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/examples/kaniko-local/Dockerfile b/integration/examples/kaniko-local/Dockerfile index 2d107918ad0..184d6cce3e3 100644 --- a/integration/examples/kaniko-local/Dockerfile +++ b/integration/examples/kaniko-local/Dockerfile @@ -1,6 +1,7 @@ -FROM gcr.io/google-appengine/golang +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleCloudPlatform/skaffold +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/integration/examples/kaniko-local/main.go b/integration/examples/kaniko-local/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/examples/kaniko-local/main.go +++ b/integration/examples/kaniko-local/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/examples/kaniko/Dockerfile b/integration/examples/kaniko/Dockerfile index 2d107918ad0..184d6cce3e3 100644 --- a/integration/examples/kaniko/Dockerfile +++ b/integration/examples/kaniko/Dockerfile @@ -1,6 +1,7 @@ -FROM gcr.io/google-appengine/golang +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleCloudPlatform/skaffold +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/integration/examples/kaniko/main.go b/integration/examples/kaniko/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/examples/kaniko/main.go +++ b/integration/examples/kaniko/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/examples/tagging-with-environment-variables/Dockerfile b/integration/examples/tagging-with-environment-variables/Dockerfile index bf21da631a5..184d6cce3e3 100644 --- a/integration/examples/tagging-with-environment-variables/Dockerfile +++ b/integration/examples/tagging-with-environment-variables/Dockerfile @@ -1,5 +1,7 @@ -FROM golang:1.10.1-alpine3.7 +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/integration/examples/tagging-with-environment-variables/k8s-pod.yaml b/integration/examples/tagging-with-environment-variables/k8s-pod.yaml index 846600e0a43..14cc6911607 100644 --- a/integration/examples/tagging-with-environment-variables/k8s-pod.yaml +++ b/integration/examples/tagging-with-environment-variables/k8s-pod.yaml @@ -6,4 +6,3 @@ spec: containers: - name: getting-started image: gcr.io/k8s-skaffold/skaffold-example - imagePullPolicy: IfNotPresent diff --git a/integration/examples/tagging-with-environment-variables/main.go b/integration/examples/tagging-with-environment-variables/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/examples/tagging-with-environment-variables/main.go +++ b/integration/examples/tagging-with-environment-variables/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/testdata/fix/Dockerfile b/integration/testdata/fix/Dockerfile index 368cfde2af7..184d6cce3e3 100644 --- a/integration/testdata/fix/Dockerfile +++ b/integration/testdata/fix/Dockerfile @@ -1,6 +1,7 @@ -FROM golang:1.10.1-alpine3.7 +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleContainerTools/skaffold/examples/getting-started +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/integration/testdata/fix/main.go b/integration/testdata/fix/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/testdata/fix/main.go +++ b/integration/testdata/fix/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/testdata/init/compose/main.go b/integration/testdata/init/compose/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/testdata/init/compose/main.go +++ b/integration/testdata/init/compose/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } diff --git a/integration/testdata/kaniko-sub-folder/sub/Dockerfile b/integration/testdata/kaniko-sub-folder/sub/Dockerfile index 2d107918ad0..184d6cce3e3 100644 --- a/integration/testdata/kaniko-sub-folder/sub/Dockerfile +++ b/integration/testdata/kaniko-sub-folder/sub/Dockerfile @@ -1,6 +1,7 @@ -FROM gcr.io/google-appengine/golang +FROM golang:1.10.1-alpine3.7 as builder +COPY main.go . +RUN go build -o /app main.go -WORKDIR /go/src/github.com/GoogleCloudPlatform/skaffold +FROM alpine:3.7 CMD ["./app"] -COPY main.go . -RUN go build -o app main.go +COPY --from=builder /app . diff --git a/integration/testdata/kaniko-sub-folder/sub/main.go b/integration/testdata/kaniko-sub-folder/sub/main.go index 64b7bdfc4a1..593721cfe2e 100644 --- a/integration/testdata/kaniko-sub-folder/sub/main.go +++ b/integration/testdata/kaniko-sub-folder/sub/main.go @@ -8,6 +8,7 @@ import ( func main() { for { fmt.Println("Hello world!") + time.Sleep(time.Second * 1) } } From 73e417e2a5897cc27a3909aef93f3af5a3c06bee Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 10:55:31 +0100 Subject: [PATCH 07/14] Use smaller image Signed-off-by: David Gageot --- integration/testdata/dev/Dockerfile | 2 +- integration/testdata/file-sync/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/testdata/dev/Dockerfile b/integration/testdata/dev/Dockerfile index 16a8be7008c..0b2d2005730 100644 --- a/integration/testdata/dev/Dockerfile +++ b/integration/testdata/dev/Dockerfile @@ -1,3 +1,3 @@ -FROM golang:1.10.1-alpine3.7 as builder +FROM busybox COPY foo /foo CMD while true; do cat /foo; sleep 1; done diff --git a/integration/testdata/file-sync/Dockerfile b/integration/testdata/file-sync/Dockerfile index 98832659bc6..18553b971df 100644 --- a/integration/testdata/file-sync/Dockerfile +++ b/integration/testdata/file-sync/Dockerfile @@ -1,3 +1,3 @@ -FROM alpine +FROM busybox COPY . . CMD while true; do cat /foo && sleep 5; done From ee4959f614dfee48d5c126815ec6030ed6be4460 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 10:43:27 +0100 Subject: [PATCH 08/14] Remove unnecessary context Signed-off-by: David Gageot --- examples/bazel/skaffold.yaml | 1 - integration/examples/bazel/skaffold.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/bazel/skaffold.yaml b/examples/bazel/skaffold.yaml index cfef50a408c..8f3032e9bd1 100644 --- a/examples/bazel/skaffold.yaml +++ b/examples/bazel/skaffold.yaml @@ -3,6 +3,5 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-bazel - context: . bazel: target: //:skaffold_example.tar diff --git a/integration/examples/bazel/skaffold.yaml b/integration/examples/bazel/skaffold.yaml index d737916ec4c..217fea10394 100644 --- a/integration/examples/bazel/skaffold.yaml +++ b/integration/examples/bazel/skaffold.yaml @@ -3,6 +3,5 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-bazel - context: . bazel: target: //:skaffold_example.tar From 7ac21c4f9380fd7477eaf39cc69b2f435b567b42 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 10:47:57 +0100 Subject: [PATCH 09/14] Add missing annotated-skaffold.yaml Signed-off-by: David Gageot --- integration/examples/annotated-skaffold.yaml | 1 + 1 file changed, 1 insertion(+) create mode 100644 integration/examples/annotated-skaffold.yaml diff --git a/integration/examples/annotated-skaffold.yaml b/integration/examples/annotated-skaffold.yaml new file mode 100644 index 00000000000..365c9b681e5 --- /dev/null +++ b/integration/examples/annotated-skaffold.yaml @@ -0,0 +1 @@ +# This documentation has been moved to https://skaffold.dev/docs/references/yaml/ \ No newline at end of file From 85b3c9c9f9d951cf50e73e49058183b9e6d9ad08 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 10:49:30 +0100 Subject: [PATCH 10/14] Improve the README for examples Signed-off-by: David Gageot --- examples/README.md | 10 ++++++---- integration/examples/README.md | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/README.md b/examples/README.md index d634a864786..925e4ee6de8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,14 +1,16 @@ # Examples -To run the examples, you either have to manually replace the image repositories in the examples from gcr.io/k8s-skaffold to yours or you can point skaffold to your default image repository in one of the four ways: +To run the examples, you either have to manually replace the image repositories in the examples from `gcr.io/k8s-skaffold` +to yours or you can point Skaffold to your default image repository in one of the four ways: * flag: `skaffold dev --default-repo ` * env var: `SKAFFOLD_DEFAULT_REPO= skaffold dev` * global skaffold config (one time): `skaffold config set --global default-repo ` * skaffold config for current kubectl context: `skaffold config set default-repo ` -These examples are made to work with the latest release of skaffold. +These examples are made to work with the latest release of Skaffold. -If you are running skaffold at HEAD or have built it from source, please use the examples at integration/examples. +If you are running Skaffold at HEAD or have built it from source, please use the examples at `integration/examples`. -*Note for contributors*: If you wish to make changes to these examples, please edit the ones at integration/examples, as those will be synced on release. +*Note for contributors*: If you wish to make changes to these examples, please edit the ones at `integration/examples`, +as those will be synced on release. diff --git a/integration/examples/README.md b/integration/examples/README.md index d634a864786..925e4ee6de8 100644 --- a/integration/examples/README.md +++ b/integration/examples/README.md @@ -1,14 +1,16 @@ # Examples -To run the examples, you either have to manually replace the image repositories in the examples from gcr.io/k8s-skaffold to yours or you can point skaffold to your default image repository in one of the four ways: +To run the examples, you either have to manually replace the image repositories in the examples from `gcr.io/k8s-skaffold` +to yours or you can point Skaffold to your default image repository in one of the four ways: * flag: `skaffold dev --default-repo ` * env var: `SKAFFOLD_DEFAULT_REPO= skaffold dev` * global skaffold config (one time): `skaffold config set --global default-repo ` * skaffold config for current kubectl context: `skaffold config set default-repo ` -These examples are made to work with the latest release of skaffold. +These examples are made to work with the latest release of Skaffold. -If you are running skaffold at HEAD or have built it from source, please use the examples at integration/examples. +If you are running Skaffold at HEAD or have built it from source, please use the examples at `integration/examples`. -*Note for contributors*: If you wish to make changes to these examples, please edit the ones at integration/examples, as those will be synced on release. +*Note for contributors*: If you wish to make changes to these examples, please edit the ones at `integration/examples`, +as those will be synced on release. From cffc32d96db138a7d3a485201e4bd529d5144335 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 11:16:52 +0100 Subject: [PATCH 11/14] =?UTF-8?q?Let=E2=80=99s=20make=20Travis=20build=202?= =?UTF-8?q?5s=20faster?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Gageot --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index e4411dfac54..37f6458f0e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,21 @@ language: go + os: - linux - osx + +git: + submodules: false + go: - "1.11.x" - "1.12.x" + go_import_path: github.com/GoogleContainerTools/skaffold before_script: - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config + script: - make out/skaffold test From 6291a916f01d9e521ed6c37110908c40f00b7698 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 11:21:21 +0100 Subject: [PATCH 12/14] Shorter test output on AppVeyor Signed-off-by: David Gageot --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6281dd91a83..a042016ab1a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,4 +5,4 @@ environment: build_script: - go build -o out/skaffold.exe cmd/skaffold/skaffold.go test_script: - - go test -short -v -timeout 60s ./... \ No newline at end of file + - go test -short -timeout 60s ./... \ No newline at end of file From a12895aec0c94b156bd28289b89a0107d4fcfdfc Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 11:22:36 +0100 Subject: [PATCH 13/14] Use Go 1.11 on AppVeyor and Kokoro too Also update the development guide Signed-off-by: David Gageot --- DEVELOPMENT.md | 2 +- appveyor.yml | 2 +- deploy/skaffold/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fbf81621bc0..b4ec50f04f1 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -9,7 +9,7 @@ This doc explains the development workflow so you can get started You must install these tools: 1. [`go`](https://golang.org/doc/install): The language skaffold is - built in + built in (version >= go 1.11) 1. [`git`](https://help.github.com/articles/set-up-git/): For source control 1. [`dep`](https://github.com/golang/dep): For managing external Go dependencies. - Please Install dep v0.5.0 or greater. diff --git a/appveyor.yml b/appveyor.yml index a042016ab1a..2d049788d87 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ clone_folder: c:\gopath\src\github.com\GoogleContainerTools\skaffold -stack: go 1.10 +stack: go 1.11 environment: GOPATH: c:\gopath build_script: diff --git a/deploy/skaffold/Dockerfile b/deploy/skaffold/Dockerfile index b7f446da658..f092ce1a5f1 100644 --- a/deploy/skaffold/Dockerfile +++ b/deploy/skaffold/Dockerfile @@ -85,7 +85,7 @@ RUN apt-get update && apt-get install --no-install-recommends --no-install-sugge apt-get -y install docker-ce=17.12.0~ce-0~ubuntu && \ rm -rf /var/lib/apt/lists/* -COPY --from=golang:1.10 /usr/local/go /usr/local/go +COPY --from=golang:1.11 /usr/local/go /usr/local/go ENV PATH /usr/local/go/bin:/go/bin:$PATH ENV GOPATH /go/ From 1a80a5320375c8a86b1073e40aca41a61138a12c Mon Sep 17 00:00:00 2001 From: David Gageot Date: Thu, 14 Mar 2019 11:41:30 +0100 Subject: [PATCH 14/14] Get timings for each Travis step Signed-off-by: David Gageot --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 37f6458f0e9..fde68542c4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,8 @@ before_script: - echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config script: - - make out/skaffold test + - make out/skaffold + - make test after_success: - bash <(curl -s https://codecov.io/bash)