1 package helper
2
3 import (
4 "fmt"
5 "os/exec"
6 "path/filepath"
7 "strings"
8 "time"
9
10 . "github.com/onsi/ginkgo/v2"
11 . "github.com/onsi/gomega"
12 "github.com/onsi/gomega/gexec"
13 "github.com/onsi/gomega/types"
14
15 "github.com/redhat-developer/odo/pkg/labels"
16 )
17
18 const (
19 TelemetryCaller = "TELEMETRY_CALLER"
20 )
21
22 func runningCmd(cmd *exec.Cmd) string {
23 prog := filepath.Base(cmd.Path)
24 var env []string
25 for _, e := range cmd.Env {
26 if strings.HasPrefix(e, "ODO_") || e == TelemetryCaller {
27 env = append(env, e)
28 }
29 }
30 return fmt.Sprintf("Running %s with args %v and odo env: %v", prog, cmd.Args, env)
31 }
32
33 func CmdRunner(program string, args ...string) *gexec.Session {
34
35 prefix := fmt.Sprintf("[%s] ", filepath.Base(program))
36 prefixWriter := gexec.NewPrefixedWriter(prefix, GinkgoWriter)
37 command := exec.Command(program, args...)
38 setSysProcAttr(command)
39 fmt.Fprintln(GinkgoWriter, runningCmd(command))
40 session, err := gexec.Start(command, prefixWriter, prefixWriter)
41 Expect(err).NotTo(HaveOccurred())
42 return session
43 }
44
45
46
47 func WaitForOutputToContain(substring string, timeoutInSeconds int, intervalInSeconds int, session *gexec.Session) {
48 Eventually(func() string {
49 if session.ExitCode() != -1 {
50 Expect(string(session.Out.Contents())).To(ContainSubstring(substring), "session exited, but substring not found")
51 }
52 contents := string(session.Out.Contents())
53 return contents
54 }, timeoutInSeconds, intervalInSeconds).Should(ContainSubstring(substring))
55
56 }
57
58 func WaitForOutputToContainOne(substrings []string, timeoutInSeconds int, intervalInSeconds int, session *gexec.Session) {
59
60 matchers := make([]types.GomegaMatcher, 0, len(substrings))
61 for _, substring := range substrings {
62 matchers = append(matchers, ContainSubstring(substring))
63 }
64 Eventually(func() string {
65 if session.ExitCode() != -1 {
66 Expect(string(session.Out.Contents())).To(SatisfyAny(matchers...), "session exited, but substring not found")
67 }
68 contents := string(session.Out.Contents())
69 return contents
70 }, timeoutInSeconds, intervalInSeconds).Should(SatisfyAny(matchers...))
71 }
72
73
74
75 func WaitForErroutToContain(substring string, timeoutInSeconds int, intervalInSeconds int, session *gexec.Session) {
76
77 Eventually(func() string {
78 if session.ExitCode() != -1 {
79 Expect(string(session.Err.Contents())).To(ContainSubstring(substring), "session exited, but substring not found")
80 }
81 contents := string(session.Err.Contents())
82 return contents
83 }, timeoutInSeconds, intervalInSeconds).Should(ContainSubstring(substring))
84
85 }
86
87
88
89
90 func WaitAndCheckForTerminatingState(path, resourceType, namespace string, timeoutMinutes int) bool {
91 pingTimeout := time.After(time.Duration(timeoutMinutes) * time.Minute)
92
93
94 tick := time.Tick(time.Second)
95 for {
96 select {
97 case <-pingTimeout:
98 Fail(fmt.Sprintf("Timeout after %d minutes", timeoutMinutes))
99
100 case <-tick:
101 session := CmdRunner(path, "get", resourceType, "--namespace", namespace)
102 Eventually(session).Should(gexec.Exit(0))
103
104 outputStdErr := string(session.Wait().Err.Contents())
105 outputStdOut := string(session.Wait().Out.Contents())
106
107
108
109 if strings.Contains(strings.ToLower(outputStdErr), "no resources found") || strings.Contains(strings.ToLower(outputStdOut), "terminating") {
110 return true
111 }
112 }
113 }
114 }
115
116
117
118 func GetAnnotationsDeployment(path, componentName, appName, projectName string) map[string]string {
119 var mapOutput = make(map[string]string)
120 selector := labels.Builder().WithComponentName(componentName).WithAppName(appName).SelectorFlag()
121 output := Cmd(path, "get", "deployment", selector, "--namespace", projectName,
122 "-o", "go-template='{{ range $k, $v := (index .items 0).metadata.annotations}}{{$k}}:{{$v}}{{\"\\n\"}}{{end}}'").ShouldPass().Out()
123
124 for _, line := range strings.Split(output, "\n") {
125 line = strings.TrimPrefix(line, "'")
126 splits := strings.Split(line, ":")
127 if len(splits) < 2 {
128 continue
129 }
130 name := splits[0]
131 value := strings.Join(splits[1:], ":")
132 mapOutput[name] = value
133 }
134 return mapOutput
135 }
136
137
138 func GetSecrets(path, project string) string {
139 session := CmdRunner(path, "get", "secrets", "--namespace", project)
140 Eventually(session).Should(gexec.Exit(0))
141 output := string(session.Wait().Out.Contents())
142 return output
143 }
144
145
146 func GetEnvRefNames(path, componentName, appName, projectName string) []string {
147 selector := labels.Builder().WithComponentName(componentName).WithAppName(appName).SelectorFlag()
148 output := Cmd(path, "get", "deployment", selector, "--namespace", projectName,
149 "-o", "jsonpath='{range .items[0].spec.template.spec.containers[0].envFrom[*]}{.secretRef.name}{\"\\n\"}{end}'").ShouldPass().Out()
150
151 var result []string
152 for _, line := range strings.Split(output, "\n") {
153 line = strings.TrimPrefix(line, "'")
154 result = append(result, strings.TrimSpace(line))
155 }
156 return result
157 }
158
159
160 func GetEnvFromEntry(path string, componentName string, appName string, projectName string) string {
161 envFromOut := Cmd(path, "get", "deployment", componentName+"-"+appName, "--namespace", projectName,
162 "-o", "jsonpath='{.spec.template.spec.containers[0].envFrom}'").ShouldPass().Out()
163 return strings.TrimSpace(envFromOut)
164 }
165
166
167 func GetVolumeNamesFromDeployment(path, componentName, appName, projectName string) map[string]string {
168 var mapOutput = make(map[string]string)
169 selector := labels.Builder().WithComponentName(componentName).WithAppName(appName).SelectorFlag()
170 output := Cmd(path, "get", "deployment", selector, "--namespace", projectName,
171 "-o", "jsonpath='{range .items[0].spec.template.spec.volumes[*]}{.name}{\":\"}{.persistentVolumeClaim.claimName}{\"\\n\"}{end}'").ShouldPass().Out()
172
173 for _, line := range strings.Split(output, "\n") {
174 line = strings.TrimPrefix(line, "'")
175 splits := strings.Split(line, ":")
176 if splits[0] == "" {
177 continue
178 }
179 name := splits[0]
180
181
182
183 value := "emptyDir"
184 if len(splits) > 1 && splits[1] != "" {
185 value = splits[1]
186 }
187 mapOutput[name] = value
188 }
189 return mapOutput
190 }
191
View as plain text