github.com/GoogleContainerTools/skaffold/v2@v2.13.2/integration/deploy_cloudrun_test.go (about)

     1  /*
     2  Copyright 2022 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package integration
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/google/go-cmp/cmp"
    26  	"github.com/google/uuid"
    27  	"google.golang.org/api/option"
    28  	"google.golang.org/api/run/v1"
    29  
    30  	"github.com/GoogleContainerTools/skaffold/v2/integration/skaffold"
    31  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/gcp"
    32  	"github.com/GoogleContainerTools/skaffold/v2/pkg/skaffold/schema/latest"
    33  	"github.com/GoogleContainerTools/skaffold/v2/testutil"
    34  )
    35  
    36  func TestDeployCloudRun(t *testing.T) {
    37  	MarkIntegrationTest(t, NeedsGcp)
    38  	// Other integration tests run with the --default-repo option.
    39  	// This one explicitly specifies the full image name.
    40  	skaffold.Deploy().InDir("testdata/deploy-cloudrun").RunOrFail(t)
    41  	ctx := context.Background()
    42  	svc, err := getRunService(ctx, "k8s-skaffold", "us-central1", "skaffold-test")
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	if err = checkReady(svc); err != nil {
    47  		t.Fatal(err)
    48  	}
    49  }
    50  
    51  func TestDeployCloudRunWithHooks(t *testing.T) {
    52  	MarkIntegrationTest(t, NeedsGcp)
    53  
    54  	testutil.Run(t, "cloud run deploy with hooks", func(t *testutil.T) {
    55  		expectedOutput := []string{
    56  			"PRE-DEPLOY Cloud Run MODULE1 host hook",
    57  			"POST-DEPLOY Cloud Run MODULE1 host hook",
    58  			"PRE-DEPLOY Cloud Run MODULE2 host hook",
    59  			"POST-DEPLOY Cloud Run MODULE2 host hook",
    60  		}
    61  
    62  		out := skaffold.Run().InDir("testdata/deploy-cloudrun-with-hooks").RunOrFailOutput(t.T)
    63  
    64  		commandOutput := string(out)
    65  		previousFoundIndex := -1
    66  
    67  		for _, expectedOutput := range expectedOutput {
    68  			expectedOutputFoundIndex := strings.Index(commandOutput, expectedOutput)
    69  			isPreviousOutputBeforeThanCurrent := previousFoundIndex < expectedOutputFoundIndex
    70  			t.CheckTrue(isPreviousOutputBeforeThanCurrent)
    71  			previousFoundIndex = expectedOutputFoundIndex
    72  		}
    73  	})
    74  }
    75  
    76  func TestDeployJobWithMaxRetries(t *testing.T) {
    77  	MarkIntegrationTest(t, NeedsGcp)
    78  
    79  	tests := []struct {
    80  		descrition         string
    81  		jobManifest        string
    82  		skaffoldCfg        string
    83  		args               []string
    84  		expectedMaxRetries int64
    85  	}{
    86  		{
    87  			descrition:         "maxRetries set to specific value",
    88  			expectedMaxRetries: 2,
    89  			jobManifest: `
    90  apiVersion: run.googleapis.com/v1
    91  kind: Job
    92  metadata:
    93    annotations:
    94      run.googleapis.com/launch-stage: BETA
    95    name: %v
    96  spec:
    97    template:
    98      spec:
    99        template:
   100          spec:
   101            containers:
   102              - image: docker.io/library/busybox:latest
   103                name: job
   104            maxRetries: 2`,
   105  			skaffoldCfg: `
   106  apiVersion: %v
   107  kind: Config
   108  metadata:
   109     name: cloud-run-test
   110  manifests:
   111    rawYaml:
   112      - job.yaml
   113  deploy:
   114    cloudrun:
   115      projectid: %v
   116      region: %v`,
   117  		},
   118  		{
   119  			descrition:         "maxRetries set to 0",
   120  			expectedMaxRetries: 0,
   121  			jobManifest: `
   122  apiVersion: run.googleapis.com/v1
   123  kind: Job
   124  metadata:
   125    annotations:
   126      run.googleapis.com/launch-stage: BETA
   127    name: %v
   128  spec:
   129    template:
   130      spec:
   131        template:
   132          spec:
   133            containers:
   134              - image: docker.io/library/busybox:latest
   135                name: job
   136            maxRetries: 0`,
   137  			skaffoldCfg: `
   138  apiVersion: %v
   139  kind: Config
   140  metadata:
   141     name: cloud-run-test
   142  manifests:
   143    rawYaml:
   144      - job.yaml
   145  deploy:
   146    cloudrun:
   147      projectid: %v
   148      region: %v`,
   149  		},
   150  		{
   151  			descrition:         "maxRetries not specified - default 3",
   152  			expectedMaxRetries: 3,
   153  			jobManifest: `
   154  apiVersion: run.googleapis.com/v1
   155  kind: Job
   156  metadata:
   157    annotations:
   158      run.googleapis.com/launch-stage: BETA
   159    name: %v
   160  spec:
   161    template:
   162      spec:
   163        template:
   164          spec:
   165            containers:
   166              - image: docker.io/library/busybox:latest
   167                name: job`,
   168  			skaffoldCfg: `
   169  apiVersion: %v
   170  kind: Config
   171  metadata:
   172     name: cloud-run-test
   173  manifests:
   174    rawYaml:
   175      - job.yaml
   176  deploy:
   177    cloudrun:
   178      projectid: %v
   179      region: %v`,
   180  		},
   181  	}
   182  
   183  	for _, test := range tests {
   184  		testutil.Run(t, test.descrition, func(t *testutil.T) {
   185  			projectID := "k8s-skaffold"
   186  			region := "us-central1"
   187  			jobName := fmt.Sprintf("job-%v", uuid.New().String())
   188  			skaffoldCfg := fmt.Sprintf(test.skaffoldCfg, latest.Version, projectID, region)
   189  			jobManifest := fmt.Sprintf(test.jobManifest, jobName)
   190  
   191  			tmpDir := t.NewTempDir()
   192  			tmpDir.Write("skaffold.yaml", skaffoldCfg)
   193  			tmpDir.Write("job.yaml", jobManifest)
   194  
   195  			skaffold.Run().InDir(tmpDir.Root()).RunOrFail(t.T)
   196  			t.Cleanup(func() {
   197  				skaffold.Delete(test.args...).InDir(tmpDir.Root()).RunOrFail(t.T)
   198  			})
   199  
   200  			job, err := getJob(context.Background(), projectID, region, jobName)
   201  			if err != nil {
   202  				t.Fatal(err)
   203  			}
   204  
   205  			if diff := cmp.Diff(job.Spec.Template.Spec.Template.Spec.MaxRetries, test.expectedMaxRetries); diff != "" {
   206  				t.Fatalf("Job MaxRetries differ (-got,+want):\n%s", diff)
   207  			}
   208  		})
   209  	}
   210  }
   211  
   212  // TODO: remove nolint when test is unskipped
   213  //
   214  //nolint:unused
   215  func getRunService(ctx context.Context, project, region, service string) (*run.Service, error) {
   216  	crclient, err := run.NewService(ctx, gcp.ClientOptions(ctx)...)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  	sName := fmt.Sprintf("projects/%s/locations/%s/services/%s", project, region, service)
   221  	call := crclient.Projects.Locations.Services.Get(sName)
   222  	return call.Do()
   223  }
   224  
   225  func getJob(ctx context.Context, project, region, job string) (*run.Job, error) {
   226  	cOptions := []option.ClientOption{option.WithEndpoint(fmt.Sprintf("%s-run.googleapis.com", region))}
   227  	cOptions = append(gcp.ClientOptions(ctx), cOptions...)
   228  	crclient, err := run.NewService(ctx, cOptions...)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  	jName := fmt.Sprintf("namespaces/%v/jobs/%v", project, job)
   233  	call := crclient.Namespaces.Jobs.Get(jName)
   234  	return call.Do()
   235  }
   236  
   237  // TODO: remove nolint when test is unskipped
   238  //
   239  //nolint:unused
   240  func checkReady(svc *run.Service) error {
   241  	var ready *run.GoogleCloudRunV1Condition
   242  	for _, cond := range svc.Status.Conditions {
   243  		if cond.Type == "Ready" {
   244  			ready = cond
   245  		}
   246  	}
   247  	if ready == nil {
   248  		return fmt.Errorf("ready condition not found in service: %v", svc)
   249  	}
   250  	if ready.Status != "True" {
   251  		return fmt.Errorf("expected ready status of true, got %s with reason %s", ready.Status, ready.Message)
   252  	}
   253  	return nil
   254  }