Giter Site home page Giter Site logo

cf-blue-green-deploy's People

Contributors

axelibm avatar bluemixgaragelondon avatar holly-cummins avatar jochenehret avatar matulko avatar r4vi avatar rrufus avatar samhandev avatar samze avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cf-blue-green-deploy's Issues

Incorrect route registration when routes for a second domain only have paths

Situation

I have:

  • an app

  • two domains:

    • the shared apps domain which routes to the app by default
    • a second, private domain
  • a route from the private domain containing a path:

    cf create-route my-space private-domain --path some-path
    
  • a mapping of the above route to my app

Expected behaviour

When deploying with the blue-green-deploy plugin the new app created has the same routes as the original app.

Actual behaviour

The route with the path is not mapped to the app. Instead, a route to just the private-domain is created and mapped, resulting in incorrect routing behaviour.

FR - Display Smoke Test Output in Real Time

Thanks for such a useful plugin! I have a long-running smoke test script that writes to stdout as it progresses. It seems that BGD captures the output as the smoke test is running and then displays it in its entirety only when the script has completed. It would be nice to see the output in real time. I'm new to Go, but I believe this is possible and would be willing to take a crack at it if it's something you'd consider merging.

Deployment fails with unhelpful error when multiple applications in manifest

If you have multiple applications in your manifest, e.g.:


---
applications:
- name: app_1
- name: app_2

And attempt to run the following command:

cf bgd app_1

You will get the following output:

Using manifest file /.../manifest.yml

Could not unmap route - App app_1-new not found

And that's it.

This is because when you have multiple applications in the manifest, pushing with push <app_name> does not indicate the name that should be used on CF, but rather the name of the application that should be pushed. If it can't find it, it appears to shrug and report OK.

I would expect the BGD plugin to either: work around this and do a BGD of the single app I've requested, or fail-fast and tell me that it's not supported.

It's possible this is also an issue with the CF CLI not returning a non-zero exit code if it can't find the application requested in the manifest.

bgd is ignoring instances, memory and disk_quota from manifest.yml

Hi there!

I noticed that bgd is ignoring the instances, memory and disk_quota from the manifest.yml file.

My app is running on PCF currently with 3 Instances, 1G memory and 1G disk.
If I try to redeploy with bgd over this app the deploy do not scale with the new resources.

If there is no app running, the deploy uses the data from the manifest.yml creating a app with the right resources.

My manifest.yml file:

applications:
- buildpack: staticfile_buildpack
  disk_quota: 2G
  env:
    GRANT_TYPE: password
    RESOURCE_URL: https://test.com
    SKIP_SSL_VALIDATION: true
    SSO_AUTO_APROVED_SCOPES: open.id, todo.read
    SSO_IDENTITY_PROVIDERS: SSO
    SSO_REDIRECT_URIS: https://test.com/
    SSO_SCOPE: open.id, todo.read
  instances: 4
  memory: 2G
  name: app-devops
  random-route: false
  services:
  - config-server

Here the output from the command trying to redeploy the app:

# cf bgd app-name -f manifest.yml -smoke-test smoketest.sh
Deleting app app-name-old in org Org / space devops as devops...
OK
Using manifest file manifest.yml

Creating app app-name-new in org Org / space devops as devops...
OK

Using route app-name-new.test.com
Binding app-name-new.test.com to app-name-new...
OK

Uploading app-name-new...
Uploading app files from: /home/jenkins-slave/workspace/deploy-module
Uploading 477.6K, 66 files

                             
Done uploading
OK
Binding service sbil-config-server to app app-name-new in org Org / space devops as devops...
OK

Starting app app-name-new in org Org / space devops as devops...
Downloading staticfile_buildpack...
Downloaded staticfile_buildpack
Creating container
Successfully created container
Downloading app package...
Downloaded app package (7.2M)
-----> Staticfile Buildpack version 1.4.21
-----> Installing nginx
       Using nginx version 1.13.8
-----> Installing nginx 1.13.8
       Copy [/tmp/buildpacks/4797a036f87bb3928bb164c574a43e2d/dependencies/3292a1fdf05213ded5bd38c322c33b1c/nginx-1.13.8-linux-x64-9585c5f4.tgz]
-----> Root folder /tmp/app
-----> Copying project files into public
-----> Configuring nginx
Exit status 0
Uploading droplet, build artifacts cache...
Uploading build artifacts cache...
Uploading droplet...
Uploaded build artifacts cache (218B)
Uploaded droplet (9.9M)
Successfully destroyed container
Uploading complete
Stopping instance c5e39b2b-46b6-43a1-90ab-4bcddd71a514
Destroying container

