When you’re packaging your bespoke systems as BOSH releases, over and over again, you will first need a Ruby/Java/Golang/Python package for compilation or runtime. The BOSH community is now providing language packs to make it much simpler and faster. This article is a quick look and a "build a BOSH release" walk thru using the Go language pack (you can also see the resulting BOSH release).
The primary bosh
command you’ll need to learn is bosh vendor-package
, and then how/when to use the compile.env
and runtime.env
scripts that are bundled with each language pack.
Find them all at https://github.com/bosh-packages. At the time of writing, the available language packs are:
- java – openjdk-8 and openjdk-9
- golang – golang-1.9 and golang-1.10
- ruby – ruby-2.4-r3
- python – python-2.7
Want to help make the world a better place? Pull requests for ruby-2.5 and python-3.6 would be welcomed by me so I can use them.
Note, afaik, the BOSH core team, doesn’t call them "language packs". Yet.
I like "language packs", though "language releases" or packages may sound more familiar. – Dmitriy
Probably because there are other "packs" you can use that aren’t programming languages: cf-cli and nginx. But I like the phrase "language packs". Your thoughts?
Walk Through
Let’s package up a sample Golang web app as a BOSH release.
First, clone the sample app locally and confirm that you know how to compile and run it:
go get github.com/cloudfoundry-community/simple-go-web-app
cd $GOPATH/src/github.com/cloudfoundry-community/simple-go-web-app
export MESSAGE="this is the message to display"
export PORT=8000
go run main.go
Your sample Golang web app will now be running at http://localhost:8000/ and will display your $MESSAGE
:
$ curl http://localhost:8000
this is the message to display
Now, let’s package and run this via BOSH. First, create a workspace folder and clone the language pack. We’re using golang-release
to compile our Golang application:
mkdir -p ~/workspace
cd ~/workspace
git clone https://github.com/bosh-packages/golang-release
Create a new BOSH release project, or use an existing one, and vendor the language pack:
gem install bosh-gen
bosh-gen new simple-go-web-app
cd simple-go-web-app-boshrelease
I’m using bosh-gen because a) it makes everything in this article easier; and b) I wrote bosh-gen. This article assumes you’ve upgraded bosh-gen to v0.98.
Now, the first step of magic for language packs is the bosh vendor-package
command:
bosh vendor-package golang-1.10-linux ~/workspace/golang-release
The output will look like:
Adding package 'golang-1.10-linux/48c842421b6f05acf88dc6ec17f7574dade28a86'...
-- Started uploading 'golang-1.10-linux/48c842421b6f05acf88dc6ec17f7574dade28a86' (sha1=e9a18aebf2c407ce17423c22c913b6612cf4b75f)
2018/04/04 09:44:29 Successfully uploaded file to https://s3.amazonaws.com/sample-go-boshrelease/58b5770b-eff5-49f1-5b2d-f834dc80e4d3
-- Finished uploading 'golang-1.10-linux/48c842421b6f05acf88dc6ec17f7574dade28a86' (sha1=e9a18aebf2c407ce17423c22c913b6612cf4b75f)
Added package 'golang-1.10-linux/48c842421b6f05acf88dc6ec17f7574dade28a86'
Your BOSH release will now have a new package:
$ git status
.final_builds/
packages/golang-1.10-linux/
Commit it to your repo:
git add .
git commit -m "add golang-1.10-linux langage pack"
Submodule the sample Golang app into the src
folder:
git submodule add https://github.com/cloudfoundry-community/simple-go-web-app \
src/gopath/src/github.com/cloudfoundry-community/simple-go-web-app
Create a simple-go-web-app
BOSH package, that compiles itself with our golang-1.10-linux
language pack.
bosh-gen package simple-go-web-app \
-d golang-1.10-linux \
--src gopath
Update packaging/simple-go-web-app/packaging
to load the golang-1.10-linux
language pack and to go build
our application:
set -eux
cd gopath
source /var/vcap/packages/golang-1.10-linux/bosh/compile.env
go build -v github.com/cloudfoundry-community/simple-go-web-app
mkdir $BOSH_INSTALL_TARGET/bin
cp simple-go-web-app $BOSH_INSTALL_TARGET/bin
The source .../compile.env
is the second part of magic for language packs.
It does something different for each language pack, and for each base operating system. For the golang-release on linux, it sets up $GOROOT
and also sets $GOPATH
to the current directory.
So, in our packaging
script above, we first change to the base directory of our $GOPATH
and then run source /var/vcap/packages/golang-1.10-linux/bosh/compile.env
. We are now free to go build
to produce our linux binary simple-go-web-app
.
The java
language pack sets up $JAVA_HOME
and $PATH
.
Finally, we copy the binary into the $BOSH_INSTALL_TARGET
folder. Anything in this folder is part of the compiled BOSH package.
Next, we need a BOSH job to run our packaged simple-go-web-app
binary:
bosh-gen job simple-go-web-app -d simple-go-web-app
This command will override some default files in a pre-created jobs/simple-go-web-app
directory. That’s fine. Say yes to all prompts.
export BOSH_DEPLOYMENT=simple-go-web-app
bosh create-release --force && \
bosh upload-release --rebase && \
bosh deploy manifests/simple-go-web-app.yml -o manifests/operators/dev.yml
Once the packages have been compiled and the simple-go-web-app
instance is running, you can ping your web app on the default job port :8080
:
$ curl 10.244.0.2:8080
Hello world
Epilogue – CI Pipeline
To flesh out this example BOSH release, I’ve also added a CI pipeline, which publishes final releases, updates the base manifest manifests/simple-go-web-app.yml
with each version.
The CI pipeline, as well as, publishing compiled releases to S3, also creates a use-compiled-releases.yml
operator file.
To try it out:
bosh -d simple-go-web-app \
deploy <(curl -L https://raw.githubusercontent.com/cloudfoundry-community/simple-go-web-app-boshrelease/master/manifests/simple-go-web-app.yml) \
-o <(curl -L https://raw.githubusercontent.com/cloudfoundry-community/simple-go-web-app-boshrelease/master/manifests/operators/use-compiled-releases.yml)