github.com/sleungcy/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  }