3 of 3 instances running

App started


OK

App app-name-new was started using this command `$HOME/boot.sh`

Showing health and status for app app-name-new in org Org / space devops as devops...
OK

requested state: started
instances: 3/3
usage: 1G x 3 instances
urls: app-name-new.test.com
last uploaded: Fri May 4 20:26:59 UTC 2018
stack: cflinuxfs2
buildpack: staticfile_buildpack

     state     since                    cpu    memory    disk      details
#0   running   2018-05-04 03:27:25 PM   0.0%   0 of 1G   0 of 1G
#1   running   2018-05-04 03:27:26 PM   0.0%   0 of 1G   0 of 1G
#2   running   2018-05-04 03:27:25 PM   0.0%   0 of 1G   0 of 1G
ssh support is enabled for 'app-name'

ssh support is already enabled for 'app-name-new'

Removing route app-name-new.test.com from app app-name-new in org SvcsIT-AnEOrg / space devops as devops...
OK
Creating route app-name.test.com for org SvcsIT-AnEOrg / space devops as devops...
OK
Route app-name.test.com already exists
Adding route app-name.test.com to app app-name-new in org SvcsIT-AnEOrg / space devops as devops...
OK
Renaming app app-name to app-name-old in org SvcsIT-AnEOrg / space devops as devops...
OK
Renaming app app-name-new to app-name in org SvcsIT-AnEOrg / space devops as devops...
OK
Removing route app-name.test.com from app app-name-old in org SvcsIT-AnEOrg / space devops as devops...
OK

Feature proposal: delete -old app on success

Is there a reason that the -old suffixed app is left running after a successful deployment?

Would you accept a PR to automatically remove it when the deploy was successful?

Would you need the behaviour to be feature flagged with a new CLI argument?

Create previous app

Hi,
it would be great if the blue-green could have an additional step were the old green deployment is only stopped and relabeled to something like "previous".
So in case the new green is broken for example by business logic you could easy switch back to the previous version.
What do you think?

Thanks

Domain is ignored when copying existing routes to new application

I have my application deployed at testbed.artsquare.com on Bluemix. When pushing with bgd, the new application is routed as testbed-new.mybluemix.net--not a big issue, but potentially a gotcha for some. However, bgd then tries to map the new application to testbed.mybluemix.net instead of testbed.artsquare.com. Instead, it should copy the exact routes that are already applied.

Specifying the routes in a manifest is not practical because the application is first deployed to a staging environment with a completely different route setup.

Routes temporarily disappear when using CF v265

The problem

When using Cloud Foundry v265 applications pushed with the blue-green-deploy plugin suffer downtime of up to 60 seconds. The steps to reproduce listed below demonstrate this is not actually caused by your plugin, but I am raising this issue because you are affected by it. When I find the Cloud Foundry component responsible I will raise it with them as well.

Update: We have tracked this down to the route-emitter and have raised an issue with its maintainers: https://github.com/cloudfoundry/route-emitter/issues/8. A fix is in diego-release v1.22.0. The earliest cf-release that includes this fix is v268.

Context

We have deployed open source Cloud Foundry v265, upgrading from v257. We fully automate the deployment of applications using the blue-green-deployment plugin. There was zero downtime with CF v257, but now with CF v265 there is up to 60 seconds where requests to the app are responded to with a status code of 404.

Steps to reproduce

This can be reproduced with all versions of the plugin, but we use scripting because the root cause is not this plugin. It seems it is a race condition in Cloud Foundry:

  • Deploy Cloud Foundry v265

  • Deploy an application

  • Set up a curl to monitor the app:

    while true; do curl -s -o /dev/null -w "%{http_code} " https://${APP_NAME}.${APP_DOMAIN} -k; date; sleep 1; done | tee /tmp/bgd.out
    
  • Do a blue-green deploy using this example script.

You should see 404s returned after the unmapping of the route from the old application for up to 60 seconds.

Add a sleep of 60 seconds before the unmapping of the route from the old app and the problem goes away.

A theory

In our setup the route-emitter emits registration and unregistration messages via NATS every 20 seconds and does a bulk update every 60 seconds. I believe this is representative of most deployments. Because the downtime is always less than 60 seconds I believe the state in BBS is correct and on the bulk update the problem gets fixed. Therefore, the route-emitter is somehow unregistering the route from the new app instead of the old app.

