github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/actor/v2action/manifest_test.go (about)

     1  package v2action_test
     2  
     3  import (
     4  	"errors"
     5  	"io/ioutil"
     6  	"os"
     7  
     8  	. "code.cloudfoundry.org/cli/actor/v2action"
     9  	"code.cloudfoundry.org/cli/actor/v2action/v2actionfakes"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    12  	"code.cloudfoundry.org/cli/types"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Manifest Actions", func() {
    18  	var (
    19  		actor                     *Actor
    20  		fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient
    21  		manifestFilePath          string
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		fakeCloudControllerClient = new(v2actionfakes.FakeCloudControllerClient)
    26  		actor = NewActor(fakeCloudControllerClient, nil, nil)
    27  	})
    28  
    29  	Describe("CreateApplicationManifestByNameAndSpace", func() {
    30  		var (
    31  			createWarnings Warnings
    32  			createErr      error
    33  		)
    34  
    35  		JustBeforeEach(func() {
    36  			createWarnings, createErr = actor.CreateApplicationManifestByNameAndSpace("some-app", "some-space-guid", manifestFilePath)
    37  		})
    38  
    39  		Context("when getting the application summary errors", func() {
    40  			BeforeEach(func() {
    41  				fakeCloudControllerClient.GetApplicationsReturns([]ccv2.Application{}, ccv2.Warnings{"some-app-warning"}, errors.New("some-app-error"))
    42  			})
    43  
    44  			It("returns the error and all warnings", func() {
    45  				Expect(createErr).To(MatchError("some-app-error"))
    46  				Expect(createWarnings).To(ConsistOf("some-app-warning"))
    47  			})
    48  		})
    49  
    50  		Context("when getting the application summary succeeds", func() {
    51  			var app ccv2.Application
    52  
    53  			BeforeEach(func() {
    54  				app = ccv2.Application{
    55  					GUID: "some-app-guid",
    56  					Name: "some-app",
    57  					Buildpack: types.FilteredString{
    58  						IsSet: true,
    59  						Value: "some-buildpack",
    60  					},
    61  					DetectedBuildpack: types.FilteredString{
    62  						IsSet: true,
    63  						Value: "some-detected-buildpack",
    64  					},
    65  					DiskQuota:   types.NullByteSizeInMb{IsSet: true, Value: 1024},
    66  					DockerImage: "some-docker-image",
    67  					DockerCredentials: ccv2.DockerCredentials{
    68  						Username: "some-docker-username",
    69  						Password: "some-docker-password", // CC currently always returns an empty string
    70  					},
    71  					Command: types.FilteredString{
    72  						IsSet: true,
    73  						Value: "some-command",
    74  					},
    75  					DetectedStartCommand: types.FilteredString{
    76  						IsSet: true,
    77  						Value: "some-detected-command",
    78  					},
    79  					EnvironmentVariables: map[string]string{
    80  						"env_1": "foo",
    81  						"env_2": "182837403930483038",
    82  						"env_3": "true",
    83  						"env_4": "1.00001",
    84  					},
    85  					HealthCheckTimeout:      120,
    86  					HealthCheckHTTPEndpoint: "\\some-endpoint",
    87  					HealthCheckType:         "http",
    88  					Instances: types.NullInt{
    89  						Value: 10,
    90  						IsSet: true,
    91  					},
    92  					Memory:    types.NullByteSizeInMb{IsSet: true, Value: 200},
    93  					StackGUID: "some-stack-guid",
    94  				}
    95  
    96  				fakeCloudControllerClient.GetApplicationsReturns(
    97  					[]ccv2.Application{app},
    98  					ccv2.Warnings{"some-app-warning"},
    99  					nil)
   100  
   101  				fakeCloudControllerClient.GetApplicationRoutesReturns(
   102  					[]ccv2.Route{
   103  						{
   104  							GUID:       "some-route-1-guid",
   105  							Host:       "host-1",
   106  							DomainGUID: "some-domain-guid",
   107  						},
   108  						{
   109  							GUID:       "some-route-2-guid",
   110  							Host:       "host-2",
   111  							DomainGUID: "some-domain-guid",
   112  						},
   113  					},
   114  					ccv2.Warnings{"some-routes-warning"},
   115  					nil)
   116  
   117  				fakeCloudControllerClient.GetSharedDomainReturns(
   118  					ccv2.Domain{GUID: "some-domain-guid", Name: "some-domain"},
   119  					ccv2.Warnings{"some-domain-warning"},
   120  					nil)
   121  
   122  				fakeCloudControllerClient.GetStackReturns(
   123  					ccv2.Stack{Name: "some-stack"},
   124  					ccv2.Warnings{"some-stack-warning"},
   125  					nil)
   126  			})
   127  
   128  			Context("when getting services fails", func() {
   129  				BeforeEach(func() {
   130  					fakeCloudControllerClient.GetServiceBindingsReturns(
   131  						[]ccv2.ServiceBinding{},
   132  						ccv2.Warnings{"some-service-warning"},
   133  						errors.New("some-service-error"),
   134  					)
   135  				})
   136  
   137  				It("returns the error and all warnings", func() {
   138  					Expect(createErr).To(MatchError("some-service-error"))
   139  					Expect(createWarnings).To(ConsistOf("some-app-warning", "some-routes-warning", "some-domain-warning", "some-stack-warning", "some-service-warning"))
   140  				})
   141  			})
   142  
   143  			Context("when getting services succeeds", func() {
   144  				BeforeEach(func() {
   145  					fakeCloudControllerClient.GetServiceBindingsReturns(
   146  						[]ccv2.ServiceBinding{
   147  							{ServiceInstanceGUID: "service-1-guid"},
   148  							{ServiceInstanceGUID: "service-2-guid"},
   149  						},
   150  						ccv2.Warnings{"some-service-warning"},
   151  						nil,
   152  					)
   153  					fakeCloudControllerClient.GetServiceInstanceStub = func(serviceInstanceGUID string) (ccv2.ServiceInstance, ccv2.Warnings, error) {
   154  						switch serviceInstanceGUID {
   155  						case "service-1-guid":
   156  							return ccv2.ServiceInstance{Name: "service-1"}, ccv2.Warnings{"some-service-1-warning"}, nil
   157  						case "service-2-guid":
   158  							return ccv2.ServiceInstance{Name: "service-2"}, ccv2.Warnings{"some-service-2-warning"}, nil
   159  						default:
   160  							panic("unknown service instance")
   161  						}
   162  					}
   163  				})
   164  
   165  				Context("when writing manifest succeeds", func() {
   166  					BeforeEach(func() {
   167  						manifestFile, err := ioutil.TempFile("", "manifest-test-")
   168  						Expect(err).NotTo(HaveOccurred())
   169  						Expect(manifestFile.Close()).To(Succeed())
   170  						manifestFilePath = manifestFile.Name()
   171  					})
   172  
   173  					AfterEach(func() {
   174  						Expect(os.Remove(manifestFilePath)).To(Succeed())
   175  					})
   176  
   177  					It("writes the manifest to the specified path", func() {
   178  						manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   179  						Expect(err).NotTo(HaveOccurred())
   180  						Expect(createWarnings).To(ConsistOf("some-app-warning", "some-routes-warning", "some-domain-warning", "some-stack-warning", "some-service-warning", "some-service-1-warning", "some-service-2-warning"))
   181  						Expect(string(manifestBytes)).To(Equal(`applications:
   182  - name: some-app
   183    buildpack: some-buildpack
   184    command: some-command
   185    disk_quota: 1G
   186    docker:
   187      image: some-docker-image
   188      username: some-docker-username
   189    env:
   190      env_1: foo
   191      env_2: "182837403930483038"
   192      env_3: "true"
   193      env_4: "1.00001"
   194    health-check-http-endpoint: \some-endpoint
   195    health-check-type: http
   196    instances: 10
   197    memory: 200M
   198    routes:
   199    - route: host-1.some-domain
   200    - route: host-2.some-domain
   201    services:
   202    - service-1
   203    - service-2
   204    stack: some-stack
   205    timeout: 120
   206  `))
   207  					})
   208  
   209  					Context("when there are no routes", func() {
   210  						BeforeEach(func() {
   211  							fakeCloudControllerClient.GetApplicationRoutesReturns(nil, nil, nil)
   212  						})
   213  
   214  						It("writes the manifest with no-route set to true", func() {
   215  							manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   216  							Expect(err).NotTo(HaveOccurred())
   217  							Expect(createWarnings).To(ConsistOf("some-app-warning", "some-stack-warning", "some-service-warning", "some-service-1-warning", "some-service-2-warning"))
   218  							Expect(string(manifestBytes)).To(Equal(`applications:
   219  - name: some-app
   220    buildpack: some-buildpack
   221    command: some-command
   222    disk_quota: 1G
   223    docker:
   224      image: some-docker-image
   225      username: some-docker-username
   226    env:
   227      env_1: foo
   228      env_2: "182837403930483038"
   229      env_3: "true"
   230      env_4: "1.00001"
   231    health-check-http-endpoint: \some-endpoint
   232    health-check-type: http
   233    instances: 10
   234    memory: 200M
   235    no-route: true
   236    services:
   237    - service-1
   238    - service-2
   239    stack: some-stack
   240    timeout: 120
   241  `))
   242  						})
   243  					})
   244  
   245  					Context("when docker image and username are not provided", func() {
   246  						BeforeEach(func() {
   247  							app.DockerImage = ""
   248  							app.DockerCredentials = ccv2.DockerCredentials{}
   249  							fakeCloudControllerClient.GetApplicationsReturns(
   250  								[]ccv2.Application{app},
   251  								ccv2.Warnings{"some-app-warning"},
   252  								nil)
   253  						})
   254  
   255  						It("does not include it in manifest", func() {
   256  							manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   257  							Expect(err).NotTo(HaveOccurred())
   258  							Expect(string(manifestBytes)).To(Equal(`applications:
   259  - name: some-app
   260    buildpack: some-buildpack
   261    command: some-command
   262    disk_quota: 1G
   263    env:
   264      env_1: foo
   265      env_2: "182837403930483038"
   266      env_3: "true"
   267      env_4: "1.00001"
   268    health-check-http-endpoint: \some-endpoint
   269    health-check-type: http
   270    instances: 10
   271    memory: 200M
   272    routes:
   273    - route: host-1.some-domain
   274    - route: host-2.some-domain
   275    services:
   276    - service-1
   277    - service-2
   278    stack: some-stack
   279    timeout: 120
   280  `))
   281  						})
   282  					})
   283  
   284  					Describe("default CC values", func() {
   285  						// We ommitting default CC values from manifest
   286  						// so that it won't get too big
   287  
   288  						Context("when the health check type is port", func() {
   289  							BeforeEach(func() {
   290  								app.HealthCheckType = constant.ApplicationHealthCheckPort
   291  								fakeCloudControllerClient.GetApplicationsReturns(
   292  									[]ccv2.Application{app},
   293  									ccv2.Warnings{"some-app-warning"},
   294  									nil)
   295  							})
   296  
   297  							It("does not include health check type and endpoint", func() {
   298  								manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   299  								Expect(err).NotTo(HaveOccurred())
   300  								Expect(string(manifestBytes)).To(Equal(`applications:
   301  - name: some-app
   302    buildpack: some-buildpack
   303    command: some-command
   304    disk_quota: 1G
   305    docker:
   306      image: some-docker-image
   307      username: some-docker-username
   308    env:
   309      env_1: foo
   310      env_2: "182837403930483038"
   311      env_3: "true"
   312      env_4: "1.00001"
   313    instances: 10
   314    memory: 200M
   315    routes:
   316    - route: host-1.some-domain
   317    - route: host-2.some-domain
   318    services:
   319    - service-1
   320    - service-2
   321    stack: some-stack
   322    timeout: 120
   323  `))
   324  							})
   325  						})
   326  
   327  						Context("when the health check type is http", func() {
   328  							Context("when the health check endpoint path is '/'", func() {
   329  								BeforeEach(func() {
   330  									app.HealthCheckType = constant.ApplicationHealthCheckHTTP
   331  									app.HealthCheckHTTPEndpoint = "/"
   332  									fakeCloudControllerClient.GetApplicationsReturns(
   333  										[]ccv2.Application{app},
   334  										ccv2.Warnings{"some-app-warning"},
   335  										nil)
   336  								})
   337  
   338  								It("does not include health check endpoint in manifest", func() {
   339  									manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   340  									Expect(err).NotTo(HaveOccurred())
   341  									Expect(string(manifestBytes)).To(Equal(`applications:
   342  - name: some-app
   343    buildpack: some-buildpack
   344    command: some-command
   345    disk_quota: 1G
   346    docker:
   347      image: some-docker-image
   348      username: some-docker-username
   349    env:
   350      env_1: foo
   351      env_2: "182837403930483038"
   352      env_3: "true"
   353      env_4: "1.00001"
   354    health-check-type: http
   355    instances: 10
   356    memory: 200M
   357    routes:
   358    - route: host-1.some-domain
   359    - route: host-2.some-domain
   360    services:
   361    - service-1
   362    - service-2
   363    stack: some-stack
   364    timeout: 120
   365  `))
   366  								})
   367  							})
   368  
   369  							Context("when the health check type is process", func() {
   370  								BeforeEach(func() {
   371  									app.HealthCheckType = constant.ApplicationHealthCheckProcess
   372  									fakeCloudControllerClient.GetApplicationsReturns(
   373  										[]ccv2.Application{app},
   374  										ccv2.Warnings{"some-app-warning"},
   375  										nil)
   376  								})
   377  
   378  								It("does not include health check endpoint in manifest", func() {
   379  									manifestBytes, err := ioutil.ReadFile(manifestFilePath)
   380  									Expect(err).NotTo(HaveOccurred())
   381  									Expect(string(manifestBytes)).To(Equal(`applications:
   382  - name: some-app
   383    buildpack: some-buildpack
   384    command: some-command
   385    disk_quota: 1G
   386    docker:
   387      image: some-docker-image
   388      username: some-docker-username
   389    env:
   390      env_1: foo
   391      env_2: "182837403930483038"
   392      env_3: "true"
   393      env_4: "1.00001"
   394    health-check-type: process
   395    instances: 10
   396    memory: 200M
   397    routes:
   398    - route: host-1.some-domain
   399    - route: host-2.some-domain
   400    services:
   401    - service-1
   402    - service-2
   403    stack: some-stack
   404    timeout: 120
   405  `))
   406  								})
   407  							})
   408  						})
   409  					})
   410  				})
   411  
   412  				Context("when writing the manifest fails", func() {
   413  					BeforeEach(func() {
   414  						var err error
   415  						manifestFilePath, err = ioutil.TempDir("", "manifest-test-")
   416  						Expect(err).NotTo(HaveOccurred())
   417  					})
   418  
   419  					AfterEach(func() {
   420  						Expect(os.RemoveAll(manifestFilePath)).To(Succeed())
   421  					})
   422  
   423  					It("returns an ManifestCreationError", func() {
   424  						Expect(createErr).To(HaveOccurred())
   425  						Expect(createErr.Error()).To(ContainSubstring("Error creating manifest file:"))
   426  						Expect(createWarnings).To(ConsistOf("some-app-warning", "some-routes-warning", "some-domain-warning", "some-stack-warning", "some-service-warning", "some-service-1-warning", "some-service-2-warning"))
   427  					})
   428  				})
   429  			})
   430  		})
   431  	})
   432  })