PCF Credhub Service broker - Unable to rotate credentials and demands restart - cloud-foundry

I created a credhub instance and stored my secrets using below cf command
cf create-service credhub default my-secrets -c "{\"secretMessage\":\"1234567\"}"
My spring boot app picks up the secretMessage value without any issue. And now i executed update-service command and rotated the secretMessage with the below command
cf update-service my-secrets -c "{\"secretMessage\":\"1234567-updated\"}"
But my spring-boot app isn't picking the updated one unless and untill I restart the app in PCF.
Is there any way to pick up the rotated-credentials without restart ?

But my spring-boot app isn't picking the updated one unless and untill I restart the app in PCF.
Is there any way to pick up the rotated-credentials without restart ?
No, that is the expected behavior.
https://docs.pivotal.io/credhub-service-broker/using.html#update
Your service instance is bound to your app. Like all service instances bound to an app, it's providing information through the VCAP_SERVICES environment variable. Environment variables, including VCAP_SERVICES, are only updated when you restart the app.
You might be thinking, wait my VCAP_SERVICES has placeholders from CredHub, shouldn't those automatically update? Unfortunately no. The Diego lifecycle is responsible for looking up CredHub place holders and resolving them. This runs prior to your application starting. It then puts the actual value into VCAP_SERVICES. This is how your app can see the actual value and not the place holders, while simultaneously not having any knowledge about CredHub.

Related

Can we change/modify the environment in PCF (Pivotal Cloud Foundy) at Runtime?

We use Pivotal Cloud Foundry's YML file to set up the environment. Everything is fine. According to DEVOPS if we have to modify/create an environment variable, we have to modify YML and push the app again. I am wondering if it is possible to modify/create an environment variable while the PCF app is running. It will be really cool if it can be done without having to redeploy the app. If it can't be done, is it because of Java's way of handling the environment?
Thanks
Can we change/modify the environment in PCF (Pivotal Cloud Foundy) at Runtime?
Yes and no.
You can modify environment variables associated with an application while the application is running using the cf set-env (to set or update) and cf unset-env (to delete).
This will update the environment variable in Cloud Controller at the time you run the command. However, this will not update the environment variable inside of a running application container. In order for your application to see the change that you made, you must cf restart, cf restage or cf push.
This has nothing to do with language specifics (i.e. it doesn't matter what language you're using). It is a requirement because the container where your application is running gets created with a fixed set of environment variables. When those change, the container must be recreated. That said, even if the container could be changed at runtime, in Linux a process' environment variables cannot be updated externally at runtime either (there are technically some ways to do this, but it's really unlikely you'd do this in practice). The process itself should be restarted for environment variables to change.
If you want to have your configuration update at runtime, you can look at something like Spring Cloud Config server & its refresh capabilities. That said, it turns out that most applications and frameworks assume configuration is read once while the app is starting up, so your application would need to support changing the configuration you want to change at runtime as well.

Difference between cf push and cf restage

I have a app which is pushed to cf using cf push. Now I have changed the one of the environment variable and then restage the app using cf restage. What I understand is when we do a restage it will again compile the droplet and build it same can be done with cf push again for the app. So what I want to know is the difference between the 2 commands and how internally cf handles this?
The difference is that one uploads files and one does not.
When you run cf push, the cli is going to take bits off your local file system, upload them, stage your app and if that succeeds, run your app. This is what you want if you have made changes to files in your app and want to deploy them.
When you cf restage, the cli is not going to upload anything. It will just restage your app, and if that succeeds, run the app. This is what you want if there are no app change or you do not have the app source code, yet you want to force the build packs to run again & restart your app using the new droplet.
When you cf restart, the cli won't upload or restage, it will just stop and start the app. This is the fastest option, but only works if you just need to pick up environment changes like a changed service, memory limit or environment variables. It's also good, if you just want to try and have your app placed onto a different Diego Cell.
If you are just making changes to environment variables, you can probably get away with a cf restart, unless those environment variables are being used by one of your buildpacks, like JBP_CONFIG_*.
Hope that helps!
Regarding
So what I want to know is the difference between the 2 commands
cf push internally does the following sequence
uploading : creating a package from your app
staging : creating a container image using the package
starting : starting the container as a long running process, based on the container image
Some use cases where we need to restage
To introduce buildpack changes : CF operators update the buildpacks for various reasons (one example: security patches) effectively updating the runtime dependencies which our apps use.
Introduction of new software components : It might be possible that we need to introduce new / additional components which were not foreseen at the time of initial push. An example can be : introduction of monitoring agent for your app
When the root file system is changed.
In all the 3 scenarios above, our application code is not changing but we need to re-create the container image. In these cases we need to restage. If we compare with cf push , in case of restage we skip the package creation step.

Any way with Jenkins to select Spring Boot profile?