Update: I've confirmed by tailing the logs of the GoRouter that the route is definitely unregistered from the new app, when it should be unregistered from the old app.

Versions

cf-release v265
diego-release v1.19.0
All versions of this plugin
CF CLI 6.26

Release statically linked binaries for Linux

Would you be able to release statically linked binaries for Linux so that we can use this plugin from a container that is based on Alpine Linux?

We use cf-cli with Alpine in our deployment pipeline because it has a minimal amount of dependencies to maintain. Alpine is based on musl-libc rather than glibc, so it's unable to run dynamically linked libraries.

For reference cf-cli made a similar change last year in cloudfoundry/cli#808. Although it's also worth noting that they had some problems with specific Go versions detailed in cloudfoundry/cli#763.

I'm unclear about the exact change that's required. If I build locally from Darwin using Go 1.7 then file artefacts/blue-green-deploy.linux64 confirms that it is statically linked.

Can't install plugin

Whenever I try to install this plugin, I get the following error:
Looking up 'blue-green-deploy' from repository 'CF-Community'
10093904 bytes downloaded...
Installing plugin /tmp/ filename=blue-green-deploy.osx...
FAILED
exit status 2

I can successfully install other plugins from the CF-Community repo. I checked since my normal culprit is our corporate proxy but that doesn't seem to be the case this time.

I am running Mac OSX 10.10.5.

CF-ServiceBrokerBadResponse - Failed to set credential permissions

While attempting pushing Blue-Green with cf-push-blue-green task, following exception are raised at step of binding services to app:

Stacktrace * Exception is:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':cf-push-blue-green-1'.

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:100)

at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)

at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)

at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)

at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)

at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:88)

at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)

at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)

at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)

at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)

at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:242)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:95)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:235)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:224)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:121)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:77)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:102)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:96)

at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:612)

at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:567)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:96)

at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:57)

at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:122)

at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)

at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)

at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)

at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:46)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)

at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)

at org.gradle.initialization.DefaultGradleLauncher$ExecuteTasks.run(DefaultGradleLauncher.java:253)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:95)

at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:170)

at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:44)

at org.gradle.initialization.DefaultGradleLauncher$1.run(DefaultGradleLauncher.java:122)

at org.gradle.internal.work.DefaultWorkerLeaseService$2.execute(DefaultWorkerLeaseService.java:124)

at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:116)

at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:99)

at org.gradle.launcher.exec.GradleBuildController.run(GradleBuildController.java:66)

at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)

at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)

at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)

at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$1.run(RunAsBuildOperationBuildActionRunner.java:43)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:317)

at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:309)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:185)

at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:95)

at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:40)

at org.gradle.tooling.internal.provider.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:51)

at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:44)

at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)

at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:75)

at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:49)

at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:51)

at org.gradle.tooling.internal.provider.ServicesSetupBuildActionExecuter.execute(ServicesSetupBuildActionExecuter.java:32)

at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:36)

at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:25)

at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:64)

at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:29)

at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)

at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:42)

at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:50)

at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:30)

at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:51)

at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:173)

at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:287)

at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:260)

at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:33)

at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)

at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)

at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:253)

at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:182)

at org.gradle.launcher.Main.doAction(Main.java:33)

at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)

at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:60)

at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:37)

at org.gradle.launcher.GradleMain.main(GradleMain.java:23)

Caused by: org.cloudfoundry.client.v2.ClientV2Exception: CF-ServiceBrokerBadResponse(10001): Service broker error: UNKNOWN_ERROR - Failed to set credential permissions

at org.cloudfoundry.reactor.util.ErrorPayloadMapper.lambda$null$0(ErrorPayloadMapper.java:47)

at org.cloudfoundry.reactor.util.ErrorPayloadMapper.lambda$null$10(ErrorPayloadMapper.java:108)

at reactor.core.publisher.MonoThenMap$ThenMapMain.onNext(MonoThenMap.java:120)

at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67)

at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)

at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115)

at reactor.core.publisher.FluxUsing$UsingFuseableSubscriber.onNext(FluxUsing.java:351)

at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onNext(FluxFilterFuseable.java:103)

at reactor.core.publisher.FluxPeekFuseable$PeekFuseableConditionalSubscriber.onNext(FluxPeekFuseable.java:428)

at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:962)

at reactor.core.publisher.MonoReduceSeed$ReduceSeedSubscriber.onComplete(MonoReduceSeed.java:150)

at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:130)

at reactor.ipc.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:375)

at reactor.ipc.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:198)

