Update docs
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
13ac528ae3
commit
385503f06c
1 changed files with 44 additions and 33 deletions
|
|
@ -1,27 +1,29 @@
|
|||
# Writing an external provider
|
||||
|
||||
External provider enables you to write a fully functional provider, using any scripting or programming language. Garm will then call your executable to manage the lifecycle of the instances hosting the runners. This document describes the API that an executable needs to implement to be usable by ```garm```.
|
||||
External provider enables you to write a fully functional provider, using any scripting or programming language. Garm will call your executable to manage the lifecycle of the instances hosting the runners. This document describes the API that an executable needs to implement to be usable by ```garm```.
|
||||
|
||||
## Environment variables
|
||||
|
||||
When ```garm``` calls your executable, a number of environment variables are set, depending on the operation. There are two environment variable will always be set regardless of operation. Those variables are:
|
||||
When ```garm``` calls your executable, a number of environment variables are set, depending on the operation. There are three environment variables that will always be set regardless of operation. Those variables are:
|
||||
|
||||
* ```GARM_COMMAND```
|
||||
* ```GARM_PROVIDER_CONFIG_FILE```
|
||||
* ```GARM_CONTROLLER_ID```
|
||||
|
||||
The following are variables that are specific to some operations:
|
||||
|
||||
* ```GARM_CONTROLLER_ID```
|
||||
* ```GARM_POOL_ID```
|
||||
* ```GARM_INSTANCE_ID```
|
||||
|
||||
### The GARM_COMMAND variable
|
||||
|
||||
The ```GARM_COMMAND``` environment variable will be set to one of the operations defined in the interface. When your executable is called, you'll need to look at this variable to know which operation you need to execute.
|
||||
The ```GARM_COMMAND``` environment variable will be set to one of the operations defined in the interface. When your executable is called, you'll need to inspect this variable to know which operation you need to execute.
|
||||
|
||||
### The GARM_PROVIDER_CONFIG_FILE variable
|
||||
|
||||
The ```GARM_PROVIDER_CONFIG_FILE``` variable will contain a path on disk to a file that can contain whatever configuration your executable needs. For example, in the case of the OpenStack external provider, this file contains variables that you would normally find in a ```keystonerc``` file, used to access an OpenStack cloud. But you can use it to add any extra configuration you need.
|
||||
The ```GARM_PROVIDER_CONFIG_FILE``` variable will contain a path on disk to a file that can contain whatever configuration your executable needs. For example, in the case of the [sample OpenStack external provider](../contrib/providers.d/openstack/keystonerc), this file contains variables that you would normally find in a ```keystonerc``` file, used to access an OpenStack cloud. But you can use it to add any extra configuration you need.
|
||||
|
||||
The config is opaque to ```garm``` itself. It only has meaning for your external provider.
|
||||
|
||||
In your executable, you could implement something like this:
|
||||
|
||||
|
|
@ -52,25 +54,20 @@ esac
|
|||
|
||||
### The GARM_CONTROLLER_ID variable
|
||||
|
||||
The ```GARM_CONTROLLER_ID``` variable is set for two operations:
|
||||
The ```GARM_CONTROLLER_ID``` variable is set for all operations.
|
||||
|
||||
* CreateInstance
|
||||
* RemoveAllInstances
|
||||
|
||||
This variable contains the ```UUID4``` identifying a ```garm``` installation. Whenever you start up ```garm``` for the first time, a new ```UUID4``` is generated and saved in ```garm's``` database. This ID is meant to be used to track all resources created by ```garm``` within a provider. That way, if you decide to tare it all down, you have a way of identifying what was created by one particular installation of ```garm```.
|
||||
|
||||
This is useful if various teams from your company use the same credentials to access a cloud. You won't accidentally clobber someone else's resources.
|
||||
When garm first starts up, it generates a unique ID that identifies it as an instance. This ID is passed to the provider and should always be used to tag resources in whichever cloud you write your provider for. This ensures that if you have multiple garm installations, one particular deployment of garm will never touch any resources it did not create.
|
||||
|
||||
In most clouds you can attach ```tags``` to resources. You can use the controller ID as one of the tags during the ```CreateInstance``` operation.
|
||||
|
||||
### The GARM_POOL_ID variable
|
||||
|
||||
The ```GARM_POOL_ID``` environment variable is an ```UUID4``` describing the pool in which a runner is created. This variable is set in two operations:
|
||||
The ```GARM_POOL_ID``` environment variable is a ```UUID4``` describing the pool in which a runner is created. This variable is set in two operations:
|
||||
|
||||
* CreateInstance
|
||||
* ListInstances
|
||||
|
||||
As is with ```GARM_CONTROLLER_ID```, this ID can also be attached as a tag in most clouds.
|
||||
As with the ```GARM_CONTROLLER_ID```, this ID **must** also be attached as a tag or whichever mechanism your target cloud supports, to identify the pool to which the resources (in most cases the VMs) belong to.
|
||||
|
||||
### The GARM_INSTANCE_ID variable
|
||||
|
||||
|
|
@ -87,7 +84,7 @@ We need this ID whenever we need to execute an operation that targets one specif
|
|||
|
||||
## Operations
|
||||
|
||||
The operations that a provider must implement are described in the ```Provider``` interface available [here](https://github.com/cloudbase/garm/blob/main/runner/common/provider.go#L22-L39). The external provider implements this interface, and delegates each operation to your external executable. These operations are:
|
||||
The operations that a provider must implement are described in the ```Provider``` [interface available here](https://github.com/cloudbase/garm/blob/223477c4ddfb6b6f9079c444d2f301ef587f048b/runner/providers/external/execution/interface.go#L9-L27). The external provider implements this interface, and delegates each operation to your external executable. [These operations are](https://github.com/cloudbase/garm/blob/223477c4ddfb6b6f9079c444d2f301ef587f048b/runner/providers/external/execution/commands.go#L5-L13):
|
||||
|
||||
* CreateInstance
|
||||
* DeleteInstance
|
||||
|
|
@ -97,11 +94,9 @@ The operations that a provider must implement are described in the ```Provider``
|
|||
* Stop
|
||||
* Start
|
||||
|
||||
The ```AsParams()``` function does not need to be implemented by the external executable.
|
||||
|
||||
## CreateInstance
|
||||
|
||||
The ```CreateInstance``` command has the most moving parts. The ideal external provider is one that will create all required resources for a fully functional instance, will start the instance. Waiting for the instance to start is not necessary. If the instance can reach the ```callback_url``` configured in ```garm```, it will update it's own status when it boots.
|
||||
The ```CreateInstance``` command has the most moving parts. The ideal external provider is one that will create all required resources for a fully functional instance, will start the instance. Waiting for the instance to start is not necessary. If the instance can reach the ```callback_url``` configured in ```garm```, it will update it's own status when it starts running the userdata script.
|
||||
|
||||
But aside from creating resources, the ideal external provider is also idempotent, and will clean up after itself in case of failure. If for any reason the executable will fail to create the instance, any dependency that it has created up to the point of failure, should be cleaned up before returning an error code.
|
||||
|
||||
|
|
@ -109,24 +104,24 @@ At the very least, it must be able to clean up those resources, if it is called
|
|||
|
||||
If your executable failed before a ```provider_id``` could be supplied, ```garm``` will send the name of the instance as a ```GARM_INSTANCE_ID``` environment variable.
|
||||
|
||||
Your external provider will need to be able to handle both. The instance name generated by ```garm``` will be unique (contains a UUID4), so it's fairly safe to use when deleting instances.
|
||||
Your external provider will need to be able to handle both. The instance name generated by ```garm``` will be unique, so it's fairly safe to use when deleting instances.
|
||||
|
||||
### CreateInstance inputs
|
||||
|
||||
The ```CreateInstance``` command is the only command that receives information using, environment variables and standard input. The available environment variables are:
|
||||
The ```CreateInstance``` command is the only command that needs to handle standard input. Garm will send the runner bootstrap information in stdin. The environment variables set for this command are:
|
||||
|
||||
* GARM_PROVIDER_CONFIG_FILE - Config file specific to your executable
|
||||
* GARM_COMMAND - the command we need to run
|
||||
* GARM_CONTROLLER_ID - The unique ID of the ```garm``` installation
|
||||
* GARM_POOL_ID - The unique ID of the pool this node is a part of
|
||||
|
||||
The information sent in via standard input is a ```json``` serialized instance of the [BootstrapInstance structure](https://github.com/cloudbase/garm/blob/main/params/params.go#L80-L103)
|
||||
The information sent in via standard input is a ```json``` serialized instance of the [BootstrapInstance structure](https://github.com/cloudbase/garm/blob/6b3ea50ca54501595e541adde106703d289bb804/params/params.go#L164-L217)
|
||||
|
||||
Here is a sample of that:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "garm-e73542f6-2c10-48bb-bfe7-a0374618f405",
|
||||
"name": "garm-ny9HeeQYw2rl",
|
||||
"tools": [
|
||||
{
|
||||
"os": "osx",
|
||||
|
|
@ -182,8 +177,12 @@ Here is a sample of that:
|
|||
"callback-url": "https://garm.example.com/api/v1/callbacks/status",
|
||||
"metadata-url": "https://garm.example.com/api/v1/metadata",
|
||||
"instance-token": "super secret JWT token",
|
||||
"ssh-keys": null,
|
||||
"extra_specs": {
|
||||
"my_custom_config": "some_value"
|
||||
},
|
||||
"ca-cert-bundle": null,
|
||||
"github-runner-group": "my_group",
|
||||
"os_type": "linux",
|
||||
"arch": "amd64",
|
||||
"flavor": "m1.small",
|
||||
"image": "8ed8a690-69b6-49eb-982f-dcb466895e2d",
|
||||
|
|
@ -217,16 +216,21 @@ You will have to parse the bootstrap params, verify that the requested image exi
|
|||
|
||||
Refer to the OpenStack or Azure providers available in the [providers.d](../contrib/providers.d/) folder. Of particular interest are the [cloudconfig folders](../contrib/providers.d/openstack/cloudconfig/), where the instance user data templates are stored. These templates are used to generate the needed automation for the instances to download the github runner agent, send back status updates (including the final github runner agent ID), and download the github runner registration token from garm.
|
||||
|
||||
Examples of external providers written in Go can be found at the followinf locations:
|
||||
|
||||
* <https://github.com/cloudbase/garm-provider-azure>
|
||||
* <https://github.com/cloudbase/garm-provider-openstack>
|
||||
|
||||
### CreateInstance outputs
|
||||
|
||||
On success, your executable is expected to print to standard output a json that can be deserialized into an ```Instance{}``` structure [defined here](https://github.com/cloudbase/garm/blob/main/params/params.go#L43-L78).
|
||||
On success, your executable is expected to print to standard output a json that can be deserialized into an ```Instance{}``` structure [defined here](https://github.com/cloudbase/garm/blob/6b3ea50ca54501595e541adde106703d289bb804/params/params.go#L90-L154).
|
||||
|
||||
Not all fields are expected to be populated by the provider. The ones that should be set are:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider_id": "88818ff3-1fca-4cb5-9b37-84bfc3511ea6",
|
||||
"name": "garm-0542a982-4a0d-4aca-aef0-d736c96f61ca",
|
||||
"name": "garm-ny9HeeQYw2rl",
|
||||
"os_type": "linux",
|
||||
"os_name": "ubuntu",
|
||||
"os_version": "20.04",
|
||||
|
|
@ -247,25 +251,27 @@ In case of error, ```garm``` expects at the very least to see a non-zero exit co
|
|||
|
||||
The ```DeleteInstance``` command will permanently remove an instance from the cloud provider.
|
||||
|
||||
Available environment variables:
|
||||
The environment variables set for this command are:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
* GARM_CONTROLLER_ID
|
||||
* GARM_INSTANCE_ID
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
|
||||
This command is not expected to output anything. On success it should simply ```exit 0```.
|
||||
|
||||
If the target instance does not exist in the provider, this command is expected to be a noop.
|
||||
If the target instance does not exist in the provider, this command is expected to be a no-op.
|
||||
|
||||
## GetInstance
|
||||
|
||||
The ```GetInstance``` command will return details about the instance, as seen by the provider.
|
||||
|
||||
Available environment variables:
|
||||
The environment variables set for this command are:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
* GARM_CONTROLLER_ID
|
||||
* GARM_INSTANCE_ID
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
|
||||
On success, this command is expected to return a valid ```json``` that can be deserialized into an ```Instance{}``` structure (see CreateInstance). If possible, IP addresses allocated to the VM should be returned in addition to the sample ```json``` printed above.
|
||||
|
||||
|
|
@ -275,9 +281,10 @@ On failure, this command is expected to return a non-zero exit code.
|
|||
|
||||
The ```ListInstances``` command will print to standard output, a json that is deserializable into an **array** of ```Instance{}```.
|
||||
|
||||
Available environment variables:
|
||||
The environment variables set for this command are:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_CONTROLLER_ID
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
* GARM_POOL_ID
|
||||
|
||||
|
|
@ -291,7 +298,7 @@ On failure, a non-zero exit code is expected.
|
|||
|
||||
The ```RemoveAllInstances``` operation will remove all resources created in a cloud that have been tagged with the ```GARM_CONTROLLER_ID```. External providers should tag all resources they create with the garm controller ID. That tag can then be used to identify all resources when attempting to delete all instances.
|
||||
|
||||
Available environment variables:
|
||||
The environment variables set for this command are:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
|
|
@ -301,13 +308,16 @@ On success, no output is expected.
|
|||
|
||||
On failure, a non-zero exit code is expected.
|
||||
|
||||
Note: This command is currently not used by garm.
|
||||
|
||||
## Start
|
||||
|
||||
The ```Start``` operation will start the virtual machine in the selected cloud.
|
||||
|
||||
Available environment variables:
|
||||
The environment variables set for this command are:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_CONTROLLER_ID
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
* GARM_INSTANCE_ID
|
||||
|
||||
|
|
@ -324,6 +334,7 @@ The ```Stop``` operation will stop the virtual machine in the selected cloud.
|
|||
Available environment variables:
|
||||
|
||||
* GARM_COMMAND
|
||||
* GARM_CONTROLLER_ID
|
||||
* GARM_PROVIDER_CONFIG_FILE
|
||||
* GARM_INSTANCE_ID
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue