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 }