at reactor.ipc.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:338)

at reactor.ipc.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:343)

at reactor.ipc.netty.channel.ChannelOperations.onHandlerTerminate(ChannelOperations.java:419)

at reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:566)

at reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:125)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)

at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1240)

at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1041)

at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)

at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)

at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)

at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:624)

at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:559)

at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:476)

at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)

at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)

Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 

Assembly trace from producer [reactor.core.publisher.MonoPeek] :

reactor.core.publisher.Mono.checkpoint(Mono.java:1400)

org.cloudfoundry.reactor.client.v2.servicebindings.ReactorServiceBindingsV2.create(ReactorServiceBindingsV2.java:52)

org.cloudfoundry.operations.services.DefaultServices.requestCreateServiceBinding(DefaultServices.java:693)

org.cloudfoundry.operations.services.DefaultServices.createServiceBinding(DefaultServices.java:452)

org.cloudfoundry.operations.services.DefaultServices.lambda$bind$1(DefaultServices.java:130)

org.cloudfoundry.util.tuple.TupleUtils.lambda$function$8(TupleUtils.java:69)

reactor.core.publisher.MonoThenMap$ThenMapMain.onNext(MonoThenMap.java:120)

reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:962)

reactor.core.publisher.MonoThenMap$ThenMapMain$ThenMapInner.onNext(MonoThenMap.java:237)

reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:962)

reactor.core.publisher.MonoWhen$WhenCoordinator.signal(MonoWhen.java:249)

reactor.core.publisher.MonoWhen$WhenInner.onNext(MonoWhen.java:308)

reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)

reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:72)

reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:962)

reactor.core.publisher.MonoSingle$SingleSubscriber.onComplete(MonoSingle.java:169)

reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:739)

reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:511)

reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:491)

reactor.core.publisher.FluxFlatMap$FlatMapMain.onComplete(FluxFlatMap.java:484)

reactor.core.publisher.MonoFlatMap$FlatMapInner.onComplete(MonoFlatMap.java:245)

reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainAsync(FluxFlattenIterable.java:317)

reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:616)

reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onComplete(FluxFlattenIterable.java:258)

reactor.core.publisher.FluxBuffer$BufferExactSubscriber.onComplete(FluxBuffer.java:179)

reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:183)

reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:79)

reactor.core.publisher.FluxBuffer.subscribe(FluxBuffer.java:72)

reactor.core.publisher.FluxFlattenIterable.subscribe(FluxFlattenIterable.java:104)

reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:183)

reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:173)

reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76)

reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)

reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:235)

reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)

reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:108)

reactor.ipc.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:207)

reactor.ipc.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:322)

reactor.ipc.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:316)

reactor.ipc.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:581)

reactor.ipc.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:125)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)

io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

reactor.ipc.netty.http.HttpOperations.lambda$static$3(HttpOperations.java:261)

reactor.ipc.netty.ReactorNetty$ExtractorHandler.channelRead(ReactorNetty.java:328)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)

io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1240)

io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1041)

io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)

io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)

io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)

io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)

io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)

io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)

io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:624)

io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:559)

io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:476)

io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)

io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)

Error has been observed by the following operator(s):

|_	Mono.checkpoint(ReactorServiceBindingsV2.java:52)

|_	Mono.checkpoint(DefaultServices.java:133)

Incorrect routes mapped for apps with context paths

Note: I'm currently using the Staging version to work around #58.

Here's my manifest:

applications:
- name: my-app
  routes:
  - route: my-hostname.my.domain/my/path

where the hostname is my-hostname, the configured domain is my.domain and the context path is /my/path.

After BGD, this is the output of cf app my-app:

name:   my-app
routes: my-app-new.my.domain, my-app-new.my.domain/my/path, my-hostname.my.domain

Instead of the expected single route, I see 3 different ones (all of them incorrect).

  1. The specified route my-hostname.my.domain/my/path is not mapped at all.
  2. Instead, the non-context route my-hostname.my.domain is mapped. This may break other apps which map to the generic route.
  3. The my-app-new route is now blocked by this app. If we were to run BGD for the same app in a different space (with the same domain), it would fail with a "route already in use" error.

-f argument not used

We are seeing behaviour that looks like the argument to -f is not being used.
When we create a manifest.yml file, place it in the current directory, and run cf blue-green-deploy myapp, the output clearly states:
Using manifest file /path/to/manifest.yml

However, running the command from some other directory with -f /path/to/manifest.yml added to the command arguments causes that same statement not to be output & our deployment fails.