My group is using Jenkins to build and deploy a Spring Boot application to AWS (Elastic Beanstalk).
For development I was selecting the desired profile for the environment I was in (DEV, QA) by setting the spring.profiles.active property in application.properties.
But dev-ops would like to set the property externally. Since the app is being deployed to a SpotInst managed EC2, I have no control over the environment.
I've been doing a lot of searching, but haven't as yet come across anything that fits this situation.
I'm using Gradle for building. The build generates a WAR file and is deployed to Tomcat.
Is there anyway to accomplish this with some sort of parameter substitution?
Thanks.
Our devOps person discovered that we can set environment properties through AWS Beanstalk. By going to Configuration on the beanstalk instance and clicking on the Modify button under Software, scroll down and there is a section for environment variables. He put in spring.profiles.active=qa and that took care of it.
Since we have one beanstalk for each separate environment, it only has to be set once for each.
I am not sure if this will fit into your devOps process but there is very easy and clean way to achieve this.
Configure your application.yaml file like below:
spring:
profiles:
active: ${SPRING_PROFILE:"dev"}
And while starting the application pass this parameter SPRING_PROFILE as command line argument. Note that dev is default value which will be used if the program doesn't find any matching command line argument or environment variable.
You can set the default value to the one you want to use for devOps while for all other purpose where you can control you can pass as argument.

CF set-env without restage

Let's say I would have one app with two instances.
I would change an environment variable (cf set-env) and not perform a cf restage.
Eventually one of the two instances would crash and restart. Would it take the new environment variable or the old?
In general if an instance crashes (say the app runs out of memory) and is restarted by Diego (the runtime that's actually running the container instances), the restarted instance will still have the environment variables it was originally "desired" (created) with.
If you explicitly cf restart or cf stop && cf start the app it will pickup the new environment variables which out needing to be restaged.
As user152468 said above, if the environment variables are used during the staging process you will need to cf restage the app for them to functionally take effect.
Edge Case Scenario
If the Diego runtime goes away/loses data for some catastrophic reason, the Cloud Controller will re-sync it and recreate the apps that are meant to be running. In this event the behavior is similar to a cf restart and the app will pick up the new environment variables. This is definitely uncommon, but would also count as a "crash" scenario.
EDIT:
After reading tcdowney's answer below, I tried it out. And tcdowney is right. When the app is restarted due to a crash, it will not pick up the new environment variable, so both of your app instances will share the same environment.
In contrast when you do a cf restart my-app then it will pick it up. Sorry for the confusion!
========================================================
It would take the new value of the environment variable. See here: https://docs.run.pivotal.io/devguide/deploy-apps/start-restart-restage.html
Only if the variable is relevant for the buildpack, you will need to restage.

Drupal on Elastic Beanstalk Redirects to Install.php on "eb deploy"

I am encountering what I believe to be permission issues when trying to deploy a Drupal application onto Elastic Beanstalk
I followed this tutorial to get Drupal up and running: http://comm-press.de/en/blog/drupal-climbs-aws-elastic-beanstalk
I am using a Postgres database and I am entering the correct credentials when filling out the forms on install.php, without error.
Any subsequent deploys after the initial deploy brings me back to install.php. After entering in my database information, I get this message, telling me Drupal is already installed (which it is).
http://i.imgur.com/N6KDvvo.png
Why does my site get redirected to install.php after 'eb deploy'? What permissions should I set my drupal folder such that settings.php and /sites/default/files is generated?
The install state is controlled by the DB-- if Drupal bootstraps with no DB information, you are routed to the code that asks you for it.
I was able to bypass this part by setting up a AWS RDS DB and connecting all instances to it.
--But, wait, there's more. Now that having all the instances reading from the same DB has squashed most of the concurrency problems between instances*. Go ahead, try and add a photo to your admin profile. I will wait. Yep, most of the time you'll get the wrong instance and the single image on one instance is not shown on all instances.
I am working on solving that problem with a start up & cron job script that loads updates to resources from the AWS S3 service.
Step A load code into S3
Step B set an accessible timestamp for $lastModified to now()
Step 1 wget/curl a timestamp of the last remote modification ($lastModified)
Step 2 compare the local last updated stamp ($lastUpdated) to remote last modified timestamp
Step 3 if ($lastModified == $lastUpdated) {die} else {update incremental changes && set $lastUpdated = $lastModified}
Watch that first incremental update, it's a doozy.
So... additionally I should mention that we are installing completely vanilla drupal when we instantiate an image, as part of the Docker file from drupal the drupal apache image the last thing the Docker file runs is a setup script.
Elastic Beanstalk sets Environment variables-- some of those variables are the amazon access key id and access secret key.
I curl an IP only available inside of Elastic Beanstalk curl -v 169.254.169.254
From that output in the setup script I can tell if I am local AWS EB or in AWS EB. That allows me to conditionally change certain configurations-- like connecting RDS or a local MySQL DB to Drupal.
The setup script uses aws cli to pull from S3 (sync) to add, replace, update everything in the webroot turning the instance into a setup Drupal installation as far as file level assets go.
sed and service reload is done a lot. Elasticache vs local Redis...
last we start the web server in the foreground && tail -f /dev/null so the container doesn't immediately close.
Drupal is just for static assets pages and a header/menu/footer wrapper for our web app (templates are served..., Twig/JS fills the template in with data). Authentication happens via API-- not even using 90% or so of the goodness in Drupal...
Incremental changes are pulled by comparing hash values and acting to run the update process if they are different.