From 0cc96f4e1870c174b093e29c9bd64e80376eac55 Mon Sep 17 00:00:00 2001 From: Pavel Busko Date: Mon, 23 Sep 2024 18:28:04 +0200 Subject: [PATCH] [RFC0028] Support for Cloud Native Buildpacks lifecycle (#2871) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Dillmann Co-authored-by: Nicolas Bender Co-authored-by: Pavel Busko Co-authored-by: Ralf Pannemans Co-authored-by: Al Berez Co-authored-by: João Pereira --- .../workflows/tests-integration-reusable.yml | 2 + actor/v7action/application.go | 1 + actor/v7pushaction/actor.go | 3 + actor/v7pushaction/create_push_plans.go | 12 + actor/v7pushaction/create_push_plans_test.go | 22 +- .../handle_cnb_credentials_override.go | 23 + .../handle_cnb_credentials_override_test.go | 66 +++ .../v7pushaction/handle_lifecycle_override.go | 19 + actor/v7pushaction/push_plan.go | 2 + api/cloudcontroller/ccv3/application_test.go | 11 + .../ccv3/constant/application.go | 3 + cf/commands/application/apps.go | 2 +- command/commandfakes/fake_config.go | 479 ++++++++++++------ command/config.go | 1 + command/v7/create_app_command.go | 34 +- command/v7/create_app_command_test.go | 38 ++ command/v7/push_command.go | 69 ++- command/v7/push_command_test.go | 86 ++++ command/v7/shared/app_summary_displayer.go | 33 +- command/v7/shared/manifest_diff_displayer.go | 10 + .../v7/shared/manifest_diff_displayer_test.go | 32 ++ integration/assets/js-hello/index.js | 12 + integration/assets/js-hello/package.json | 8 + integration/helpers/app.go | 5 + .../commonisolated/common_isolated_setup.go | 1 + .../experimental/experimental_suite_test.go | 1 + .../shared/global/global_suite_test.go | 1 + integration/v7/global/global_suite_test.go | 1 + integration/v7/isolated/app_command_test.go | 14 + .../v7/isolated/create_app_command_test.go | 14 +- integration/v7/push/help_test.go | 1 + integration/v7/push/push_suite_test.go | 1 + integration/v7/push/tasks_test.go | 5 +- resources/application_resource.go | 16 +- util/configv3/env.go | 17 + util/configv3/load_config.go | 1 + util/manifestparser/application.go | 33 +- 37 files changed, 857 insertions(+), 222 deletions(-) create mode 100644 actor/v7pushaction/handle_cnb_credentials_override.go create mode 100644 actor/v7pushaction/handle_cnb_credentials_override_test.go create mode 100644 actor/v7pushaction/handle_lifecycle_override.go create mode 100644 integration/assets/js-hello/index.js create mode 100644 integration/assets/js-hello/package.json diff --git a/.github/workflows/tests-integration-reusable.yml b/.github/workflows/tests-integration-reusable.yml index 892c045629a..d9435f0e9d4 100644 --- a/.github/workflows/tests-integration-reusable.yml +++ b/.github/workflows/tests-integration-reusable.yml @@ -207,6 +207,7 @@ jobs: "include_container_networking": true, "include_detect": true, "include_docker": true, + "include_cnb": true, "include_internet_dependent": true, "include_isolation_segments": true, "isolation_segment_name": "persistent_isolation_segment", @@ -237,6 +238,7 @@ jobs: cf api ${API} --skip-ssl-validation cf auth cf enable-feature-flag diego_docker + cf enable-feature-flag diego_cnb cf enable-feature-flag service_instance_sharing - name: Run CATS Tests diff --git a/actor/v7action/application.go b/actor/v7action/application.go index 7d1c1fb2dca..e86ca01c34a 100644 --- a/actor/v7action/application.go +++ b/actor/v7action/application.go @@ -162,6 +162,7 @@ func (actor Actor) CreateApplicationInSpace(app resources.Application, spaceGUID LifecycleBuildpacks: app.LifecycleBuildpacks, StackName: app.StackName, Name: app.Name, + Credentials: app.Credentials, SpaceGUID: spaceGUID, }) diff --git a/actor/v7pushaction/actor.go b/actor/v7pushaction/actor.go index 829b64e2a19..4d2b2822cf2 100644 --- a/actor/v7pushaction/actor.go +++ b/actor/v7pushaction/actor.go @@ -42,6 +42,9 @@ func NewActor(v3Actor V7Actor, sharedActor SharedActor) *Actor { HandleInstancesOverride, HandleStartCommandOverride, + HandleCNBCredentialsOverride, + + HandleLifecycleOverride, // Type must come before endpoint because endpoint validates against type HandleHealthCheckTypeOverride, diff --git a/actor/v7pushaction/create_push_plans.go b/actor/v7pushaction/create_push_plans.go index 0b9efcf2af2..7c656d05063 100644 --- a/actor/v7pushaction/create_push_plans.go +++ b/actor/v7pushaction/create_push_plans.go @@ -31,6 +31,18 @@ func (actor Actor) CreatePushPlans( BitsPath: manifestApplication.Path, } + if manifestApplication.Lifecycle != "" { + plan.Application.LifecycleType = manifestApplication.Lifecycle + } + + if overrides.Lifecycle != "" { + plan.Application.LifecycleType = overrides.Lifecycle + } + + if overrides.CNBCredentials != nil { + plan.Application.Credentials = overrides.CNBCredentials + } + if manifestApplication.Docker != nil { plan.DockerImageCredentials = v7action.DockerImageCredentials{ Path: manifestApplication.Docker.Image, diff --git a/actor/v7pushaction/create_push_plans_test.go b/actor/v7pushaction/create_push_plans_test.go index 871026c3adb..9b8040935a0 100644 --- a/actor/v7pushaction/create_push_plans_test.go +++ b/actor/v7pushaction/create_push_plans_test.go @@ -41,7 +41,7 @@ var _ = Describe("CreatePushPlans", func() { manifest = manifestparser.Manifest{ Applications: []manifestparser.Application{ - {Name: "name-1", Path: "path1"}, + {Name: "name-1", Path: "path1", Lifecycle: "cnb"}, {Name: "name-2", Path: "path2", Docker: &manifestparser.Docker{Image: "image", Username: "uname"}}, }, } @@ -49,6 +49,9 @@ var _ = Describe("CreatePushPlans", func() { spaceGUID = "space" flagOverrides = FlagOverrides{ DockerPassword: "passwd", + CNBCredentials: map[string]interface{}{ + "foo": "bar", + }, } testUpdatePlanCount = 0 @@ -120,6 +123,10 @@ var _ = Describe("CreatePushPlans", func() { Expect(pushPlans[0].DockerImageCredentials.Username).To(Equal("")) Expect(pushPlans[0].DockerImageCredentials.Password).To(Equal("")) Expect(pushPlans[0].BitsPath).To(Equal("path1")) + Expect(pushPlans[0].Application.LifecycleType).To(BeEquivalentTo("cnb")) + Expect(pushPlans[0].Application.Credentials).To(Equal(map[string]interface{}{ + "foo": "bar", + })) Expect(pushPlans[1].Application.Name).To(Equal("name-2")) Expect(pushPlans[1].Application.GUID).To(Equal("app-guid-2")) Expect(pushPlans[1].SpaceGUID).To(Equal(spaceGUID)) @@ -128,7 +135,20 @@ var _ = Describe("CreatePushPlans", func() { Expect(pushPlans[1].DockerImageCredentials.Username).To(Equal("uname")) Expect(pushPlans[1].DockerImageCredentials.Password).To(Equal("passwd")) Expect(pushPlans[1].BitsPath).To(Equal("path2")) + Expect(pushPlans[1].Application.LifecycleType).To(BeEquivalentTo("")) }) + }) + When("lifecycle is overwritten", func() { + BeforeEach(func() { + flagOverrides = FlagOverrides{ + Lifecycle: "buildpack", + } + }) + + It("uses the lifecycle from the command line", func() { + Expect(pushPlans[0].Application.LifecycleType).To(BeEquivalentTo("buildpack")) + }) }) + }) diff --git a/actor/v7pushaction/handle_cnb_credentials_override.go b/actor/v7pushaction/handle_cnb_credentials_override.go new file mode 100644 index 00000000000..8fa212aab4b --- /dev/null +++ b/actor/v7pushaction/handle_cnb_credentials_override.go @@ -0,0 +1,23 @@ +package v7pushaction + +import ( + "code.cloudfoundry.org/cli/command/translatableerror" + "code.cloudfoundry.org/cli/util/manifestparser" +) + +func HandleCNBCredentialsOverride(manifest manifestparser.Manifest, overrides FlagOverrides) (manifestparser.Manifest, error) { + if overrides.CNBCredentials != nil { + if manifest.ContainsMultipleApps() { + return manifest, translatableerror.CommandLineArgsWithMultipleAppsError{} + } + + app := manifest.GetFirstApp() + if app.RemainingManifestFields == nil { + app.RemainingManifestFields = map[string]interface{}{} + } + + app.RemainingManifestFields["cnb-credentials"] = overrides.CNBCredentials + } + + return manifest, nil +} diff --git a/actor/v7pushaction/handle_cnb_credentials_override_test.go b/actor/v7pushaction/handle_cnb_credentials_override_test.go new file mode 100644 index 00000000000..87a1117de08 --- /dev/null +++ b/actor/v7pushaction/handle_cnb_credentials_override_test.go @@ -0,0 +1,66 @@ +package v7pushaction_test + +import ( + . "code.cloudfoundry.org/cli/actor/v7pushaction" + "code.cloudfoundry.org/cli/util/manifestparser" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("HandleCNBCredentialsOverride", func() { + var ( + originalManifest manifestparser.Manifest + transformedManifest manifestparser.Manifest + overrides FlagOverrides + executeErr error + ) + + BeforeEach(func() { + originalManifest = manifestparser.Manifest{ + Applications: []manifestparser.Application{{}}, + } + overrides = FlagOverrides{} + }) + + JustBeforeEach(func() { + transformedManifest, executeErr = HandleCNBCredentialsOverride(originalManifest, overrides) + }) + + When("the cnb credentials are present", func() { + BeforeEach(func() { + overrides.CNBCredentials = map[string]interface{}{ + "foo": "bar", + } + }) + + It("add it to the raw manifest", func() { + Expect(executeErr).NotTo(HaveOccurred()) + Expect(transformedManifest).To(Equal(manifestparser.Manifest{ + Applications: []manifestparser.Application{{ + RemainingManifestFields: map[string]interface{}{ + "cnb-credentials": map[string]interface{}{ + "foo": "bar", + }, + }, + }}, + })) + }) + + }) + + When("the credentials are not present", func() { + BeforeEach(func() { + overrides.CNBCredentials = nil + }) + + It("does not add it to the raw manifest", func() { + Expect(executeErr).NotTo(HaveOccurred()) + Expect(transformedManifest).To(Equal(manifestparser.Manifest{ + Applications: []manifestparser.Application{{}}, + })) + + }) + + }) +}) diff --git a/actor/v7pushaction/handle_lifecycle_override.go b/actor/v7pushaction/handle_lifecycle_override.go new file mode 100644 index 00000000000..005aa659029 --- /dev/null +++ b/actor/v7pushaction/handle_lifecycle_override.go @@ -0,0 +1,19 @@ +package v7pushaction + +import ( + "code.cloudfoundry.org/cli/command/translatableerror" + "code.cloudfoundry.org/cli/util/manifestparser" +) + +func HandleLifecycleOverride(manifest manifestparser.Manifest, overrides FlagOverrides) (manifestparser.Manifest, error) { + if overrides.Lifecycle != "" { + if manifest.ContainsMultipleApps() { + return manifest, translatableerror.CommandLineArgsWithMultipleAppsError{} + } + + app := manifest.GetFirstApp() + app.Lifecycle = overrides.Lifecycle + } + + return manifest, nil +} diff --git a/actor/v7pushaction/push_plan.go b/actor/v7pushaction/push_plan.go index 876a8ec2259..dc4a181e2b2 100644 --- a/actor/v7pushaction/push_plan.go +++ b/actor/v7pushaction/push_plan.go @@ -43,6 +43,7 @@ type FlagOverrides struct { DockerImage string DockerPassword string DockerUsername string + CNBCredentials map[string]interface{} HealthCheckEndpoint string HealthCheckTimeout int64 HealthCheckType constant.HealthCheckType @@ -62,6 +63,7 @@ type FlagOverrides struct { NoManifest bool Task bool LogRateLimit string + Lifecycle constant.AppLifecycleType } func (state PushPlan) String() string { diff --git a/api/cloudcontroller/ccv3/application_test.go b/api/cloudcontroller/ccv3/application_test.go index 467c8548722..46002b20b09 100644 --- a/api/cloudcontroller/ccv3/application_test.go +++ b/api/cloudcontroller/ccv3/application_test.go @@ -96,6 +96,17 @@ var _ = Describe("Application", func() { }) }) + When("lifecycle type cnb is provided", func() { + BeforeEach(func() { + app.LifecycleType = constant.AppLifecycleTypeCNB + app.LifecycleBuildpacks = []string{"docker://nodejs"} + }) + + It("sets the lifecycle buildpack to be empty in the JSON", func() { + Expect(string(appBytes)).To(MatchJSON(`{"lifecycle":{"data":{"buildpacks":["docker://nodejs"]},"type":"cnb"}}`)) + }) + }) + When("null buildpack is provided", func() { BeforeEach(func() { app.LifecycleBuildpacks = []string{"null"} diff --git a/api/cloudcontroller/ccv3/constant/application.go b/api/cloudcontroller/ccv3/constant/application.go index b0acd644dc0..dca0b70af39 100644 --- a/api/cloudcontroller/ccv3/constant/application.go +++ b/api/cloudcontroller/ccv3/constant/application.go @@ -9,6 +9,9 @@ const ( // AppLifecycleTypeDocker will pull a docker image from a registry to run an // app. AppLifecycleTypeDocker AppLifecycleType = "docker" + // AppLifecycleTypeCNB will use a droplet (created with cloud native buildpacks) + // and a rootfs to run the app. + AppLifecycleTypeCNB AppLifecycleType = "cnb" ) // ApplicationAction represents the action being taken on an application diff --git a/cf/commands/application/apps.go b/cf/commands/application/apps.go index d77b38fff28..e246f9ff09b 100644 --- a/cf/commands/application/apps.go +++ b/cf/commands/application/apps.go @@ -7,7 +7,7 @@ import ( "code.cloudfoundry.org/cli/cf/flags" . "code.cloudfoundry.org/cli/cf/i18n" "code.cloudfoundry.org/cli/cf/models" - "code.cloudfoundry.org/cli/plugin/models" + plugin_models "code.cloudfoundry.org/cli/plugin/models" "code.cloudfoundry.org/cli/cf/api" "code.cloudfoundry.org/cli/cf/configuration/coreconfig" diff --git a/command/commandfakes/fake_config.go b/command/commandfakes/fake_config.go index 4e94d9f543c..2b7f1fe4014 100644 --- a/command/commandfakes/fake_config.go +++ b/command/commandfakes/fake_config.go @@ -91,6 +91,18 @@ type FakeConfig struct { cFUsernameReturnsOnCall map[int]struct { result1 string } + CNBCredentialsStub func() (map[string]interface{}, error) + cNBCredentialsMutex sync.RWMutex + cNBCredentialsArgsForCall []struct { + } + cNBCredentialsReturns struct { + result1 map[string]interface{} + result2 error + } + cNBCredentialsReturnsOnCall map[int]struct { + result1 map[string]interface{} + result2 error + } ColorEnabledStub func() configv3.ColorSetting colorEnabledMutex sync.RWMutex colorEnabledArgsForCall []struct { @@ -636,15 +648,16 @@ func (fake *FakeConfig) APIVersion() string { ret, specificReturn := fake.aPIVersionReturnsOnCall[len(fake.aPIVersionArgsForCall)] fake.aPIVersionArgsForCall = append(fake.aPIVersionArgsForCall, struct { }{}) + stub := fake.APIVersionStub + fakeReturns := fake.aPIVersionReturns fake.recordInvocation("APIVersion", []interface{}{}) fake.aPIVersionMutex.Unlock() - if fake.APIVersionStub != nil { - return fake.APIVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.aPIVersionReturns return fakeReturns.result1 } @@ -688,15 +701,16 @@ func (fake *FakeConfig) AccessToken() string { ret, specificReturn := fake.accessTokenReturnsOnCall[len(fake.accessTokenArgsForCall)] fake.accessTokenArgsForCall = append(fake.accessTokenArgsForCall, struct { }{}) + stub := fake.AccessTokenStub + fakeReturns := fake.accessTokenReturns fake.recordInvocation("AccessToken", []interface{}{}) fake.accessTokenMutex.Unlock() - if fake.AccessTokenStub != nil { - return fake.AccessTokenStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.accessTokenReturns return fakeReturns.result1 } @@ -740,9 +754,10 @@ func (fake *FakeConfig) AddPlugin(arg1 configv3.Plugin) { fake.addPluginArgsForCall = append(fake.addPluginArgsForCall, struct { arg1 configv3.Plugin }{arg1}) + stub := fake.AddPluginStub fake.recordInvocation("AddPlugin", []interface{}{arg1}) fake.addPluginMutex.Unlock() - if fake.AddPluginStub != nil { + if stub != nil { fake.AddPluginStub(arg1) } } @@ -772,9 +787,10 @@ func (fake *FakeConfig) AddPluginRepository(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.AddPluginRepositoryStub fake.recordInvocation("AddPluginRepository", []interface{}{arg1, arg2}) fake.addPluginRepositoryMutex.Unlock() - if fake.AddPluginRepositoryStub != nil { + if stub != nil { fake.AddPluginRepositoryStub(arg1, arg2) } } @@ -803,15 +819,16 @@ func (fake *FakeConfig) AuthorizationEndpoint() string { ret, specificReturn := fake.authorizationEndpointReturnsOnCall[len(fake.authorizationEndpointArgsForCall)] fake.authorizationEndpointArgsForCall = append(fake.authorizationEndpointArgsForCall, struct { }{}) + stub := fake.AuthorizationEndpointStub + fakeReturns := fake.authorizationEndpointReturns fake.recordInvocation("AuthorizationEndpoint", []interface{}{}) fake.authorizationEndpointMutex.Unlock() - if fake.AuthorizationEndpointStub != nil { - return fake.AuthorizationEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.authorizationEndpointReturns return fakeReturns.result1 } @@ -855,15 +872,16 @@ func (fake *FakeConfig) BinaryName() string { ret, specificReturn := fake.binaryNameReturnsOnCall[len(fake.binaryNameArgsForCall)] fake.binaryNameArgsForCall = append(fake.binaryNameArgsForCall, struct { }{}) + stub := fake.BinaryNameStub + fakeReturns := fake.binaryNameReturns fake.recordInvocation("BinaryName", []interface{}{}) fake.binaryNameMutex.Unlock() - if fake.BinaryNameStub != nil { - return fake.BinaryNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.binaryNameReturns return fakeReturns.result1 } @@ -907,15 +925,16 @@ func (fake *FakeConfig) BinaryVersion() string { ret, specificReturn := fake.binaryVersionReturnsOnCall[len(fake.binaryVersionArgsForCall)] fake.binaryVersionArgsForCall = append(fake.binaryVersionArgsForCall, struct { }{}) + stub := fake.BinaryVersionStub + fakeReturns := fake.binaryVersionReturns fake.recordInvocation("BinaryVersion", []interface{}{}) fake.binaryVersionMutex.Unlock() - if fake.BinaryVersionStub != nil { - return fake.BinaryVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.binaryVersionReturns return fakeReturns.result1 } @@ -959,15 +978,16 @@ func (fake *FakeConfig) CFPassword() string { ret, specificReturn := fake.cFPasswordReturnsOnCall[len(fake.cFPasswordArgsForCall)] fake.cFPasswordArgsForCall = append(fake.cFPasswordArgsForCall, struct { }{}) + stub := fake.CFPasswordStub + fakeReturns := fake.cFPasswordReturns fake.recordInvocation("CFPassword", []interface{}{}) fake.cFPasswordMutex.Unlock() - if fake.CFPasswordStub != nil { - return fake.CFPasswordStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.cFPasswordReturns return fakeReturns.result1 } @@ -1011,15 +1031,16 @@ func (fake *FakeConfig) CFUsername() string { ret, specificReturn := fake.cFUsernameReturnsOnCall[len(fake.cFUsernameArgsForCall)] fake.cFUsernameArgsForCall = append(fake.cFUsernameArgsForCall, struct { }{}) + stub := fake.CFUsernameStub + fakeReturns := fake.cFUsernameReturns fake.recordInvocation("CFUsername", []interface{}{}) fake.cFUsernameMutex.Unlock() - if fake.CFUsernameStub != nil { - return fake.CFUsernameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.cFUsernameReturns return fakeReturns.result1 } @@ -1058,20 +1079,77 @@ func (fake *FakeConfig) CFUsernameReturnsOnCall(i int, result1 string) { }{result1} } +func (fake *FakeConfig) CNBCredentials() (map[string]interface{}, error) { + fake.cNBCredentialsMutex.Lock() + ret, specificReturn := fake.cNBCredentialsReturnsOnCall[len(fake.cNBCredentialsArgsForCall)] + fake.cNBCredentialsArgsForCall = append(fake.cNBCredentialsArgsForCall, struct { + }{}) + stub := fake.CNBCredentialsStub + fakeReturns := fake.cNBCredentialsReturns + fake.recordInvocation("CNBCredentials", []interface{}{}) + fake.cNBCredentialsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeConfig) CNBCredentialsCallCount() int { + fake.cNBCredentialsMutex.RLock() + defer fake.cNBCredentialsMutex.RUnlock() + return len(fake.cNBCredentialsArgsForCall) +} + +func (fake *FakeConfig) CNBCredentialsCalls(stub func() (map[string]interface{}, error)) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = stub +} + +func (fake *FakeConfig) CNBCredentialsReturns(result1 map[string]interface{}, result2 error) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = nil + fake.cNBCredentialsReturns = struct { + result1 map[string]interface{} + result2 error + }{result1, result2} +} + +func (fake *FakeConfig) CNBCredentialsReturnsOnCall(i int, result1 map[string]interface{}, result2 error) { + fake.cNBCredentialsMutex.Lock() + defer fake.cNBCredentialsMutex.Unlock() + fake.CNBCredentialsStub = nil + if fake.cNBCredentialsReturnsOnCall == nil { + fake.cNBCredentialsReturnsOnCall = make(map[int]struct { + result1 map[string]interface{} + result2 error + }) + } + fake.cNBCredentialsReturnsOnCall[i] = struct { + result1 map[string]interface{} + result2 error + }{result1, result2} +} + func (fake *FakeConfig) ColorEnabled() configv3.ColorSetting { fake.colorEnabledMutex.Lock() ret, specificReturn := fake.colorEnabledReturnsOnCall[len(fake.colorEnabledArgsForCall)] fake.colorEnabledArgsForCall = append(fake.colorEnabledArgsForCall, struct { }{}) + stub := fake.ColorEnabledStub + fakeReturns := fake.colorEnabledReturns fake.recordInvocation("ColorEnabled", []interface{}{}) fake.colorEnabledMutex.Unlock() - if fake.ColorEnabledStub != nil { - return fake.ColorEnabledStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.colorEnabledReturns return fakeReturns.result1 } @@ -1115,15 +1193,16 @@ func (fake *FakeConfig) CurrentUser() (configv3.User, error) { ret, specificReturn := fake.currentUserReturnsOnCall[len(fake.currentUserArgsForCall)] fake.currentUserArgsForCall = append(fake.currentUserArgsForCall, struct { }{}) + stub := fake.CurrentUserStub + fakeReturns := fake.currentUserReturns fake.recordInvocation("CurrentUser", []interface{}{}) fake.currentUserMutex.Unlock() - if fake.CurrentUserStub != nil { - return fake.CurrentUserStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.currentUserReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1170,15 +1249,16 @@ func (fake *FakeConfig) CurrentUserName() (string, error) { ret, specificReturn := fake.currentUserNameReturnsOnCall[len(fake.currentUserNameArgsForCall)] fake.currentUserNameArgsForCall = append(fake.currentUserNameArgsForCall, struct { }{}) + stub := fake.CurrentUserNameStub + fakeReturns := fake.currentUserNameReturns fake.recordInvocation("CurrentUserName", []interface{}{}) fake.currentUserNameMutex.Unlock() - if fake.CurrentUserNameStub != nil { - return fake.CurrentUserNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.currentUserNameReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1225,15 +1305,16 @@ func (fake *FakeConfig) DialTimeout() time.Duration { ret, specificReturn := fake.dialTimeoutReturnsOnCall[len(fake.dialTimeoutArgsForCall)] fake.dialTimeoutArgsForCall = append(fake.dialTimeoutArgsForCall, struct { }{}) + stub := fake.DialTimeoutStub + fakeReturns := fake.dialTimeoutReturns fake.recordInvocation("DialTimeout", []interface{}{}) fake.dialTimeoutMutex.Unlock() - if fake.DialTimeoutStub != nil { - return fake.DialTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.dialTimeoutReturns return fakeReturns.result1 } @@ -1277,15 +1358,16 @@ func (fake *FakeConfig) DockerPassword() string { ret, specificReturn := fake.dockerPasswordReturnsOnCall[len(fake.dockerPasswordArgsForCall)] fake.dockerPasswordArgsForCall = append(fake.dockerPasswordArgsForCall, struct { }{}) + stub := fake.DockerPasswordStub + fakeReturns := fake.dockerPasswordReturns fake.recordInvocation("DockerPassword", []interface{}{}) fake.dockerPasswordMutex.Unlock() - if fake.DockerPasswordStub != nil { - return fake.DockerPasswordStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.dockerPasswordReturns return fakeReturns.result1 } @@ -1329,15 +1411,16 @@ func (fake *FakeConfig) Experimental() bool { ret, specificReturn := fake.experimentalReturnsOnCall[len(fake.experimentalArgsForCall)] fake.experimentalArgsForCall = append(fake.experimentalArgsForCall, struct { }{}) + stub := fake.ExperimentalStub + fakeReturns := fake.experimentalReturns fake.recordInvocation("Experimental", []interface{}{}) fake.experimentalMutex.Unlock() - if fake.ExperimentalStub != nil { - return fake.ExperimentalStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.experimentalReturns return fakeReturns.result1 } @@ -1382,15 +1465,16 @@ func (fake *FakeConfig) GetPlugin(arg1 string) (configv3.Plugin, bool) { fake.getPluginArgsForCall = append(fake.getPluginArgsForCall, struct { arg1 string }{arg1}) + stub := fake.GetPluginStub + fakeReturns := fake.getPluginReturns fake.recordInvocation("GetPlugin", []interface{}{arg1}) fake.getPluginMutex.Unlock() - if fake.GetPluginStub != nil { - return fake.GetPluginStub(arg1) + if stub != nil { + return stub(arg1) } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.getPluginReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1445,15 +1529,16 @@ func (fake *FakeConfig) GetPluginCaseInsensitive(arg1 string) (configv3.Plugin, fake.getPluginCaseInsensitiveArgsForCall = append(fake.getPluginCaseInsensitiveArgsForCall, struct { arg1 string }{arg1}) + stub := fake.GetPluginCaseInsensitiveStub + fakeReturns := fake.getPluginCaseInsensitiveReturns fake.recordInvocation("GetPluginCaseInsensitive", []interface{}{arg1}) fake.getPluginCaseInsensitiveMutex.Unlock() - if fake.GetPluginCaseInsensitiveStub != nil { - return fake.GetPluginCaseInsensitiveStub(arg1) + if stub != nil { + return stub(arg1) } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.getPluginCaseInsensitiveReturns return fakeReturns.result1, fakeReturns.result2 } @@ -1507,15 +1592,16 @@ func (fake *FakeConfig) HasTargetedOrganization() bool { ret, specificReturn := fake.hasTargetedOrganizationReturnsOnCall[len(fake.hasTargetedOrganizationArgsForCall)] fake.hasTargetedOrganizationArgsForCall = append(fake.hasTargetedOrganizationArgsForCall, struct { }{}) + stub := fake.HasTargetedOrganizationStub + fakeReturns := fake.hasTargetedOrganizationReturns fake.recordInvocation("HasTargetedOrganization", []interface{}{}) fake.hasTargetedOrganizationMutex.Unlock() - if fake.HasTargetedOrganizationStub != nil { - return fake.HasTargetedOrganizationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.hasTargetedOrganizationReturns return fakeReturns.result1 } @@ -1559,15 +1645,16 @@ func (fake *FakeConfig) HasTargetedSpace() bool { ret, specificReturn := fake.hasTargetedSpaceReturnsOnCall[len(fake.hasTargetedSpaceArgsForCall)] fake.hasTargetedSpaceArgsForCall = append(fake.hasTargetedSpaceArgsForCall, struct { }{}) + stub := fake.HasTargetedSpaceStub + fakeReturns := fake.hasTargetedSpaceReturns fake.recordInvocation("HasTargetedSpace", []interface{}{}) fake.hasTargetedSpaceMutex.Unlock() - if fake.HasTargetedSpaceStub != nil { - return fake.HasTargetedSpaceStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.hasTargetedSpaceReturns return fakeReturns.result1 } @@ -1611,15 +1698,16 @@ func (fake *FakeConfig) IsCFOnK8s() bool { ret, specificReturn := fake.isCFOnK8sReturnsOnCall[len(fake.isCFOnK8sArgsForCall)] fake.isCFOnK8sArgsForCall = append(fake.isCFOnK8sArgsForCall, struct { }{}) + stub := fake.IsCFOnK8sStub + fakeReturns := fake.isCFOnK8sReturns fake.recordInvocation("IsCFOnK8s", []interface{}{}) fake.isCFOnK8sMutex.Unlock() - if fake.IsCFOnK8sStub != nil { - return fake.IsCFOnK8sStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.isCFOnK8sReturns return fakeReturns.result1 } @@ -1663,15 +1751,16 @@ func (fake *FakeConfig) IsTTY() bool { ret, specificReturn := fake.isTTYReturnsOnCall[len(fake.isTTYArgsForCall)] fake.isTTYArgsForCall = append(fake.isTTYArgsForCall, struct { }{}) + stub := fake.IsTTYStub + fakeReturns := fake.isTTYReturns fake.recordInvocation("IsTTY", []interface{}{}) fake.isTTYMutex.Unlock() - if fake.IsTTYStub != nil { - return fake.IsTTYStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.isTTYReturns return fakeReturns.result1 } @@ -1715,15 +1804,16 @@ func (fake *FakeConfig) Locale() string { ret, specificReturn := fake.localeReturnsOnCall[len(fake.localeArgsForCall)] fake.localeArgsForCall = append(fake.localeArgsForCall, struct { }{}) + stub := fake.LocaleStub + fakeReturns := fake.localeReturns fake.recordInvocation("Locale", []interface{}{}) fake.localeMutex.Unlock() - if fake.LocaleStub != nil { - return fake.LocaleStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.localeReturns return fakeReturns.result1 } @@ -1767,15 +1857,16 @@ func (fake *FakeConfig) LogCacheEndpoint() string { ret, specificReturn := fake.logCacheEndpointReturnsOnCall[len(fake.logCacheEndpointArgsForCall)] fake.logCacheEndpointArgsForCall = append(fake.logCacheEndpointArgsForCall, struct { }{}) + stub := fake.LogCacheEndpointStub + fakeReturns := fake.logCacheEndpointReturns fake.recordInvocation("LogCacheEndpoint", []interface{}{}) fake.logCacheEndpointMutex.Unlock() - if fake.LogCacheEndpointStub != nil { - return fake.LogCacheEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.logCacheEndpointReturns return fakeReturns.result1 } @@ -1819,15 +1910,16 @@ func (fake *FakeConfig) MinCLIVersion() string { ret, specificReturn := fake.minCLIVersionReturnsOnCall[len(fake.minCLIVersionArgsForCall)] fake.minCLIVersionArgsForCall = append(fake.minCLIVersionArgsForCall, struct { }{}) + stub := fake.MinCLIVersionStub + fakeReturns := fake.minCLIVersionReturns fake.recordInvocation("MinCLIVersion", []interface{}{}) fake.minCLIVersionMutex.Unlock() - if fake.MinCLIVersionStub != nil { - return fake.MinCLIVersionStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.minCLIVersionReturns return fakeReturns.result1 } @@ -1871,15 +1963,16 @@ func (fake *FakeConfig) NOAARequestRetryCount() int { ret, specificReturn := fake.nOAARequestRetryCountReturnsOnCall[len(fake.nOAARequestRetryCountArgsForCall)] fake.nOAARequestRetryCountArgsForCall = append(fake.nOAARequestRetryCountArgsForCall, struct { }{}) + stub := fake.NOAARequestRetryCountStub + fakeReturns := fake.nOAARequestRetryCountReturns fake.recordInvocation("NOAARequestRetryCount", []interface{}{}) fake.nOAARequestRetryCountMutex.Unlock() - if fake.NOAARequestRetryCountStub != nil { - return fake.NOAARequestRetryCountStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.nOAARequestRetryCountReturns return fakeReturns.result1 } @@ -1923,15 +2016,16 @@ func (fake *FakeConfig) NetworkPolicyV1Endpoint() string { ret, specificReturn := fake.networkPolicyV1EndpointReturnsOnCall[len(fake.networkPolicyV1EndpointArgsForCall)] fake.networkPolicyV1EndpointArgsForCall = append(fake.networkPolicyV1EndpointArgsForCall, struct { }{}) + stub := fake.NetworkPolicyV1EndpointStub + fakeReturns := fake.networkPolicyV1EndpointReturns fake.recordInvocation("NetworkPolicyV1Endpoint", []interface{}{}) fake.networkPolicyV1EndpointMutex.Unlock() - if fake.NetworkPolicyV1EndpointStub != nil { - return fake.NetworkPolicyV1EndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.networkPolicyV1EndpointReturns return fakeReturns.result1 } @@ -1975,15 +2069,16 @@ func (fake *FakeConfig) OverallPollingTimeout() time.Duration { ret, specificReturn := fake.overallPollingTimeoutReturnsOnCall[len(fake.overallPollingTimeoutArgsForCall)] fake.overallPollingTimeoutArgsForCall = append(fake.overallPollingTimeoutArgsForCall, struct { }{}) + stub := fake.OverallPollingTimeoutStub + fakeReturns := fake.overallPollingTimeoutReturns fake.recordInvocation("OverallPollingTimeout", []interface{}{}) fake.overallPollingTimeoutMutex.Unlock() - if fake.OverallPollingTimeoutStub != nil { - return fake.OverallPollingTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.overallPollingTimeoutReturns return fakeReturns.result1 } @@ -2027,15 +2122,16 @@ func (fake *FakeConfig) PluginHome() string { ret, specificReturn := fake.pluginHomeReturnsOnCall[len(fake.pluginHomeArgsForCall)] fake.pluginHomeArgsForCall = append(fake.pluginHomeArgsForCall, struct { }{}) + stub := fake.PluginHomeStub + fakeReturns := fake.pluginHomeReturns fake.recordInvocation("PluginHome", []interface{}{}) fake.pluginHomeMutex.Unlock() - if fake.PluginHomeStub != nil { - return fake.PluginHomeStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginHomeReturns return fakeReturns.result1 } @@ -2079,15 +2175,16 @@ func (fake *FakeConfig) PluginRepositories() []configv3.PluginRepository { ret, specificReturn := fake.pluginRepositoriesReturnsOnCall[len(fake.pluginRepositoriesArgsForCall)] fake.pluginRepositoriesArgsForCall = append(fake.pluginRepositoriesArgsForCall, struct { }{}) + stub := fake.PluginRepositoriesStub + fakeReturns := fake.pluginRepositoriesReturns fake.recordInvocation("PluginRepositories", []interface{}{}) fake.pluginRepositoriesMutex.Unlock() - if fake.PluginRepositoriesStub != nil { - return fake.PluginRepositoriesStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginRepositoriesReturns return fakeReturns.result1 } @@ -2131,15 +2228,16 @@ func (fake *FakeConfig) Plugins() []configv3.Plugin { ret, specificReturn := fake.pluginsReturnsOnCall[len(fake.pluginsArgsForCall)] fake.pluginsArgsForCall = append(fake.pluginsArgsForCall, struct { }{}) + stub := fake.PluginsStub + fakeReturns := fake.pluginsReturns fake.recordInvocation("Plugins", []interface{}{}) fake.pluginsMutex.Unlock() - if fake.PluginsStub != nil { - return fake.PluginsStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pluginsReturns return fakeReturns.result1 } @@ -2183,15 +2281,16 @@ func (fake *FakeConfig) PollingInterval() time.Duration { ret, specificReturn := fake.pollingIntervalReturnsOnCall[len(fake.pollingIntervalArgsForCall)] fake.pollingIntervalArgsForCall = append(fake.pollingIntervalArgsForCall, struct { }{}) + stub := fake.PollingIntervalStub + fakeReturns := fake.pollingIntervalReturns fake.recordInvocation("PollingInterval", []interface{}{}) fake.pollingIntervalMutex.Unlock() - if fake.PollingIntervalStub != nil { - return fake.PollingIntervalStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.pollingIntervalReturns return fakeReturns.result1 } @@ -2235,15 +2334,16 @@ func (fake *FakeConfig) RefreshToken() string { ret, specificReturn := fake.refreshTokenReturnsOnCall[len(fake.refreshTokenArgsForCall)] fake.refreshTokenArgsForCall = append(fake.refreshTokenArgsForCall, struct { }{}) + stub := fake.RefreshTokenStub + fakeReturns := fake.refreshTokenReturns fake.recordInvocation("RefreshToken", []interface{}{}) fake.refreshTokenMutex.Unlock() - if fake.RefreshTokenStub != nil { - return fake.RefreshTokenStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.refreshTokenReturns return fakeReturns.result1 } @@ -2287,9 +2387,10 @@ func (fake *FakeConfig) RemovePlugin(arg1 string) { fake.removePluginArgsForCall = append(fake.removePluginArgsForCall, struct { arg1 string }{arg1}) + stub := fake.RemovePluginStub fake.recordInvocation("RemovePlugin", []interface{}{arg1}) fake.removePluginMutex.Unlock() - if fake.RemovePluginStub != nil { + if stub != nil { fake.RemovePluginStub(arg1) } } @@ -2318,15 +2419,16 @@ func (fake *FakeConfig) RequestRetryCount() int { ret, specificReturn := fake.requestRetryCountReturnsOnCall[len(fake.requestRetryCountArgsForCall)] fake.requestRetryCountArgsForCall = append(fake.requestRetryCountArgsForCall, struct { }{}) + stub := fake.RequestRetryCountStub + fakeReturns := fake.requestRetryCountReturns fake.recordInvocation("RequestRetryCount", []interface{}{}) fake.requestRetryCountMutex.Unlock() - if fake.RequestRetryCountStub != nil { - return fake.RequestRetryCountStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.requestRetryCountReturns return fakeReturns.result1 } @@ -2370,15 +2472,16 @@ func (fake *FakeConfig) RoutingEndpoint() string { ret, specificReturn := fake.routingEndpointReturnsOnCall[len(fake.routingEndpointArgsForCall)] fake.routingEndpointArgsForCall = append(fake.routingEndpointArgsForCall, struct { }{}) + stub := fake.RoutingEndpointStub + fakeReturns := fake.routingEndpointReturns fake.recordInvocation("RoutingEndpoint", []interface{}{}) fake.routingEndpointMutex.Unlock() - if fake.RoutingEndpointStub != nil { - return fake.RoutingEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.routingEndpointReturns return fakeReturns.result1 } @@ -2422,15 +2525,16 @@ func (fake *FakeConfig) SSHOAuthClient() string { ret, specificReturn := fake.sSHOAuthClientReturnsOnCall[len(fake.sSHOAuthClientArgsForCall)] fake.sSHOAuthClientArgsForCall = append(fake.sSHOAuthClientArgsForCall, struct { }{}) + stub := fake.SSHOAuthClientStub + fakeReturns := fake.sSHOAuthClientReturns fake.recordInvocation("SSHOAuthClient", []interface{}{}) fake.sSHOAuthClientMutex.Unlock() - if fake.SSHOAuthClientStub != nil { - return fake.SSHOAuthClientStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.sSHOAuthClientReturns return fakeReturns.result1 } @@ -2474,9 +2578,10 @@ func (fake *FakeConfig) SetAccessToken(arg1 string) { fake.setAccessTokenArgsForCall = append(fake.setAccessTokenArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetAccessTokenStub fake.recordInvocation("SetAccessToken", []interface{}{arg1}) fake.setAccessTokenMutex.Unlock() - if fake.SetAccessTokenStub != nil { + if stub != nil { fake.SetAccessTokenStub(arg1) } } @@ -2505,9 +2610,10 @@ func (fake *FakeConfig) SetAsyncTimeout(arg1 int) { fake.setAsyncTimeoutArgsForCall = append(fake.setAsyncTimeoutArgsForCall, struct { arg1 int }{arg1}) + stub := fake.SetAsyncTimeoutStub fake.recordInvocation("SetAsyncTimeout", []interface{}{arg1}) fake.setAsyncTimeoutMutex.Unlock() - if fake.SetAsyncTimeoutStub != nil { + if stub != nil { fake.SetAsyncTimeoutStub(arg1) } } @@ -2536,9 +2642,10 @@ func (fake *FakeConfig) SetColorEnabled(arg1 string) { fake.setColorEnabledArgsForCall = append(fake.setColorEnabledArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetColorEnabledStub fake.recordInvocation("SetColorEnabled", []interface{}{arg1}) fake.setColorEnabledMutex.Unlock() - if fake.SetColorEnabledStub != nil { + if stub != nil { fake.SetColorEnabledStub(arg1) } } @@ -2567,9 +2674,10 @@ func (fake *FakeConfig) SetKubernetesAuthInfo(arg1 string) { fake.setKubernetesAuthInfoArgsForCall = append(fake.setKubernetesAuthInfoArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetKubernetesAuthInfoStub fake.recordInvocation("SetKubernetesAuthInfo", []interface{}{arg1}) fake.setKubernetesAuthInfoMutex.Unlock() - if fake.SetKubernetesAuthInfoStub != nil { + if stub != nil { fake.SetKubernetesAuthInfoStub(arg1) } } @@ -2598,9 +2706,10 @@ func (fake *FakeConfig) SetLocale(arg1 string) { fake.setLocaleArgsForCall = append(fake.setLocaleArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetLocaleStub fake.recordInvocation("SetLocale", []interface{}{arg1}) fake.setLocaleMutex.Unlock() - if fake.SetLocaleStub != nil { + if stub != nil { fake.SetLocaleStub(arg1) } } @@ -2629,9 +2738,10 @@ func (fake *FakeConfig) SetMinCLIVersion(arg1 string) { fake.setMinCLIVersionArgsForCall = append(fake.setMinCLIVersionArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetMinCLIVersionStub fake.recordInvocation("SetMinCLIVersion", []interface{}{arg1}) fake.setMinCLIVersionMutex.Unlock() - if fake.SetMinCLIVersionStub != nil { + if stub != nil { fake.SetMinCLIVersionStub(arg1) } } @@ -2661,9 +2771,10 @@ func (fake *FakeConfig) SetOrganizationInformation(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.SetOrganizationInformationStub fake.recordInvocation("SetOrganizationInformation", []interface{}{arg1, arg2}) fake.setOrganizationInformationMutex.Unlock() - if fake.SetOrganizationInformationStub != nil { + if stub != nil { fake.SetOrganizationInformationStub(arg1, arg2) } } @@ -2692,9 +2803,10 @@ func (fake *FakeConfig) SetRefreshToken(arg1 string) { fake.setRefreshTokenArgsForCall = append(fake.setRefreshTokenArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetRefreshTokenStub fake.recordInvocation("SetRefreshToken", []interface{}{arg1}) fake.setRefreshTokenMutex.Unlock() - if fake.SetRefreshTokenStub != nil { + if stub != nil { fake.SetRefreshTokenStub(arg1) } } @@ -2725,9 +2837,10 @@ func (fake *FakeConfig) SetSpaceInformation(arg1 string, arg2 string, arg3 bool) arg2 string arg3 bool }{arg1, arg2, arg3}) + stub := fake.SetSpaceInformationStub fake.recordInvocation("SetSpaceInformation", []interface{}{arg1, arg2, arg3}) fake.setSpaceInformationMutex.Unlock() - if fake.SetSpaceInformationStub != nil { + if stub != nil { fake.SetSpaceInformationStub(arg1, arg2, arg3) } } @@ -2756,9 +2869,10 @@ func (fake *FakeConfig) SetTargetInformation(arg1 configv3.TargetInformationArgs fake.setTargetInformationArgsForCall = append(fake.setTargetInformationArgsForCall, struct { arg1 configv3.TargetInformationArgs }{arg1}) + stub := fake.SetTargetInformationStub fake.recordInvocation("SetTargetInformation", []interface{}{arg1}) fake.setTargetInformationMutex.Unlock() - if fake.SetTargetInformationStub != nil { + if stub != nil { fake.SetTargetInformationStub(arg1) } } @@ -2789,9 +2903,10 @@ func (fake *FakeConfig) SetTokenInformation(arg1 string, arg2 string, arg3 strin arg2 string arg3 string }{arg1, arg2, arg3}) + stub := fake.SetTokenInformationStub fake.recordInvocation("SetTokenInformation", []interface{}{arg1, arg2, arg3}) fake.setTokenInformationMutex.Unlock() - if fake.SetTokenInformationStub != nil { + if stub != nil { fake.SetTokenInformationStub(arg1, arg2, arg3) } } @@ -2820,9 +2935,10 @@ func (fake *FakeConfig) SetTrace(arg1 string) { fake.setTraceArgsForCall = append(fake.setTraceArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetTraceStub fake.recordInvocation("SetTrace", []interface{}{arg1}) fake.setTraceMutex.Unlock() - if fake.SetTraceStub != nil { + if stub != nil { fake.SetTraceStub(arg1) } } @@ -2852,9 +2968,10 @@ func (fake *FakeConfig) SetUAAClientCredentials(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.SetUAAClientCredentialsStub fake.recordInvocation("SetUAAClientCredentials", []interface{}{arg1, arg2}) fake.setUAAClientCredentialsMutex.Unlock() - if fake.SetUAAClientCredentialsStub != nil { + if stub != nil { fake.SetUAAClientCredentialsStub(arg1, arg2) } } @@ -2883,9 +3000,10 @@ func (fake *FakeConfig) SetUAAEndpoint(arg1 string) { fake.setUAAEndpointArgsForCall = append(fake.setUAAEndpointArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetUAAEndpointStub fake.recordInvocation("SetUAAEndpoint", []interface{}{arg1}) fake.setUAAEndpointMutex.Unlock() - if fake.SetUAAEndpointStub != nil { + if stub != nil { fake.SetUAAEndpointStub(arg1) } } @@ -2914,9 +3032,10 @@ func (fake *FakeConfig) SetUAAGrantType(arg1 string) { fake.setUAAGrantTypeArgsForCall = append(fake.setUAAGrantTypeArgsForCall, struct { arg1 string }{arg1}) + stub := fake.SetUAAGrantTypeStub fake.recordInvocation("SetUAAGrantType", []interface{}{arg1}) fake.setUAAGrantTypeMutex.Unlock() - if fake.SetUAAGrantTypeStub != nil { + if stub != nil { fake.SetUAAGrantTypeStub(arg1) } } @@ -2945,15 +3064,16 @@ func (fake *FakeConfig) SkipSSLValidation() bool { ret, specificReturn := fake.skipSSLValidationReturnsOnCall[len(fake.skipSSLValidationArgsForCall)] fake.skipSSLValidationArgsForCall = append(fake.skipSSLValidationArgsForCall, struct { }{}) + stub := fake.SkipSSLValidationStub + fakeReturns := fake.skipSSLValidationReturns fake.recordInvocation("SkipSSLValidation", []interface{}{}) fake.skipSSLValidationMutex.Unlock() - if fake.SkipSSLValidationStub != nil { - return fake.SkipSSLValidationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.skipSSLValidationReturns return fakeReturns.result1 } @@ -2997,15 +3117,16 @@ func (fake *FakeConfig) StagingTimeout() time.Duration { ret, specificReturn := fake.stagingTimeoutReturnsOnCall[len(fake.stagingTimeoutArgsForCall)] fake.stagingTimeoutArgsForCall = append(fake.stagingTimeoutArgsForCall, struct { }{}) + stub := fake.StagingTimeoutStub + fakeReturns := fake.stagingTimeoutReturns fake.recordInvocation("StagingTimeout", []interface{}{}) fake.stagingTimeoutMutex.Unlock() - if fake.StagingTimeoutStub != nil { - return fake.StagingTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.stagingTimeoutReturns return fakeReturns.result1 } @@ -3049,15 +3170,16 @@ func (fake *FakeConfig) StartupTimeout() time.Duration { ret, specificReturn := fake.startupTimeoutReturnsOnCall[len(fake.startupTimeoutArgsForCall)] fake.startupTimeoutArgsForCall = append(fake.startupTimeoutArgsForCall, struct { }{}) + stub := fake.StartupTimeoutStub + fakeReturns := fake.startupTimeoutReturns fake.recordInvocation("StartupTimeout", []interface{}{}) fake.startupTimeoutMutex.Unlock() - if fake.StartupTimeoutStub != nil { - return fake.StartupTimeoutStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.startupTimeoutReturns return fakeReturns.result1 } @@ -3101,15 +3223,16 @@ func (fake *FakeConfig) Target() string { ret, specificReturn := fake.targetReturnsOnCall[len(fake.targetArgsForCall)] fake.targetArgsForCall = append(fake.targetArgsForCall, struct { }{}) + stub := fake.TargetStub + fakeReturns := fake.targetReturns fake.recordInvocation("Target", []interface{}{}) fake.targetMutex.Unlock() - if fake.TargetStub != nil { - return fake.TargetStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetReturns return fakeReturns.result1 } @@ -3153,15 +3276,16 @@ func (fake *FakeConfig) TargetedOrganization() configv3.Organization { ret, specificReturn := fake.targetedOrganizationReturnsOnCall[len(fake.targetedOrganizationArgsForCall)] fake.targetedOrganizationArgsForCall = append(fake.targetedOrganizationArgsForCall, struct { }{}) + stub := fake.TargetedOrganizationStub + fakeReturns := fake.targetedOrganizationReturns fake.recordInvocation("TargetedOrganization", []interface{}{}) fake.targetedOrganizationMutex.Unlock() - if fake.TargetedOrganizationStub != nil { - return fake.TargetedOrganizationStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedOrganizationReturns return fakeReturns.result1 } @@ -3205,15 +3329,16 @@ func (fake *FakeConfig) TargetedOrganizationName() string { ret, specificReturn := fake.targetedOrganizationNameReturnsOnCall[len(fake.targetedOrganizationNameArgsForCall)] fake.targetedOrganizationNameArgsForCall = append(fake.targetedOrganizationNameArgsForCall, struct { }{}) + stub := fake.TargetedOrganizationNameStub + fakeReturns := fake.targetedOrganizationNameReturns fake.recordInvocation("TargetedOrganizationName", []interface{}{}) fake.targetedOrganizationNameMutex.Unlock() - if fake.TargetedOrganizationNameStub != nil { - return fake.TargetedOrganizationNameStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedOrganizationNameReturns return fakeReturns.result1 } @@ -3257,15 +3382,16 @@ func (fake *FakeConfig) TargetedSpace() configv3.Space { ret, specificReturn := fake.targetedSpaceReturnsOnCall[len(fake.targetedSpaceArgsForCall)] fake.targetedSpaceArgsForCall = append(fake.targetedSpaceArgsForCall, struct { }{}) + stub := fake.TargetedSpaceStub + fakeReturns := fake.targetedSpaceReturns fake.recordInvocation("TargetedSpace", []interface{}{}) fake.targetedSpaceMutex.Unlock() - if fake.TargetedSpaceStub != nil { - return fake.TargetedSpaceStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.targetedSpaceReturns return fakeReturns.result1 } @@ -3309,15 +3435,16 @@ func (fake *FakeConfig) TerminalWidth() int { ret, specificReturn := fake.terminalWidthReturnsOnCall[len(fake.terminalWidthArgsForCall)] fake.terminalWidthArgsForCall = append(fake.terminalWidthArgsForCall, struct { }{}) + stub := fake.TerminalWidthStub + fakeReturns := fake.terminalWidthReturns fake.recordInvocation("TerminalWidth", []interface{}{}) fake.terminalWidthMutex.Unlock() - if fake.TerminalWidthStub != nil { - return fake.TerminalWidthStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.terminalWidthReturns return fakeReturns.result1 } @@ -3361,15 +3488,16 @@ func (fake *FakeConfig) UAADisableKeepAlives() bool { ret, specificReturn := fake.uAADisableKeepAlivesReturnsOnCall[len(fake.uAADisableKeepAlivesArgsForCall)] fake.uAADisableKeepAlivesArgsForCall = append(fake.uAADisableKeepAlivesArgsForCall, struct { }{}) + stub := fake.UAADisableKeepAlivesStub + fakeReturns := fake.uAADisableKeepAlivesReturns fake.recordInvocation("UAADisableKeepAlives", []interface{}{}) fake.uAADisableKeepAlivesMutex.Unlock() - if fake.UAADisableKeepAlivesStub != nil { - return fake.UAADisableKeepAlivesStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAADisableKeepAlivesReturns return fakeReturns.result1 } @@ -3413,15 +3541,16 @@ func (fake *FakeConfig) UAAEndpoint() string { ret, specificReturn := fake.uAAEndpointReturnsOnCall[len(fake.uAAEndpointArgsForCall)] fake.uAAEndpointArgsForCall = append(fake.uAAEndpointArgsForCall, struct { }{}) + stub := fake.UAAEndpointStub + fakeReturns := fake.uAAEndpointReturns fake.recordInvocation("UAAEndpoint", []interface{}{}) fake.uAAEndpointMutex.Unlock() - if fake.UAAEndpointStub != nil { - return fake.UAAEndpointStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAEndpointReturns return fakeReturns.result1 } @@ -3465,15 +3594,16 @@ func (fake *FakeConfig) UAAGrantType() string { ret, specificReturn := fake.uAAGrantTypeReturnsOnCall[len(fake.uAAGrantTypeArgsForCall)] fake.uAAGrantTypeArgsForCall = append(fake.uAAGrantTypeArgsForCall, struct { }{}) + stub := fake.UAAGrantTypeStub + fakeReturns := fake.uAAGrantTypeReturns fake.recordInvocation("UAAGrantType", []interface{}{}) fake.uAAGrantTypeMutex.Unlock() - if fake.UAAGrantTypeStub != nil { - return fake.UAAGrantTypeStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAGrantTypeReturns return fakeReturns.result1 } @@ -3517,15 +3647,16 @@ func (fake *FakeConfig) UAAOAuthClient() string { ret, specificReturn := fake.uAAOAuthClientReturnsOnCall[len(fake.uAAOAuthClientArgsForCall)] fake.uAAOAuthClientArgsForCall = append(fake.uAAOAuthClientArgsForCall, struct { }{}) + stub := fake.UAAOAuthClientStub + fakeReturns := fake.uAAOAuthClientReturns fake.recordInvocation("UAAOAuthClient", []interface{}{}) fake.uAAOAuthClientMutex.Unlock() - if fake.UAAOAuthClientStub != nil { - return fake.UAAOAuthClientStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAOAuthClientReturns return fakeReturns.result1 } @@ -3569,15 +3700,16 @@ func (fake *FakeConfig) UAAOAuthClientSecret() string { ret, specificReturn := fake.uAAOAuthClientSecretReturnsOnCall[len(fake.uAAOAuthClientSecretArgsForCall)] fake.uAAOAuthClientSecretArgsForCall = append(fake.uAAOAuthClientSecretArgsForCall, struct { }{}) + stub := fake.UAAOAuthClientSecretStub + fakeReturns := fake.uAAOAuthClientSecretReturns fake.recordInvocation("UAAOAuthClientSecret", []interface{}{}) fake.uAAOAuthClientSecretMutex.Unlock() - if fake.UAAOAuthClientSecretStub != nil { - return fake.UAAOAuthClientSecretStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.uAAOAuthClientSecretReturns return fakeReturns.result1 } @@ -3620,9 +3752,10 @@ func (fake *FakeConfig) UnsetOrganizationAndSpaceInformation() { fake.unsetOrganizationAndSpaceInformationMutex.Lock() fake.unsetOrganizationAndSpaceInformationArgsForCall = append(fake.unsetOrganizationAndSpaceInformationArgsForCall, struct { }{}) + stub := fake.UnsetOrganizationAndSpaceInformationStub fake.recordInvocation("UnsetOrganizationAndSpaceInformation", []interface{}{}) fake.unsetOrganizationAndSpaceInformationMutex.Unlock() - if fake.UnsetOrganizationAndSpaceInformationStub != nil { + if stub != nil { fake.UnsetOrganizationAndSpaceInformationStub() } } @@ -3643,9 +3776,10 @@ func (fake *FakeConfig) UnsetSpaceInformation() { fake.unsetSpaceInformationMutex.Lock() fake.unsetSpaceInformationArgsForCall = append(fake.unsetSpaceInformationArgsForCall, struct { }{}) + stub := fake.UnsetSpaceInformationStub fake.recordInvocation("UnsetSpaceInformation", []interface{}{}) fake.unsetSpaceInformationMutex.Unlock() - if fake.UnsetSpaceInformationStub != nil { + if stub != nil { fake.UnsetSpaceInformationStub() } } @@ -3666,9 +3800,10 @@ func (fake *FakeConfig) UnsetUserInformation() { fake.unsetUserInformationMutex.Lock() fake.unsetUserInformationArgsForCall = append(fake.unsetUserInformationArgsForCall, struct { }{}) + stub := fake.UnsetUserInformationStub fake.recordInvocation("UnsetUserInformation", []interface{}{}) fake.unsetUserInformationMutex.Unlock() - if fake.UnsetUserInformationStub != nil { + if stub != nil { fake.UnsetUserInformationStub() } } @@ -3691,9 +3826,10 @@ func (fake *FakeConfig) V7SetSpaceInformation(arg1 string, arg2 string) { arg1 string arg2 string }{arg1, arg2}) + stub := fake.V7SetSpaceInformationStub fake.recordInvocation("V7SetSpaceInformation", []interface{}{arg1, arg2}) fake.v7SetSpaceInformationMutex.Unlock() - if fake.V7SetSpaceInformationStub != nil { + if stub != nil { fake.V7SetSpaceInformationStub(arg1, arg2) } } @@ -3722,15 +3858,16 @@ func (fake *FakeConfig) Verbose() (bool, []string) { ret, specificReturn := fake.verboseReturnsOnCall[len(fake.verboseArgsForCall)] fake.verboseArgsForCall = append(fake.verboseArgsForCall, struct { }{}) + stub := fake.VerboseStub + fakeReturns := fake.verboseReturns fake.recordInvocation("Verbose", []interface{}{}) fake.verboseMutex.Unlock() - if fake.VerboseStub != nil { - return fake.VerboseStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1, ret.result2 } - fakeReturns := fake.verboseReturns return fakeReturns.result1, fakeReturns.result2 } @@ -3777,15 +3914,16 @@ func (fake *FakeConfig) WriteConfig() error { ret, specificReturn := fake.writeConfigReturnsOnCall[len(fake.writeConfigArgsForCall)] fake.writeConfigArgsForCall = append(fake.writeConfigArgsForCall, struct { }{}) + stub := fake.WriteConfigStub + fakeReturns := fake.writeConfigReturns fake.recordInvocation("WriteConfig", []interface{}{}) fake.writeConfigMutex.Unlock() - if fake.WriteConfigStub != nil { - return fake.WriteConfigStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.writeConfigReturns return fakeReturns.result1 } @@ -3829,15 +3967,16 @@ func (fake *FakeConfig) WritePluginConfig() error { ret, specificReturn := fake.writePluginConfigReturnsOnCall[len(fake.writePluginConfigArgsForCall)] fake.writePluginConfigArgsForCall = append(fake.writePluginConfigArgsForCall, struct { }{}) + stub := fake.WritePluginConfigStub + fakeReturns := fake.writePluginConfigReturns fake.recordInvocation("WritePluginConfig", []interface{}{}) fake.writePluginConfigMutex.Unlock() - if fake.WritePluginConfigStub != nil { - return fake.WritePluginConfigStub() + if stub != nil { + return stub() } if specificReturn { return ret.result1 } - fakeReturns := fake.writePluginConfigReturns return fakeReturns.result1 } @@ -3897,6 +4036,8 @@ func (fake *FakeConfig) Invocations() map[string][][]interface{} { defer fake.cFPasswordMutex.RUnlock() fake.cFUsernameMutex.RLock() defer fake.cFUsernameMutex.RUnlock() + fake.cNBCredentialsMutex.RLock() + defer fake.cNBCredentialsMutex.RUnlock() fake.colorEnabledMutex.RLock() defer fake.colorEnabledMutex.RUnlock() fake.currentUserMutex.RLock() diff --git a/command/config.go b/command/config.go index 44b30e5ba99..676223c7923 100644 --- a/command/config.go +++ b/command/config.go @@ -24,6 +24,7 @@ type Config interface { CurrentUserName() (string, error) DialTimeout() time.Duration DockerPassword() string + CNBCredentials() (map[string]interface{}, error) Experimental() bool GetPlugin(pluginName string) (configv3.Plugin, bool) GetPluginCaseInsensitive(pluginName string) (configv3.Plugin, bool) diff --git a/command/v7/create_app_command.go b/command/v7/create_app_command.go index 938be0bcf73..9b8a1e35baf 100644 --- a/command/v7/create_app_command.go +++ b/command/v7/create_app_command.go @@ -1,6 +1,9 @@ package v7 import ( + "errors" + "fmt" + "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/command/flag" @@ -11,8 +14,9 @@ type CreateAppCommand struct { BaseCommand RequiredArgs flag.AppName `positional-args:"yes"` - AppType flag.AppType `long:"app-type" choice:"buildpack" choice:"docker" description:"App lifecycle type to stage and run the app" default:"buildpack"` - usage interface{} `usage:"CF_NAME create-app APP_NAME [--app-type (buildpack | docker)]"` + AppType flag.AppType `long:"app-type" choice:"buildpack" choice:"docker" choice:"cnb" description:"App lifecycle type to stage and run the app" default:"buildpack"` + Buildpacks []string `long:"buildpack" short:"b" description:"Custom buildpack by name (e.g. my-buildpack), Docker image (e.g. docker://registry/image:tag), Git URL (e.g. 'https://github.com/cloudfoundry/java-buildpack.git') or Git URL with a branch or tag (e.g. 'https://github.com/cloudfoundry/java-buildpack.git#v3.3.0' for 'v3.3.0' tag). To use built-in buildpacks only, specify 'default' or 'null'"` + usage interface{} `usage:"CF_NAME create-app APP_NAME [--app-type (buildpack | docker | cnb)]"` relatedCommands interface{} `related_commands:"app, apps, push"` } @@ -34,11 +38,29 @@ func (cmd CreateAppCommand) Execute(args []string) error { "CurrentUser": user.Name, }) + cmd.UI.DisplayText(fmt.Sprintf("Using app type %q", constant.AppLifecycleType(cmd.AppType))) + + app := resources.Application{ + Name: cmd.RequiredArgs.AppName, + LifecycleType: constant.AppLifecycleType(cmd.AppType), + LifecycleBuildpacks: cmd.Buildpacks, + } + + if constant.AppLifecycleType(cmd.AppType) == constant.AppLifecycleTypeCNB { + if len(cmd.Buildpacks) == 0 { + return errors.New("buildpack(s) must be provided when using --app-type cnb") + } + + creds, err := cmd.Config.CNBCredentials() + if err != nil { + return err + } + + app.Credentials = creds + } + _, warnings, err := cmd.Actor.CreateApplicationInSpace( - resources.Application{ - Name: cmd.RequiredArgs.AppName, - LifecycleType: constant.AppLifecycleType(cmd.AppType), - }, + app, cmd.Config.TargetedSpace().GUID, ) cmd.UI.DisplayWarnings(warnings) diff --git a/command/v7/create_app_command_test.go b/command/v7/create_app_command_test.go index 5125dd09b44..a1b6cec95fa 100644 --- a/command/v7/create_app_command_test.go +++ b/command/v7/create_app_command_test.go @@ -124,6 +124,32 @@ var _ = Describe("create-app Command", func() { Expect(createSpaceGUID).To(Equal("some-space-guid")) }) }) + + When("app type is cnb", func() { + BeforeEach(func() { + cmd.AppType = "cnb" + cmd.Buildpacks = []string{"foo"} + fakeConfig.CNBCredentialsReturns(map[string]interface{}{ + "foo": "bar", + }, nil) + }) + + It("creates an app with app type: cnb", func() { + Expect(executeErr).ToNot(HaveOccurred()) + + Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(1)) + createApp, createSpaceGUID := fakeActor.CreateApplicationInSpaceArgsForCall(0) + Expect(createApp).To(Equal(resources.Application{ + Name: app, + LifecycleType: constant.AppLifecycleTypeCNB, + LifecycleBuildpacks: []string{"foo"}, + Credentials: map[string]interface{}{ + "foo": "bar", + }, + })) + Expect(createSpaceGUID).To(Equal("some-space-guid")) + }) + }) }) When("the create is unsuccessful", func() { @@ -168,6 +194,18 @@ var _ = Describe("create-app Command", func() { Expect(testUI.Err).To(Say("I am also a warning")) }) }) + + Context("due to missing buildpacks when AppType is cnb", func() { + BeforeEach(func() { + cmd.AppType = "cnb" + }) + + It("displays the header and error", func() { + Expect(executeErr).To(MatchError("buildpack(s) must be provided when using --app-type cnb")) + + Expect(testUI.Out).To(Say("Creating app some-app in org some-org / space some-space as banana...")) + }) + }) }) }) }) diff --git a/command/v7/push_command.go b/command/v7/push_command.go index cbf71d78e78..85a0af77740 100644 --- a/command/v7/push_command.go +++ b/command/v7/push_command.go @@ -105,8 +105,10 @@ type PushCommand struct { Task bool `long:"task" description:"Push an app that is used only to execute tasks. The app will be staged, but not started and will have no route assigned."` Vars []template.VarKV `long:"var" description:"Variable key value pair for variable substitution, (e.g., name=app1); can specify multiple times"` PathsToVarsFiles []flag.PathWithExistenceCheck `long:"vars-file" description:"Path to a variable substitution file for manifest; can specify multiple times"` + Lifecycle constant.AppLifecycleType `long:"lifecycle" description:"App lifecycle type to stage and run the app" default:""` dockerPassword interface{} `environmentName:"CF_DOCKER_PASSWORD" environmentDescription:"Password used for private docker repository"` - usage interface{} `usage:"CF_NAME push APP_NAME [-b BUILDPACK_NAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]...\n \n CF_NAME push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route ]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]..."` + cnbCredentials interface{} `environmentName:"CNB_REGISTRY_CREDS" environmentDescription:"Credentials for pulling Cloud Native Buildpacks from private registries"` + usage interface{} `usage:"CF_NAME push APP_NAME [-b BUILDPACK_NAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--lifecycle (buildpack | docker | cnb)] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]...\n \n CF_NAME push APP_NAME --docker-image [REGISTRY_HOST:PORT/]IMAGE[:TAG] [--docker-username USERNAME]\n [-c COMMAND] [-f MANIFEST_PATH | --no-manifest] [--no-start] [--no-wait] [-i NUM_INSTANCES]\n [-k DISK] [-m MEMORY] [-l LOG_RATE_LIMIT] [-p PATH] [-s STACK] [-t HEALTH_TIMEOUT] [--task TASK]\n [-u (process | port | http)] [--no-route | --random-route ]\n [--var KEY=VALUE] [--vars-file VARS_FILE_PATH]..."` envCFStagingTimeout interface{} `environmentName:"CF_STAGING_TIMEOUT" environmentDescription:"Max wait time for staging, in minutes" environmentDefault:"15"` envCFStartupTimeout interface{} `environmentName:"CF_STARTUP_TIMEOUT" environmentDescription:"Max wait time for app instance startup, in minutes" environmentDefault:"5"` @@ -174,6 +176,11 @@ func (cmd PushCommand) Execute(args []string) error { return err } + flagOverrides.CNBCredentials, err = cmd.Config.CNBCredentials() + if err != nil { + return err + } + transformedManifest, err := cmd.PushActor.HandleFlagOverrides(baseManifest, flagOverrides) if err != nil { return err @@ -238,6 +245,7 @@ func (cmd PushCommand) Execute(args []string) error { transformedManifest, flagOverrides, ) + cmd.UI.DisplayWarnings(warnings) if err != nil { return err @@ -363,11 +371,70 @@ func (cmd PushCommand) GetFlagOverrides() (v7pushaction.FlagOverrides, error) { NoManifest: cmd.NoManifest, Task: cmd.Task, LogRateLimit: cmd.LogRateLimit, + Lifecycle: cmd.Lifecycle, }, nil } func (cmd PushCommand) ValidateFlags() error { switch { + // Lifecycle buildpack requested + case cmd.Lifecycle == constant.AppLifecycleTypeBuildpack && cmd.DockerImage.Path != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-image, -o", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeBuildpack && cmd.DockerUsername != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-username", + }, + } + + // Lifecycle docker requested + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.Buildpacks != nil: + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--buildpack, -b", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.Stack != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--stack, -s", + }, + } + case cmd.Lifecycle == constant.AppLifecycleTypeDocker && cmd.DropletPath != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--droplet", + }, + } + + // Lifecycle cnb requested + case cmd.Lifecycle == constant.AppLifecycleTypeCNB && cmd.DockerImage.Path != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-image, -o", + }, + } + + case cmd.Lifecycle == constant.AppLifecycleTypeCNB && cmd.DockerUsername != "": + return translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-username", + }, + } + case cmd.DockerUsername != "" && cmd.DockerImage.Path == "": return translatableerror.RequiredFlagsError{ Arg1: "--docker-image, -o", diff --git a/command/v7/push_command_test.go b/command/v7/push_command_test.go index ead21520928..1a58b4cfafe 100644 --- a/command/v7/push_command_test.go +++ b/command/v7/push_command_test.go @@ -1081,6 +1081,7 @@ var _ = Describe("push Command", func() { cmd.Vars = []template.VarKV{{Name: "key", Value: "val"}} cmd.Task = true cmd.LogRateLimit = "512M" + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack }) JustBeforeEach(func() { @@ -1111,6 +1112,7 @@ var _ = Describe("push Command", func() { Expect(overrides.Task).To(BeTrue()) Expect(overrides.LogRateLimit).To(Equal("512M")) Expect(*overrides.MaxInFlight).To(Equal(1)) + Expect(overrides.Lifecycle).To(BeEquivalentTo("buildpack")) }) When("a docker image is provided", func() { @@ -1313,5 +1315,89 @@ var _ = Describe("push Command", func() { translatableerror.IncorrectUsageError{ Message: "--max-in-flight must be greater than or equal to 1", }), + + Entry("lifecycle buildpack and docker-image flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack + cmd.DockerImage = flag.DockerImage{Path: "foo"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-image, -o", + }, + }), + + Entry("lifecycle buildpack and docker-username flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeBuildpack + cmd.DockerUsername = "user" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle buildpack", + "--docker-username", + }, + }), + + Entry("lifecycle docker and buildpacks flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.Buildpacks = []string{"nodejs"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--buildpack, -b", + }, + }), + + Entry("lifecycle docker and stck flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.Stack = "stack" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--stack, -s", + }, + }), + + Entry("lifecycle docker and droplet flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeDocker + cmd.DropletPath = flag.PathWithExistenceCheck("path") + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle docker", + "--droplet", + }, + }), + + Entry("lifecycle cnb and docker-image flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeCNB + cmd.DockerImage = flag.DockerImage{Path: "foo"} + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-image, -o", + }, + }), + + Entry("lifecycle cnb and docker-username flags are passed", + func() { + cmd.Lifecycle = constant.AppLifecycleTypeCNB + cmd.DockerUsername = "user" + }, + translatableerror.ArgumentCombinationError{ + Args: []string{ + "--lifecycle cnb", + "--docker-username", + }, + }), ) }) diff --git a/command/v7/shared/app_summary_displayer.go b/command/v7/shared/app_summary_displayer.go index a111b532b72..f7d386a66b1 100644 --- a/command/v7/shared/app_summary_displayer.go +++ b/command/v7/shared/app_summary_displayer.go @@ -32,33 +32,24 @@ func (display AppSummaryDisplayer) AppDisplay(summary v7action.DetailedApplicati isoRow = append(isoRow, display.UI.TranslateText("isolation segment:"), name) } + keyValueTable = [][]string{ + {display.UI.TranslateText("name:"), summary.Application.Name}, + {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, + isoRow, + {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, + {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, + {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, + } + if summary.LifecycleType == constant.AppLifecycleTypeDocker { - keyValueTable = [][]string{ - {display.UI.TranslateText("name:"), summary.Application.Name}, - {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, - isoRow, - {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, - {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, - {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, - {display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}, - isoRow, - } + keyValueTable = append(keyValueTable, []string{display.UI.TranslateText("docker image:"), summary.CurrentDroplet.Image}, isoRow) } else { - keyValueTable = [][]string{ - {display.UI.TranslateText("name:"), summary.Application.Name}, - {display.UI.TranslateText("requested state:"), strings.ToLower(string(summary.State))}, - isoRow, - {display.UI.TranslateText("routes:"), routeSummary(summary.Routes)}, - {display.UI.TranslateText("last uploaded:"), display.getCreatedTime(summary)}, - {display.UI.TranslateText("stack:"), summary.CurrentDroplet.Stack}, - {display.UI.TranslateText("buildpacks:"), ""}, - isoRow, - } + keyValueTable = append(keyValueTable, []string{display.UI.TranslateText("buildpacks:"), ""}, isoRow) } display.UI.DisplayKeyValueTable("", keyValueTable, ui.DefaultTableSpacePadding) - if summary.LifecycleType == constant.AppLifecycleTypeBuildpack { + if summary.LifecycleType != constant.AppLifecycleTypeDocker { display.displayBuildpackTable(summary.CurrentDroplet.Buildpacks) } diff --git a/command/v7/shared/manifest_diff_displayer.go b/command/v7/shared/manifest_diff_displayer.go index 375e000e0a6..254a2c9455b 100644 --- a/command/v7/shared/manifest_diff_displayer.go +++ b/command/v7/shared/manifest_diff_displayer.go @@ -183,10 +183,20 @@ func redactDiff(diff resources.Diff) resources.Diff { return diff } +func redactCNBCredentials(diff resources.Diff) resources.Diff { + if strings.HasSuffix(diff.Path, "cnb-credentials") { + diff.Value = "[PRIVATE DATA HIDDEN]" + } + + return diff +} + func (display *ManifestDiffDisplayer) formatDiff(field string, diff resources.Diff, depth int, addHyphen bool) { if display.RedactEnv { diff = redactDiff(diff) } + + diff = redactCNBCredentials(diff) addHyphen = isInt(field) || addHyphen switch diff.Op { case resources.AddOperation: diff --git a/command/v7/shared/manifest_diff_displayer_test.go b/command/v7/shared/manifest_diff_displayer_test.go index e40dfa2fb4e..e3f63f77e39 100644 --- a/command/v7/shared/manifest_diff_displayer_test.go +++ b/command/v7/shared/manifest_diff_displayer_test.go @@ -572,6 +572,38 @@ applications: }) }) + When("adding cnb-credentials", func() { + BeforeEach(func() { + rawManifest = []byte(`--- +applications: +- name: dora + lifecycle: cnb + cnb-credentials: + foo: bar`) + diff = resources.ManifestDiff{ + Diffs: []resources.Diff{ + { + Op: resources.AddOperation, + Path: "/applications/0/cnb-credentials", + Value: []map[string]interface{}{ + { + "foo": "Bar", + }, + }, + }, + }, + } + }) + + It("redacts output", func() { + Expect(testUI.Out).To(Say(` --- + applications: + - name: dora + lifecycle: cnb +\+ cnb-credentials: '\[PRIVATE DATA HIDDEN\]'`)) + }) + }) + When("remove", func() { BeforeEach(func() { rawManifest = []byte(`--- diff --git a/integration/assets/js-hello/index.js b/integration/assets/js-hello/index.js new file mode 100644 index 00000000000..ed10e718435 --- /dev/null +++ b/integration/assets/js-hello/index.js @@ -0,0 +1,12 @@ +const http = require('http'); + +const server = http.createServer((_req, res) => { + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Hello World\n'); +}); + +const port = process.env.PORT; +server.listen(port, "0.0.0.0", () => { + console.log(`Server running at http://0.0.0.0:${port}/`); +}); diff --git a/integration/assets/js-hello/package.json b/integration/assets/js-hello/package.json new file mode 100644 index 00000000000..5d4ef7f9cff --- /dev/null +++ b/integration/assets/js-hello/package.json @@ -0,0 +1,8 @@ +{ + "name": "js-hello", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "start": "node ./index.js" + } +} diff --git a/integration/helpers/app.go b/integration/helpers/app.go index 1943ddbacc8..f2cd7458ead 100644 --- a/integration/helpers/app.go +++ b/integration/helpers/app.go @@ -129,6 +129,11 @@ func WithMultiBuildpackApp(f func(dir string)) { f("../../assets/go_calls_ruby") } +// WithJSHelloWorld creates a simple JS Hello World HTTP application to use with the CF push command. +func WithJSHelloWorld(f func(dir string)) { + f("../../assets/js-hello") +} + // WithProcfileApp creates an application to use with your CLI command // that contains Procfile defining web and worker processes. func WithProcfileApp(f func(dir string)) { diff --git a/integration/helpers/commonisolated/common_isolated_setup.go b/integration/helpers/commonisolated/common_isolated_setup.go index 17b62c11bda..6fab7989afc 100644 --- a/integration/helpers/commonisolated/common_isolated_setup.go +++ b/integration/helpers/commonisolated/common_isolated_setup.go @@ -41,6 +41,7 @@ func CommonGinkgoSetup( helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") if helpers.IsVersionMet(ccversion.MinVersionHTTP2RoutingV3) { helpers.EnableFeatureFlag("route_sharing") diff --git a/integration/shared/experimental/experimental_suite_test.go b/integration/shared/experimental/experimental_suite_test.go index 4e819c02d36..4861802bf13 100644 --- a/integration/shared/experimental/experimental_suite_test.go +++ b/integration/shared/experimental/experimental_suite_test.go @@ -36,6 +36,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/shared/global/global_suite_test.go b/integration/shared/global/global_suite_test.go index d049a732d40..11288dbdbfc 100644 --- a/integration/shared/global/global_suite_test.go +++ b/integration/shared/global/global_suite_test.go @@ -39,6 +39,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/global/global_suite_test.go b/integration/v7/global/global_suite_test.go index d049a732d40..11288dbdbfc 100644 --- a/integration/v7/global/global_suite_test.go +++ b/integration/v7/global/global_suite_test.go @@ -39,6 +39,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/isolated/app_command_test.go b/integration/v7/isolated/app_command_test.go index b7383f57adb..9b812b40bc3 100644 --- a/integration/v7/isolated/app_command_test.go +++ b/integration/v7/isolated/app_command_test.go @@ -407,6 +407,20 @@ applications: }) }) + When("the app is a CNB app", func() { + BeforeEach(func() { + helpers.WithJSHelloWorld(func(appDir string) { + Eventually(helpers.CF("push", appName, "-p", appDir, "--lifecycle", "cnb", "-b", "docker://gcr.io/paketo-buildpacks/nodejs:latest")).Should(Exit()) + }) + }) + + It("displays the app buildpacks", func() { + session := helpers.CF("app", appName) + Eventually(session).Should(Say(`paketo-buildpacks\/nodejs`)) + Eventually(session).Should(Exit(0)) + }) + }) + When("the app has tcp routes", func() { var tcpDomain helpers.Domain diff --git a/integration/v7/isolated/create_app_command_test.go b/integration/v7/isolated/create_app_command_test.go index e10dc1872ea..680891fe5a8 100644 --- a/integration/v7/isolated/create_app_command_test.go +++ b/integration/v7/isolated/create_app_command_test.go @@ -59,7 +59,7 @@ var _ = Describe("create-app command", func() { It("tells the user that the app type is incorrect, prints help text, and exits 1", func() { session := helpers.CF("create-app", appName, "--app-type", "unknown-app-type") - Eventually(session.Err).Should(Say("Incorrect Usage: Invalid value `unknown-app-type' for option `--app-type'. Allowed values are: buildpack or docker")) + Eventually(session.Err).Should(Say("Incorrect Usage: Invalid value `unknown-app-type' for option `--app-type'. Allowed values are: buildpack, docker or cnb")) Eventually(session).Should(Say("NAME:")) Eventually(session).Should(Exit(1)) }) @@ -105,6 +105,18 @@ var _ = Describe("create-app command", func() { Eventually(session).Should(Say("docker image:")) Eventually(session).Should(Exit(0)) }) + + It("creates the app with the cnb app type", func() { + session := helpers.CF("create-app", appName, "--app-type", "cnb", "-b", "docker://foobar.test") + userName, _ := helpers.GetCredentials() + Eventually(session).Should(Say("Creating app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName)) + Eventually(session).Should(Say("OK")) + Eventually(session).Should(Exit(0)) + + session = helpers.CF("app", appName) + Eventually(session).ShouldNot(Say("docker image:")) + Eventually(session).Should(Exit(0)) + }) }) }) diff --git a/integration/v7/push/help_test.go b/integration/v7/push/help_test.go index 32845920753..7503e313a38 100644 --- a/integration/v7/push/help_test.go +++ b/integration/v7/push/help_test.go @@ -26,6 +26,7 @@ var _ = Describe("help", func() { "[-b BUILDPACK_NAME]", "[-c COMMAND]", "[-f MANIFEST_PATH | --no-manifest]", + "[--lifecycle (buildpack | docker | cnb)]", "[--no-start]", "[--no-wait]", "[-i NUM_INSTANCES]", diff --git a/integration/v7/push/push_suite_test.go b/integration/v7/push/push_suite_test.go index ebd30ce219f..42423eab717 100644 --- a/integration/v7/push/push_suite_test.go +++ b/integration/v7/push/push_suite_test.go @@ -40,6 +40,7 @@ var _ = SynchronizedBeforeSuite(func() []byte { helpers.SetupSynchronizedSuite(func() { helpers.EnableFeatureFlag("diego_docker") + helpers.EnableFeatureFlag("diego_cnb") helpers.EnableFeatureFlag("service_instance_sharing") }) diff --git a/integration/v7/push/tasks_test.go b/integration/v7/push/tasks_test.go index 4b85976ea2a..319c936eeab 100644 --- a/integration/v7/push/tasks_test.go +++ b/integration/v7/push/tasks_test.go @@ -7,7 +7,6 @@ import ( . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" - . "github.com/onsi/gomega/gexec" ) var _ = Describe("push with --task", func() { @@ -19,7 +18,7 @@ var _ = Describe("push with --task", func() { appName = helpers.NewAppName() helpers.WithHelloWorldApp(func(dir string) { session := helpers.CF("push", appName, "-p", dir, "--task") - Eventually(session).Should(Exit(0)) + Eventually(session).Should(gexec.Exit(0)) }) }) @@ -28,7 +27,7 @@ var _ = Describe("push with --task", func() { BeforeEach(func() { session = helpers.CF("app", appName) - Eventually(session).Should(Exit(0)) + Eventually(session).Should(gexec.Exit(0)) }) It("pushes the app without starting it", func() { diff --git a/resources/application_resource.go b/resources/application_resource.go index b7b5c782557..b9794bb81f9 100644 --- a/resources/application_resource.go +++ b/resources/application_resource.go @@ -25,6 +25,8 @@ type Application struct { SpaceGUID string // State is the desired state of the application. State constant.ApplicationState + // Credentials are used by Cloud Native Buildpacks lifecycle to pull buildpacks + Credentials map[string]interface{} } // ApplicationNameOnly represents only the name field of a Cloud Controller V3 Application @@ -48,7 +50,7 @@ func (a Application) MarshalJSON() ([]byte, error) { if a.LifecycleType == constant.AppLifecycleTypeDocker { ccApp.setDockerLifecycle() - } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack { + } else if a.LifecycleType == constant.AppLifecycleTypeBuildpack || a.LifecycleType == constant.AppLifecycleTypeCNB { if len(a.LifecycleBuildpacks) > 0 || a.StackName != "" { if a.hasAutodetectedBuildpack() { ccApp.setAutodetectedBuildpackLifecycle(a) @@ -100,11 +102,18 @@ func (a Application) hasAutodetectedBuildpack() bool { return a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueDefault || a.LifecycleBuildpacks[0] == constant.AutodetectBuildpackValueNull } +type ccCredentials map[string]interface{} + +func (ccCredentials) UnmarshalJSON(data []byte) error { + return nil +} + type ccLifecycle struct { Type constant.AppLifecycleType `json:"type,omitempty"` Data struct { - Buildpacks []string `json:"buildpacks,omitempty"` - Stack string `json:"stack,omitempty"` + Buildpacks []string `json:"buildpacks,omitempty"` + Stack string `json:"stack,omitempty"` + Credentials ccCredentials `json:"credentials,omitempty"` } `json:"data"` } @@ -135,6 +144,7 @@ func (ccApp *ccApplication) setBuildpackLifecycle(a Application) { lifecycle.Type = a.LifecycleType lifecycle.Data.Buildpacks = a.LifecycleBuildpacks lifecycle.Data.Stack = a.StackName + lifecycle.Data.Credentials = a.Credentials ccApp.Lifecycle = lifecycle } diff --git a/util/configv3/env.go b/util/configv3/env.go index efd935e37d0..27e15504fcd 100644 --- a/util/configv3/env.go +++ b/util/configv3/env.go @@ -1,6 +1,7 @@ package configv3 import ( + "encoding/json" "strconv" "strings" "time" @@ -20,6 +21,7 @@ type EnvOverride struct { CFTrace string CFUsername string DockerPassword string + CNBCredentials string Experimental string ForceTTY string HTTPSProxy string @@ -61,6 +63,21 @@ func (config *Config) DockerPassword() string { return config.ENV.DockerPassword } +// CNBCredentials retrurns CNB credentials from the environment +func (config *Config) CNBCredentials() (map[string]interface{}, error) { + if config.ENV.CNBCredentials == "" { + return nil, nil + } + + creds := map[string]interface{}{} + + if err := json.Unmarshal([]byte(config.ENV.CNBCredentials), &creds); err != nil { + return nil, err + } + + return creds, nil +} + // Experimental returns whether or not to run experimental CLI commands. This // is based on the following: // 1. The $CF_CLI_EXPERIMENTAL environment variable if set diff --git a/util/configv3/load_config.go b/util/configv3/load_config.go index c57b84510fc..883b2cd31cb 100644 --- a/util/configv3/load_config.go +++ b/util/configv3/load_config.go @@ -128,6 +128,7 @@ func LoadConfig(flags ...FlagOverride) (*Config, error) { CFTrace: os.Getenv("CF_TRACE"), CFUsername: os.Getenv("CF_USERNAME"), DockerPassword: os.Getenv("CF_DOCKER_PASSWORD"), + CNBCredentials: os.Getenv("CNB_REGISTRY_CREDS"), Experimental: os.Getenv("CF_CLI_EXPERIMENTAL"), ForceTTY: os.Getenv("FORCE_TTY"), HTTPSProxy: os.Getenv("https_proxy"), diff --git a/util/manifestparser/application.go b/util/manifestparser/application.go index 3b12942dfcc..2ce7d936701 100644 --- a/util/manifestparser/application.go +++ b/util/manifestparser/application.go @@ -16,22 +16,23 @@ type Docker struct { // add a field for the CLI to extract from the manifest, just add it to this // struct. type Application struct { - Name string `yaml:"name"` - DiskQuota string `yaml:"disk-quota,omitempty"` - Docker *Docker `yaml:"docker,omitempty"` - HealthCheckType constant.HealthCheckType `yaml:"health-check-type,omitempty"` - HealthCheckEndpoint string `yaml:"health-check-http-endpoint,omitempty"` - HealthCheckTimeout int64 `yaml:"timeout,omitempty"` - Instances *int `yaml:"instances,omitempty"` - Path string `yaml:"path,omitempty"` - Processes []Process `yaml:"processes,omitempty"` - Memory string `yaml:"memory,omitempty"` - NoRoute bool `yaml:"no-route,omitempty"` - RandomRoute bool `yaml:"random-route,omitempty"` - DefaultRoute bool `yaml:"default-route,omitempty"` - Stack string `yaml:"stack,omitempty"` - LogRateLimit string `yaml:"log-rate-limit-per-second,omitempty"` - RemainingManifestFields map[string]interface{} `yaml:"-,inline"` + Name string `yaml:"name"` + DiskQuota string `yaml:"disk-quota,omitempty"` + Docker *Docker `yaml:"docker,omitempty"` + HealthCheckType constant.HealthCheckType `yaml:"health-check-type,omitempty"` + HealthCheckEndpoint string `yaml:"health-check-http-endpoint,omitempty"` + HealthCheckTimeout int64 `yaml:"timeout,omitempty"` + Instances *int `yaml:"instances,omitempty"` + Path string `yaml:"path,omitempty"` + Processes []Process `yaml:"processes,omitempty"` + Memory string `yaml:"memory,omitempty"` + NoRoute bool `yaml:"no-route,omitempty"` + RandomRoute bool `yaml:"random-route,omitempty"` + DefaultRoute bool `yaml:"default-route,omitempty"` + Stack string `yaml:"stack,omitempty"` + LogRateLimit string `yaml:"log-rate-limit-per-second,omitempty"` + Lifecycle constant.AppLifecycleType `yaml:"lifecycle,omitempty"` + RemainingManifestFields map[string]interface{} `yaml:"-,inline"` } func (application Application) HasBuildpacks() bool {