We were not sure whether the -f argument is still supported because it does not appear in the help statement for blue-green-deploy, although it is present in the plugin README.md.

Unable to map route because it doesn't exist (yet it clearly exists)

In v1.3.0 (this works on v1.1.0, but not on v.1.3.0 after I updated).

Could not map route - Domain my-app-route.my-domain.io not found

The plugin appears to be unable to map the "live" route to the -new app, giving the error above. When I look at the routes for this space, I definitely see it in the list.

It should also be noted that (because IT bureaucracy) my app names contain underscores and my routes contain dashes (eg: my_app -> my-app.my-domain.io). When bgd is creating the route for the -new app, it creates the route as my_app-new.my-domain.io. That's not a technically valid hostname, but cloud foundry (at least the version used on predix) doesn't seem to have a problem with it.

Need better error when fail to get default shared domain

I'm trying to use the blue-green-deploy plugin, but keep getting the error "Failed to get default shared domain". I enabled CF_TRACE=true to see the request/response, and the response looks OK to my untrained eye.

REQUEST: [2016-07-10T02:55:48Z]
GET /v2/shared_domains HTTP/1.1
Host: api.stage1.ng.bluemix.net
Accept: application/json
Authorization: [PRIVATE DATA HIDDEN]
Content-Type: application/json
User-Agent: go-cli 6.20.0+25b1961 / linux

RESPONSE: [2016-07-10T02:55:49Z]
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: Keep-Alive
Content-Type: application/json;charset=utf-8
Date: Sun, 10 Jul 2016 02:55:49 GMT
Server: nginx
X-Backside-Transport: OK OK
X-Content-Type-Options: nosniff
X-Global-Transaction-Id: 417843439

1e5
{
"total_results": 1,
"total_pages": 1,
"prev_url": null,
"next_url": null,
"resources": [
{
"metadata": {
"guid": "80f7b34d-0c35-47d5-b14a-c0974a9d9b8c",
"url": "/v2/shared_domains/80f7b34d-0c35-47d5-b14a-c0974a9d9b8c",
"created_at": "2014-05-21T14:53:48Z",
"updated_at": null
},
"entity": {
"name": "stage1.mybluemix.net",
"router_group_guid": null,
"router_group_type": null
}
}
]
}
0

Failed to get default shared domain

//=======================================================

I see the implementation of 'DefaultCfDomain' in main.go, and it seems to me that it should be able to find 'stage1.mybluemix.net' when using statement 'response.Resources[0].Entity.Name'. Can anyone help? I definitely think propagating more of the error back to the user than just saying the DefaultCfDomain can't be found would be helpful.

func (p *CfPlugin) DefaultCfDomain() (domain string, err error) {
    var res []string
    if res, err = p.Connection.CliCommandWithoutTerminalOutput("curl", "/v2/shared_domains"); err != nil {
        return
    }

    response := struct {
        Resources []struct {
            Entity struct {
                Name string
            }
        }
    }{}

    if err = json.Unmarshal([]byte(res[0]), &response); err != nil {
        return
    }

    domain = response.Resources[0].Entity.Name
    return
}

Support -p push parameter

This plugin is exactly what I've been looking for, but I'm deploying a Java application that's packaged into an executable jar. Specifying the path in a manifest file isn't simple, because the manifest expects a literal filename and can't glob or substitute placeholders, and bgd doesn't support the -p to specify what to push. With a regular cf push, I can cf p app -p target/app-*.jar.

Temporary smoke test route does not use domain defined in the app manifest

I'm trying to Blue-Green deploy a CF application but my smoke tests always fail because the cf-blue-green-deploy plugin maps a testing route with domain mybluemix.net instead of the domain defined in my manifest (ng.bluemix.net).

I see that the exising cf-blue-green-deploy code parses the manifest for the domain, but uses the domain provided by DefaultCfDomain() even if a domain is defined in the manifest.

Parameter -f manifest file not used

Hello,

When I try to specify a custom manifest file, the plugin don't used it, but the default manifest.yml.

cf blue-green-deploy batch -f manifest-batch.yml

Result:

Using manifest file /var/jenkins_home/workspace/project_develop/manifest.yml

Route is not removed after DeleteAppVersions cleans up the app

Hello,

A while ago, I noticed that PCF does not remove the route itself, when app is removed. I discovered it, when I ran cf delete-orphaned-routes -f in a space, that was used by Jenkins for some time - there were a lot of old, unused routes, all with "-new" suffix.

