We’re investigating the CF run-task command from the cli. This is used to execute tasks that run to completion, like database migrations or print something to the console 😉
Hello console
We’ve created a new console project. The main function will print the first command-line argument. Everybody is familiar with “hello world“.
The key to getting this to work on Cloud Foundry is the manifest.yml:
applications: - name: hellotaskworld path: bin/Debug/netcoreapp2.0/ instances: 0 memory: 256M no-route: true buildpacks: dotnet_core_buildpack
instances: 0 makes sure the container is not started. It would crash-and-burn since the application exits after it prints to the console. Cloud Foundry wants to have continuously running applications like a webapp.
no-route: true binds no route to the application. It cannot serve web requests.
path: bin/Debug/netcoreapp2.0/ together with buildpacks: dotnet_core_buildpack pushes the assembly and leaves the dotnet runtime in the container
After a CF PUSH we can run the application with the CLI:
cf run-task hellotaskworld "dotnet ./HelloTaskWorld.dll eric" --name hello-eric-task cf tasks hellotaskworld
id name state command 3 hello-eric-task SUCCEEDED dotnet ./HelloTaskWorld.dll eric
To get the console output we request the logs
cf logs hellotaskworld --recent
[CELL/0] OUT Creating container [CELL/0] OUT Successfully created container [APP/TASK/hello-eric-task/0] OUT Hello eric! [APP/TASK/hello-eric-task/0] OUT Exit status 0 [CELL/0] OUT Stopping instance 1dc5766e-f3f4-4b0d-9332-e1e761db911d [CELL/0] OUT Destroying container [CELL/0] OUT Successfully destroyed container
Success! We’ve send our message to Cloud Foundry.
Hello web
What about web applications? We will be deploying our website to Cloud Foundry and want our hello eric (or database migration, file cleanup, backups, …) to be run from that application.
With dotnet core the starting point of a web application is again the Main function. We can check the command-line arguments for our custom tokens.
❗ warning ❗ Cloud Foundry uses command-line arguments to configure the application: ./websitename –server.urls http://0.0.0.0:1234. Make sure your argument name is different/unique.
public static void Main(string[] args) { if (args[0] != "--name") { BuildWebHost(args).Run(); } else { // start task and print to console Console.WriteLine($"Hello {args[1]}"); } }
The manifest is very simple since the main use case is a web application.
applications: - name: webwithtask instances: 1 memory: 256M
After a CF PUSH we can run the application with the CLI. The location of the assembly we got from the logging of the PUSH which shows the command to run
type: web instances: 1/1 memory usage: 256M start command: cd ${DEPS_DIR}/0/dotnet_publish && ./WebWithTask --server.urls http://0.0.0.0:${PORT} state since cpu memory disk details #0 running 2019-09-06T10:24:32Z 0.0% 156K of 256M 104.2M of 1G
Now we can start the task by adding the –name parameter to get to the else branch in the main function.
cf run-task webwithtask "cd /home/vcap/deps/0/dotnet_publish && ./WebWithTask --name eric" --name hello-eric-task cf tasks webwithtask
id name state command 1 hello-eric-task SUCCEEDED cd /home/vcap/deps/0/dotnet_publish && ./WebWithTask --name eric
To get the console output we request the logs
cf logs webwithtask --recent
[CELL/0] OUT Creating container [CELL/0] OUT Successfully created container [APP/TASK/hello-eric-task/0] OUT Hello eric [APP/TASK/hello-eric-task/0] OUT Exit status 0 [CELL/0] OUT Stopping instance 12af1740-dec5-4975-96a8-85713102045d [CELL/0] OUT Destroying container [CELL/0] OUT Successfully destroyed container
Success! We’ve send our message to Cloud Foundry.
References
https://docs.cloudfoundry.org/devguide/using-tasks.html
https://github.com/cloudfoundry/dotnet-core-buildpack/issues/163
https://dotnet-cookbook.cfapps.io/core/app-startup-tasks/