github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/integration/helpers/app.go (about) 1 package helpers 2 3 import ( 4 "archive/zip" 5 "fmt" 6 "github.com/onsi/gomega/gbytes" 7 "io" 8 "io/ioutil" 9 "math/rand" 10 "os" 11 "path/filepath" 12 "strings" 13 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gexec" 16 "gopkg.in/yaml.v2" 17 ) 18 19 // WithHelloWorldApp creates a simple application to use with your CLI command 20 // (typically CF Push). When pushing, be aware of specifying '-b 21 // staticfile_buildpack" so that your app will correctly start up with the 22 // proper buildpack. 23 func WithHelloWorldApp(f func(dir string)) { 24 dir, err := ioutil.TempDir("", "simple-app") 25 Expect(err).ToNot(HaveOccurred()) 26 defer os.RemoveAll(dir) 27 28 tempfile := filepath.Join(dir, "index.html") 29 err = ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 30 Expect(err).ToNot(HaveOccurred()) 31 32 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 33 Expect(err).ToNot(HaveOccurred()) 34 35 f(dir) 36 } 37 38 // WithMultiEndpointApp creates a simple application to use with your CLI command 39 // (typically CF Push). It has multiple endpoints which are helpful when testing 40 // http healthchecks 41 func WithMultiEndpointApp(f func(dir string)) { 42 dir, err := ioutil.TempDir("", "simple-app") 43 Expect(err).ToNot(HaveOccurred()) 44 defer os.RemoveAll(dir) 45 46 tempfile := filepath.Join(dir, "index.html") 47 err = ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 48 Expect(err).ToNot(HaveOccurred()) 49 50 tempfile = filepath.Join(dir, "other_endpoint.html") 51 err = ioutil.WriteFile(tempfile, []byte("other endpoint"), 0666) 52 Expect(err).ToNot(HaveOccurred()) 53 54 tempfile = filepath.Join(dir, "third_endpoint.html") 55 err = ioutil.WriteFile(tempfile, []byte("third endpoint"), 0666) 56 Expect(err).ToNot(HaveOccurred()) 57 58 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 59 Expect(err).ToNot(HaveOccurred()) 60 61 f(dir) 62 } 63 64 // WithNoResourceMatchedApp creates a simple application to use with your CLI 65 // command (typically CF Push). When pushing, be aware of specifying '-b 66 // staticfile_buildpack" so that your app will correctly start up with the 67 // proper buildpack. 68 func WithNoResourceMatchedApp(f func(dir string)) { 69 dir, err := ioutil.TempDir("", "simple-app") 70 Expect(err).ToNot(HaveOccurred()) 71 defer os.RemoveAll(dir) 72 73 tempfile := filepath.Join(dir, "index.html") 74 75 err = ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %s", strings.Repeat("a", 65*1024))), 0666) 76 Expect(err).ToNot(HaveOccurred()) 77 78 f(dir) 79 } 80 81 // WithMultiBuildpackApp creates a multi-buildpack application to use with the CF push command. 82 func WithMultiBuildpackApp(f func(dir string)) { 83 f("../../assets/go_calls_ruby") 84 } 85 86 // WithProcfileApp creates an application to use with your CLI command 87 // that contains Procfile defining web and worker processes. 88 func WithProcfileApp(f func(dir string)) { 89 dir, err := ioutil.TempDir("", "simple-ruby-app") 90 Expect(err).ToNot(HaveOccurred()) 91 defer os.RemoveAll(dir) 92 93 err = ioutil.WriteFile(filepath.Join(dir, "Procfile"), []byte(`--- 94 web: ruby -run -e httpd . -p $PORT 95 console: bundle exec irb`, 96 ), 0666) 97 Expect(err).ToNot(HaveOccurred()) 98 99 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile"), nil, 0666) 100 Expect(err).ToNot(HaveOccurred()) 101 102 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile.lock"), []byte(` 103 GEM 104 specs: 105 106 PLATFORMS 107 ruby 108 109 DEPENDENCIES 110 111 BUNDLED WITH 112 1.15.0 113 `), 0666) 114 Expect(err).ToNot(HaveOccurred()) 115 116 f(dir) 117 } 118 119 // WithCrashingApp creates an application to use with your CLI command 120 // that will not successfully start its `web` process 121 func WithCrashingApp(f func(dir string)) { 122 dir, err := ioutil.TempDir("", "crashing-ruby-app") 123 Expect(err).ToNot(HaveOccurred()) 124 defer os.RemoveAll(dir) 125 126 err = ioutil.WriteFile(filepath.Join(dir, "Procfile"), []byte(`--- 127 web: bogus bogus`, 128 ), 0666) 129 Expect(err).ToNot(HaveOccurred()) 130 131 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile"), nil, 0666) 132 Expect(err).ToNot(HaveOccurred()) 133 134 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile.lock"), []byte(` 135 GEM 136 specs: 137 138 PLATFORMS 139 ruby 140 141 DEPENDENCIES 142 143 BUNDLED WITH 144 1.15.0 145 `), 0666) 146 Expect(err).ToNot(HaveOccurred()) 147 148 f(dir) 149 } 150 151 // WithBananaPantsApp creates a simple application to use with your CLI command 152 // (typically CF Push). When pushing, be aware of specifying '-b 153 // staticfile_buildpack" so that your app will correctly start up with the 154 // proper buildpack. 155 func WithBananaPantsApp(f func(dir string)) { 156 dir, err := ioutil.TempDir("", "simple-app") 157 Expect(err).ToNot(HaveOccurred()) 158 defer os.RemoveAll(dir) 159 160 tempfile := filepath.Join(dir, "index.html") 161 err = ioutil.WriteFile(tempfile, []byte("Banana Pants"), 0666) 162 Expect(err).ToNot(HaveOccurred()) 163 164 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 165 Expect(err).ToNot(HaveOccurred()) 166 167 f(dir) 168 } 169 170 // AppGUID returns the GUID for an app in the currently targeted space. 171 func AppGUID(appName string) string { 172 session := CF("app", appName, "--guid") 173 Eventually(session).Should(Exit(0)) 174 return strings.TrimSpace(string(session.Out.Contents())) 175 } 176 177 func AppJSON(appName string) string { 178 appGUID := AppGUID(appName) 179 session := CF("curl", fmt.Sprintf("/v3/apps/%s", appGUID)) 180 Eventually(session).Should(Exit(0)) 181 return strings.TrimSpace(string(session.Out.Contents())) 182 } 183 184 // WriteManifest will write out a YAML manifest file at the specified path. 185 func WriteManifest(path string, manifest map[string]interface{}) { 186 body, err := yaml.Marshal(manifest) 187 Expect(err).ToNot(HaveOccurred()) 188 err = ioutil.WriteFile(path, body, 0666) 189 Expect(err).ToNot(HaveOccurred()) 190 } 191 192 // Zipit zips the source into a .zip file in the target dir 193 func Zipit(source, target, prefix string) error { 194 // Thanks to Svett Ralchev 195 // http://blog.ralch.com/tutorial/golang-working-with-zip/ 196 197 zipfile, err := os.Create(target) 198 if err != nil { 199 return err 200 } 201 defer zipfile.Close() 202 203 if prefix != "" { 204 _, err = io.WriteString(zipfile, prefix) 205 if err != nil { 206 return err 207 } 208 } 209 210 archive := zip.NewWriter(zipfile) 211 defer archive.Close() 212 213 err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error { 214 if err != nil { 215 return err 216 } 217 218 if path == source { 219 return nil 220 } 221 222 header, err := zip.FileInfoHeader(info) 223 if err != nil { 224 return err 225 } 226 header.Name, err = filepath.Rel(source, path) 227 if err != nil { 228 return err 229 } 230 231 header.Name = filepath.ToSlash(header.Name) 232 233 if info.IsDir() { 234 header.Name += "/" 235 header.SetMode(0755) 236 } else { 237 header.Method = zip.Deflate 238 header.SetMode(0744) 239 } 240 241 writer, err := archive.CreateHeader(header) 242 if err != nil { 243 return err 244 } 245 246 if info.IsDir() { 247 return nil 248 } 249 250 file, err := os.Open(path) 251 if err != nil { 252 return err 253 } 254 defer file.Close() 255 256 _, err = io.Copy(writer, file) 257 return err 258 }) 259 260 return err 261 } 262 263 func ConfirmStagingLogs(session *Session) { 264 Eventually(session).Should(gbytes.Say(`(?i)Creating container|Successfully created container|Staging\.\.\.|Staging process started \.\.\.|Staging Complete|Exit status 0|Uploading droplet\.\.\.|Uploading complete`)) 265 }