github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/pkg/test/porch/cluster.go (about) 1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package porch 16 17 import ( 18 "bytes" 19 "os/exec" 20 "strings" 21 "testing" 22 "time" 23 ) 24 25 const ( 26 TestGitServerImage = "test-git-server" 27 ) 28 29 func GetGitServerImageName(t *testing.T) string { 30 cmd := exec.Command("kubectl", "get", "pods", "--selector=app=porch-server", "--namespace=porch-system", 31 "--output=jsonpath={.items[*].spec.containers[*].image}") 32 33 var stderr bytes.Buffer 34 var stdout bytes.Buffer 35 36 cmd.Stderr = &stderr 37 cmd.Stdout = &stdout 38 39 if err := cmd.Run(); err != nil { 40 t.Fatalf("Error when getting Porch image version: %v: %s", err, stderr.String()) 41 } 42 43 out := stdout.String() 44 t.Logf("Porch image query output: %s", out) 45 46 lines := strings.Split(out, "\n") 47 if len(lines) == 0 { 48 t.Fatalf("kubectl get pods didn't return any images: %s", out) 49 } 50 image := strings.TrimSpace(lines[0]) 51 if image == "" { 52 t.Fatalf("Cannot determine Porch server image: output was %q", out) 53 } 54 return InferGitServerImage(image) 55 } 56 57 func InferGitServerImage(porchImage string) string { 58 slash := strings.LastIndex(porchImage, "/") 59 repo := porchImage[:slash+1] 60 image := porchImage[slash+1:] 61 colon := strings.LastIndex(image, ":") 62 tag := image[colon+1:] 63 64 return repo + TestGitServerImage + ":" + tag 65 } 66 67 func KubectlApply(t *testing.T, config string) { 68 cmd := exec.Command("kubectl", "apply", "-f", "-") 69 cmd.Stdin = strings.NewReader(config) 70 out, err := cmd.CombinedOutput() 71 if err != nil { 72 t.Fatalf("kubectl apply failed: %v\ninput: %s\n\noutput:%s", err, config, string(out)) 73 } 74 t.Logf("kubectl apply\n%s\noutput:\n%s", config, string(out)) 75 } 76 77 func KubectlWaitForDeployment(t *testing.T, namespace, name string) { 78 args := []string{"rollout", "status", "deployment", "--namespace", namespace, name} 79 cmd := exec.Command("kubectl", args...) 80 out, err := cmd.CombinedOutput() 81 if err != nil { 82 t.Fatalf("kubectl %s failed: %v\noutput:\n%s", strings.Join(args, " "), err, string(out)) 83 } 84 t.Logf("kubectl %s:\n%s", strings.Join(args, " "), string(out)) 85 } 86 87 func KubectlWaitForService(t *testing.T, namespace, name string) { 88 args := []string{"get", "endpoints", "--namespace", namespace, name, "--output=jsonpath='{.subsets[*].addresses[*].ip}'"} 89 90 giveUp := time.Now().Add(1 * time.Minute) 91 for { 92 cmd := exec.Command("kubectl", args...) 93 var stdout, stderr bytes.Buffer 94 cmd.Stdout = &stdout 95 cmd.Stderr = &stderr 96 97 err := cmd.Run() 98 s := stdout.String() 99 if err == nil && len(s) > 0 { // Endpoint has an IP address assigned 100 t.Logf("Endpoints: %q", s) 101 break 102 } 103 104 if time.Now().After(giveUp) { 105 var msg string 106 if err != nil { 107 msg = err.Error() 108 } 109 t.Fatalf("Service endpoint %s/%s not ready on time. Giving up: %s", namespace, name, msg) 110 } 111 112 time.Sleep(5 * time.Second) 113 } 114 } 115 116 // Kubernetes DNS needs time to propagate the updated address 117 // Wait until we can register the repository and list its contents. 118 func KubectlWaitForGitDNS(t *testing.T, gitServerURL string) { 119 const name = "test-git-dns-resolve" 120 121 KubectlCreateNamespace(t, name) 122 defer KubectlDeleteNamespace(t, name) 123 124 // We expect repos to automatically be created (albeit empty) 125 repoURL := gitServerURL + "/" + name 126 127 cmd := exec.Command("kpt", "alpha", "repo", "register", "--namespace", name, "--name", name, repoURL) 128 t.Logf("running command %v", strings.Join(cmd.Args, " ")) 129 out, err := cmd.CombinedOutput() 130 if err != nil { 131 t.Fatalf("Failed to register probe repository: %v\n%s", err, string(out)) 132 } 133 134 // Based on experience, DNS seems to get updated inside the cluster within 135 // few seconds. We will wait about a minute. 136 // If this turns out to be an issue, we will sidestep DNS and use the Endpoints 137 // IP address directly. 138 giveUp := time.Now().Add(1 * time.Minute) 139 for { 140 cmd := exec.Command("kpt", "alpha", "rpkg", "get", "--namespace", name) 141 t.Logf("running command %v", strings.Join(cmd.Args, " ")) 142 out, err := cmd.CombinedOutput() 143 t.Logf("output: %v", string(out)) 144 145 if err == nil { 146 break 147 } 148 149 if time.Now().After(giveUp) { 150 t.Fatalf("Git service DNS resolution failed: %v", err) 151 } 152 153 time.Sleep(5 * time.Second) 154 } 155 } 156 157 func KubectlCreateNamespace(t *testing.T, name string) { 158 cmd := exec.Command("kubectl", "create", "namespace", name) 159 t.Logf("running command %v", strings.Join(cmd.Args, " ")) 160 out, err := cmd.CombinedOutput() 161 if err != nil { 162 t.Fatalf("Failed to create namespace %q: %v\n%s", name, err, string(out)) 163 } 164 t.Logf("output: %v", string(out)) 165 } 166 167 func KubectlDeleteNamespace(t *testing.T, name string) { 168 cmd := exec.Command("kubectl", "delete", "namespace", name) 169 t.Logf("running command %v", strings.Join(cmd.Args, " ")) 170 out, err := cmd.CombinedOutput() 171 if err != nil { 172 t.Logf("Failed to delete namespace %q: %v\n%s", name, err, string(out)) 173 } 174 t.Logf("output: %v", string(out)) 175 } 176 177 func RegisterRepository(t *testing.T, repoURL, namespace, name string) { 178 cmd := exec.Command("kpt", "alpha", "repo", "register", "--namespace", namespace, "--name", name, repoURL) 179 t.Logf("running command %v", strings.Join(cmd.Args, " ")) 180 out, err := cmd.CombinedOutput() 181 if err != nil { 182 t.Fatalf("Failed to register repository %q: %v\n%s", repoURL, err, string(out)) 183 } 184 t.Logf("output: %v", string(out)) 185 }