Maybe it's a good idea to implement that into the code, to completely clean up after itself? The command is simply cf delete-route [routeName]-new -f.

No 64-bit Windows version available

I just attempted to install this plugin on Windows, and I received a message saying "Plugin requested has no binary available for your OS: windows, amd64".

Given that this plugin is written in Go, that's rather surprising to me. Is there a reason for the lack of a Windows version?

-f reports error finding manifest and then proceeds to work!

There's an erroneous (and rather confusing) error about reading the manifest followed by a successful read of the manifest! :-)

$ cf blue-green-deploy gordon-test-dev -f gordon-manifest.yml
Error finding manifest: stat manifest.yaml: no such file or directory
Using manifest file gordon-manifest.yml`

Creating app gordon-test-dev-new in org XXXXX / space XXX as XXXX...
OK

go get not working for the project due to changed dependencies in cloudfoundry/cli project

I am trying to perform go get after forking the repository to fix #3 and am getting below errors due to change in cloudfoundry/cli project

package github.com/cloudfoundry/cli/cf/configuration/config_helpers: cannot find package "github.com/cloudfoundry/cli/cf/configuration/config_helpers" in any of:
        $GOROOT
        $GOPATH
package github.com/cloudfoundry/cli/cf/configuration/core_config: cannot find package "github.com/cloudfoundry/cli/cf/configuration/core_config" in any of:
     $GOROOT
     $GOPATH
package github.com/cloudfoundry/cli/plugin/fakes: cannot find package "github.com/cloudfoundry/cli/plugin/fakes" in any of:
        $GOROOT
        $GOPATH

the above erring dependencies should look like below now

"github.com/cloudfoundry/cli/cf/configuration/confighelpers"
"github.com/cloudfoundry/cli/cf/configuration/coreconfig"
"github.com/cloudfoundry/cli/plugin/pluginfakes"

There will be fixes to getSpaceGuid function accordingly.

I have done these fixes in my fork but now found internationalization is also broken in main.go

[Feature Request] Provide rollback feature

some time real-time application scenario after release if we need to rollback to previous running instance e.g. "app-name-old". currently we need to all this steps manually. it will be great helpful to provide rollback from "app-name" to makr as "app-name-failed" and "app-name-old" to "app-name".

Support building on Go 1.6+

As per the pull request #12, this project does not build on Go 1.6+. Instead, it gets the following error:

./main.go:173: cannot assign "github.com/nicksnyder/go-i18n/i18n".TranslateFunc to "github.com/cloudfoundry/cli/cf/i18n".T (type "github.com/cloudfoundry/cli/vendor/github.com/nicksnyder/go-i18n/i18n".TranslateFunc) in multiple assignment

This is caused by the lines:

    // T needs to point to a translate func, otherwise cf internals blow up
    i18n.T, _ = go_i18n.Tfunc("")

And is due to a change about how Go handles vendored dependencies in Go 1.6+. This is present in Go 1.5, but is off by default. It is on by default in Go 1.6, but can be turned off by setting GO15VENDOREXPERIMENT to 0. It will be on by default in Go 1.7, and will not be able to be turned off.

The suggested fix for the issue is:

main.go:170

-       // T needs to point to a translate func, otherwise cf internals blow up
-       i18n.T, _ = go_i18n.Tfunc("")

manifest_test.go:15

+type localeGetter struct{}
+
+func (l localeGetter) Locale() string {
+       return "en-us"
+}
+
 var _ = Describe("Manifest reader", func() {
        // testing code that calls into cf cli requires T to point to a translate func
-       i18n.T, _ = go_i18n.Tfunc("")
+       i18n.T = i18n.Init(localeGetter{})

Feature request: Scale down number of instances of non-routeable app

I've been playing around with bgd on a dev instance of CF, and I noticed that after the process finishes, both applications have the same number of instances. For example, I have an app called "test", and I scale it to 10 instances, and then I use bgd and it is successful, I don't think there's any reason why "test-old" needs to still have 10 instances after the process completes. Same would apply in the failure case, if the smoke tests fail there's no reason why "test-failed" needs to have 10 instances.

I would be happy to take a stab at writing a PR for this, but I'd like to verify that what I'm proposing makes sense. Thanks!

blue-green-deploy does not respect host setting in manifest

Hi,

we have following case:

manifest-base.yml

---
memory: 768M
instances: 1
path: ../target/pipeline-test.war
domain: domain.com
---

manifest-sbx.yml

---
inherit: manifest-base.yml
applications:
- name: pipeline-test
  host: pipeline-test-sbx

When executing blue-green-deploy command the output looks as follows:

Using manifest file manifests/manifest-sbx.yml

Creating app pipeline-test-new in org *** / space sandbox as ****...
OK

Creating route pipeline-test-new.domain.com...
OK

Binding pipeline-test-new.domain.com to pipeline-test-new...
OK

Route creation seems to take the value of the parameter name and does not honor host.

Parameter host should take precedence if available. I guess this is a bug.

Best regards,
Oliver

Routes in manifest specified with domains only are not bound

We found an issue using the blue-green-deploy plugin. We think this arises from here: https://github.com/bluemixgaragelondon/cf-blue-green-deploy/blob/master/manifest.go#L22

Given an app manifest with an app name and domains:


---
applications:
- name: test-app
  domains:
  - testing.com

When the app is deployed using the blue-green-deploy plugin
And the deployment is successful
Then the app has no routes

Is there a reason that host is required in manifest.yml? Would you accept a pull request to resolve this issue?

Scale factor is reset to 1 after update

When performing a blue-green deployment (update) on an app which has been scaled to multiple instances, the upgraded app is scaled to one while the old app remains scaled to its original number of instances.

Before blue-green-deploy:

name             requested state   instances   memory   disk   urls
static-app       started           5/5         64M      1G     static-app-macrodont-custos.cfapps.io

After blue-green-deploy:

name             requested state   instances   memory   disk   urls
static-app       started           1/1         64M      1G     static-app-macrodont-custos.cfapps.io
static-app-old   started           5/5         64M      1G

Expected: static-app instances 5/5, static-app-old instances 1/1

Domain in manifest.yml is not recognized

My CF has 2 shared domains. Seems like the plugin is not detecting the domain specified in manifest.yml and creates "new" and "old" routes on the default one.
The final app is however on the domain specified in manifest.

[Feature] Allow specifying manifest files

Currently, there is no possibility to explicitly specify a manifest when doing a blue-green deploy. I would like to be able to do something like the following:

cf bgd manifest-uat.yml app-name --smok-tests ./smoke_tests.sh

This can be worked around by putting the manifest files in separate directories, but that doesn't feel like a great solution, and makes working with them more awkward than it needs to be.

Please release new version on CF-Community

The README:

  • provides instructions for installing from CF-Community
  • mentions the new --delete-old-apps flag

However, the published version does not include support for that flag:

$ cf blue-green-deploy <app_name> --delete-old-apps
flag provided but not defined: -delete-old-apps
Usage of blue-green-deploy:
  -f string

  -smoke-test string

Sometimes plugin skips renaming current app as old

Hello,

We are not completely sure if this is a problem with the plugin or maybe CF ? We are running the open source CF v275 and we have noticed sometimes our deployment fails with
cf-cli: cf version 6.32.0+0191c33d9.2017-09-26
plugin: 1.2.0 (it reports 1.1.0 but file hash wise, we are running 1.2.0, see #42)

Renaming app myapp-new to myapp in org myorg / space live as [email protected]...
Could not rename app - Server error, status code: 400, error code: 100002, message: The app name is taken: myapp

Looking at the log, there is no step where it renames the current myapp as myapp-old.
Retrying our deployment job a few times makes it work and as expected, on those deployments the renaming from myapp as myapp-old happens as expected.

We haven't found a way to reproduce this, it just randomly happens.

If you need more information, please let me know.

Routes containing hostname.domain are not resolved correctly

Say we have a domain my.domain defined in our org. We want to map one of our services to the hostname my.hostname and context path /my/path. So the full route becomes https://my-hostname.my.domain/my/path.

If the app manifest contains a route entry, the plugin tries to resolve the entire value as the domain. For example:

applications:
- name: my-app
  routes:
  - route: my-hostname.my.domain/my/path

This gives the error:

Could not map route - Domain my-hostname.my.domain not found

Note: The new CF guidelines recommend using only the routes element - Attribute routes Replaces domain, domains, host, hosts, and no-hostname

Fails to support deployment of multiple apps via single manifest

In our recent attempt to deploy multiple apps via single manifest using the blue-green-deploy plugin it was noticed that it failed with error :
Could not push new version - Incorrect Usage. Command line flags (except -f) cannot be applied when pushing multiple apps from a manifest file.

Is there a work around for it?

Feature proposal: deploy with "copy-app" rather than "push", for Continuous Delivery

I am trying to use a Continuous Delivery style with a “staging” server for UAT and a “live” server for production.

When deploying to "live", I would like to deploy with “cf copy-app” to promote the code from “staging” to “live”, rather than "cf push", which will deploy whatever version of code is present on the invoking machine. This is so that I can be confident that the deployed code is the same as the code that has been through UAT.

To support this, cf-blue-green-deploy would need a new flag to fetch the app source from an app in a different space using cf copy-app.

Random-route not used on Green app

Hi,
It would be great for us if the deployment of the Green app could use 'random-route' if specified in the manifest. The copy of the plugin we are using now always deploys the Green app with a route of <app_name>-new., which has the potential to cause route conflict.

As an aside, the plugin does correctly carry out a blue-green deploy on an existing random route that is attached to the Blue copy of an app.
Thanks

Could not map route with context path

after upgrade bgd to 1.3, it can't map a route to new app. Error message is : Could not map route - Error resolving route:
ENV
cli version : cf version 6.35.0
bgd version : 1.3.0

my cloud foundry has 2 shared domains.
np1.paas.com
np.paas.com

manifest file :
applications:

  • name: api-service
    instances: 2
    memory: 500M
    routes:
    • route: api-service.np.paas.com
    • route: api-service.np.paas.com/api
      path: ./api-service.jar

New app has unexpected url in environment variable

Observed Error:

Environment variable url from (bluemix) IBM Cloud is suffixed with -new at the end of the subdomain.
Malformed subdomain is suffixed to a route that should have no subdomain.
Example from manifest below:

a-mybluemix-app-new.a-system-domain.ibm.com

Expected Result:

url environment variable should be the same as if the app were deployed normally with cf push $CF_APP. -new and -old should not be part of the url.

How:

Using cf-blue-green-deploy from staging.
NodeJS app with passport-idaas-openidconnect and express dependencies.
Manifest.yml like:

applications:
- name: a-mybluemix-app
  buildpack: sdk-for-nodejs
  command: node dist/app.js
  routes:
  - route: a-system-domain.ibm.com
  - route: a-mybluemix-app.mybluemix.net

Workaround:

Custom deploy script where existing is renamed and new deploy isn't given an unexpected app name. Routing is taken from manifest.

trap reportError ERR
reportError() {
    set +e

    if cf app "${CF_APP}_OLD"; then
        cf delete $CF_APP -f
        cf rename "${CF_APP}_OLD" $CF_APP
    fi

    exit 1
}

if cf app $CF_APP; then
    cf rename $CF_APP "${CF_APP}_OLD"
fi

cf push $CF_APP
cf delete -f "${CF_APP}_OLD"

Intermittent unit test failure: "BGD Plugin blue green flow when app has manifest when manifest uses hosts and domains [It] maps manifest routes"

BGD Plugin blue green flow when app has manifest when manifest uses hosts and domains [It] maps manifest routes 
/home/pipeline/be79174d-cd79-4dbd-9beb-e241fddffc4a/go/src/github.com/bluemixgaragelondon/cf-blue-green-deploy/main_test.go:192

  Expected
      <[]plugin_models.GetApp_RouteSummary | len:1, cap:1>: [
          {
              Guid: "",
              Host: "app-name-new",
              Domain: {Guid: "", Name: "specific.net"},
              Path: "",
              Port: 0,
          },
      ]
  to consist of
      <[]interface {} | len:1, cap:1>: [
          {
              Guid: "",
              Host: "app-name-new",
              Domain: {Guid: "", Name: "specific.com"},
              Path: "",
              Port: 0,
          },
      ]

This failure seems to happen about 1 in 10 builds. The root cause seems to be some randomness in whether the first or second domain listed in the manifest is used. There are also occasional acceptance test failures with a similar symptom.

Basic auth prevents health check

We have a basic auth protection for our app. Unfortunately that leads to a 401 http code which is treated as an error. Could you change the check so that it does not fail the code?

 state     since                    cpu    memory          disk           details   
#0   running   2016-07-26 07:09:10 PM   0.0%   79.5M of 256M   110.7M of 1G      
+ curl --fail -I https://xyz-B.eu-gb.mybluemix.net
curl: (22) The requested URL returned error: 401 Unauthorised
++ on_fail
++ finally
++ rm /var/folders/gb/xyz_manifest.XXXXXXXXXX.eZF3dqmA
++ echo 'DEPLOY FAILED - you may need to check '\''cf apps'\'' and '\''cf routes'\'' and do manual cleanup'
DEPLOY FAILED - you may need to check 'cf apps' and 'cf routes' and do manual cleanup

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.