github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/integration/helpers/app.go (about) 1 package helpers 2 3 import ( 4 "archive/zip" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "math/rand" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/onsi/gomega/gbytes" 14 15 . "github.com/onsi/gomega" 16 . "github.com/onsi/gomega/gexec" 17 "gopkg.in/yaml.v2" 18 ) 19 20 // CreateApp creates an empty app in CloudController with no package or droplet 21 func CreateApp(app string) { 22 Eventually(CF("create-app", app)).Should(Exit(0)) 23 } 24 25 // QuickDeleteApp deletes the app with the given name, if provided, using 26 // 'cf curl /v3/app... -X DELETE'. 27 func QuickDeleteApp(appName string) { 28 guid := AppGUID(appName) 29 url := fmt.Sprintf("/v3/apps/%s", guid) 30 session := CF("curl", "-X", "DELETE", url) 31 Eventually(session).Should(Exit(0)) 32 } 33 34 // WithHelloWorldApp creates a simple application to use with your CLI command 35 // (typically CF Push). When pushing, be aware of specifying '-b 36 // staticfile_buildpack" so that your app will correctly start up with the 37 // proper buildpack. 38 func WithHelloWorldApp(f func(dir string)) { 39 dir := TempDirAbsolutePath("", "simple-app") 40 defer os.RemoveAll(dir) 41 42 tempfile := filepath.Join(dir, "index.html") 43 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 44 Expect(err).ToNot(HaveOccurred()) 45 46 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 47 Expect(err).ToNot(HaveOccurred()) 48 49 f(dir) 50 } 51 52 // WithMultiEndpointApp creates a simple application to use with your CLI command 53 // (typically CF Push). It has multiple endpoints which are helpful when testing 54 // http healthchecks. 55 func WithMultiEndpointApp(f func(dir string)) { 56 dir := TempDirAbsolutePath("", "simple-app") 57 defer os.RemoveAll(dir) 58 59 tempfile := filepath.Join(dir, "index.html") 60 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666) 61 Expect(err).ToNot(HaveOccurred()) 62 63 tempfile = filepath.Join(dir, "other_endpoint.html") 64 err = ioutil.WriteFile(tempfile, []byte("other endpoint"), 0666) 65 Expect(err).ToNot(HaveOccurred()) 66 67 tempfile = filepath.Join(dir, "third_endpoint.html") 68 err = ioutil.WriteFile(tempfile, []byte("third endpoint"), 0666) 69 Expect(err).ToNot(HaveOccurred()) 70 71 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 72 Expect(err).ToNot(HaveOccurred()) 73 74 f(dir) 75 } 76 77 func WithSidecarApp(f func(dir string), appName string) { 78 withSidecarManifest := func(dir string) { 79 err := ioutil.WriteFile(filepath.Join(dir, "manifest.yml"), []byte(fmt.Sprintf(`--- 80 applications: 81 - name: %s 82 sidecars: 83 - name: sidecar_name 84 process_types: [web] 85 command: sleep infinity`, 86 appName)), 0666) 87 Expect(err).ToNot(HaveOccurred()) 88 89 f(dir) 90 } 91 92 WithHelloWorldApp(withSidecarManifest) 93 } 94 95 func WithTaskApp(f func(dir string), appName string) { 96 withTaskManifest := func(dir string) { 97 err := ioutil.WriteFile(filepath.Join(dir, "manifest.yml"), []byte(fmt.Sprintf(`--- 98 applications: 99 - name: %s 100 processes: 101 - type: task 102 command: echo hi`, 103 appName)), 0666) 104 Expect(err).ToNot(HaveOccurred()) 105 106 f(dir) 107 } 108 109 WithHelloWorldApp(withTaskManifest) 110 } 111 112 // WithNoResourceMatchedApp creates a simple application to use with your CLI 113 // command (typically CF Push). When pushing, be aware of specifying '-b 114 // staticfile_buildpack" so that your app will correctly start up with the 115 // proper buildpack. 116 func WithNoResourceMatchedApp(f func(dir string)) { 117 dir := TempDirAbsolutePath("", "simple-app") 118 defer os.RemoveAll(dir) 119 120 tempfile := filepath.Join(dir, "index.html") 121 122 err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %s", strings.Repeat("a", 65*1024))), 0666) 123 Expect(err).ToNot(HaveOccurred()) 124 125 f(dir) 126 } 127 128 // WithMultiBuildpackApp creates a multi-buildpack application to use with the CF push command. 129 func WithMultiBuildpackApp(f func(dir string)) { 130 f("../../assets/go_calls_ruby") 131 } 132 133 // WithProcfileApp creates an application to use with your CLI command 134 // that contains Procfile defining web and worker processes. 135 func WithProcfileApp(f func(dir string)) { 136 dir := TempDirAbsolutePath("", "simple-ruby-app") 137 defer os.RemoveAll(dir) 138 139 err := ioutil.WriteFile(filepath.Join(dir, "Procfile"), []byte(`--- 140 web: ruby -run -e httpd . -p $PORT 141 console: bundle exec irb`, 142 ), 0666) 143 Expect(err).ToNot(HaveOccurred()) 144 145 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile"), []byte(`source 'http://rubygems.org' 146 gem 'irb'`, 147 ), 0666) 148 Expect(err).ToNot(HaveOccurred()) 149 150 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile.lock"), []byte(`GEM 151 remote: http://rubygems.org/ 152 specs: 153 io-console (0.5.6) 154 irb (1.2.4) 155 reline (>= 0.0.1) 156 reline (0.1.4) 157 io-console (~> 0.5) 158 159 PLATFORMS 160 ruby 161 162 DEPENDENCIES 163 irb 164 165 BUNDLED WITH 166 2.1.4`, 167 ), 0666) 168 Expect(err).ToNot(HaveOccurred()) 169 170 f(dir) 171 } 172 173 // WithCrashingApp creates an application to use with your CLI command 174 // that will not successfully start its `web` process 175 func WithCrashingApp(f func(dir string)) { 176 dir := TempDirAbsolutePath("", "crashing-ruby-app") 177 defer os.RemoveAll(dir) 178 179 err := ioutil.WriteFile(filepath.Join(dir, "Procfile"), []byte(`--- 180 web: bogus bogus`, 181 ), 0666) 182 Expect(err).ToNot(HaveOccurred()) 183 184 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile"), nil, 0666) 185 Expect(err).ToNot(HaveOccurred()) 186 187 err = ioutil.WriteFile(filepath.Join(dir, "Gemfile.lock"), []byte(` 188 GEM 189 specs: 190 191 PLATFORMS 192 ruby 193 194 DEPENDENCIES 195 196 BUNDLED WITH 197 1.15.0 198 `), 0666) 199 Expect(err).ToNot(HaveOccurred()) 200 201 f(dir) 202 } 203 204 // WithBananaPantsApp creates a simple application to use with your CLI command 205 // (typically CF Push). When pushing, be aware of specifying '-b 206 // staticfile_buildpack" so that your app will correctly start up with the 207 // proper buildpack. 208 func WithBananaPantsApp(f func(dir string)) { 209 dir := TempDirAbsolutePath("", "simple-app") 210 defer os.RemoveAll(dir) 211 212 tempfile := filepath.Join(dir, "index.html") 213 err := ioutil.WriteFile(tempfile, []byte("Banana Pants"), 0666) 214 Expect(err).ToNot(HaveOccurred()) 215 216 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 217 Expect(err).ToNot(HaveOccurred()) 218 219 f(dir) 220 } 221 222 func WithEmptyFilesApp(f func(dir string)) { 223 dir := TempDirAbsolutePath("", "simple-app") 224 defer os.RemoveAll(dir) 225 226 tempfile := filepath.Join(dir, "index.html") 227 err := ioutil.WriteFile(tempfile, nil, 0666) 228 Expect(err).ToNot(HaveOccurred()) 229 230 err = ioutil.WriteFile(filepath.Join(dir, "Staticfile"), nil, 0666) 231 Expect(err).ToNot(HaveOccurred()) 232 233 f(dir) 234 } 235 236 // AppGUID returns the GUID for an app in the currently targeted space. 237 func AppGUID(appName string) string { 238 session := CF("app", appName, "--guid") 239 Eventually(session).Should(Exit(0)) 240 return strings.TrimSpace(string(session.Out.Contents())) 241 } 242 243 // AppJSON returns the JSON representation of an app by name. 244 func AppJSON(appName string) string { 245 appGUID := AppGUID(appName) 246 session := CF("curl", fmt.Sprintf("/v3/apps/%s", appGUID)) 247 Eventually(session).Should(Exit(0)) 248 return strings.TrimSpace(string(session.Out.Contents())) 249 } 250 251 // WriteManifest will write out a YAML manifest file at the specified path. 252 func WriteManifest(path string, manifest map[string]interface{}) { 253 body, err := yaml.Marshal(manifest) 254 Expect(err).ToNot(HaveOccurred()) 255 err = ioutil.WriteFile(path, body, 0666) 256 Expect(err).ToNot(HaveOccurred()) 257 } 258 259 // Zipit zips the source into a .zip file in the target dir. 260 func Zipit(source, target, prefix string) error { 261 // Thanks to Svett Ralchev 262 // http://blog.ralch.com/tutorial/golang-working-with-zip/ 263 264 zipfile, err := os.Create(target) 265 if err != nil { 266 return err 267 } 268 defer zipfile.Close() 269 270 if prefix != "" { 271 _, err = io.WriteString(zipfile, prefix) 272 if err != nil { 273 return err 274 } 275 } 276 277 archive := zip.NewWriter(zipfile) 278 defer archive.Close() 279 280 err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error { 281 if err != nil { 282 return err 283 } 284 285 if path == source { 286 return nil 287 } 288 289 header, err := zip.FileInfoHeader(info) 290 if err != nil { 291 return err 292 } 293 header.Name, err = filepath.Rel(source, path) 294 if err != nil { 295 return err 296 } 297 298 header.Name = filepath.ToSlash(header.Name) 299 300 if info.IsDir() { 301 header.Name += "/" 302 header.SetMode(0755) 303 } else { 304 header.Method = zip.Deflate 305 header.SetMode(0744) 306 } 307 308 writer, err := archive.CreateHeader(header) 309 if err != nil { 310 return err 311 } 312 313 if info.IsDir() { 314 return nil 315 } 316 317 file, err := os.Open(path) 318 if err != nil { 319 return err 320 } 321 defer file.Close() 322 323 _, err = io.Copy(writer, file) 324 return err 325 }) 326 327 return err 328 } 329 330 // ConfirmStagingLogs checks session for log output 331 // indicating that staging is working. 332 func ConfirmStagingLogs(session *Session) { 333 Eventually(session).Should(gbytes.Say(`(?i)Creating container|Successfully created container|Staging\.\.\.|Staging process started \.\.\.|Staging Complete|Exit status 0|Uploading droplet\.\.\.|Uploading complete`)) 334 }