github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/boskos/README.md (about)

     1  # boskos
     2  
     3  
     4  ## Background
     5  [βοσκός](https://en.wiktionary.org/wiki/%CE%B2%CE%BF%CF%83%CE%BA%CF%8C%CF%82) - shepherd in greek!
     6  
     7  boskos is a resource manager service, that handles and manages different kind of resources and transition between different states.
     8  
     9  ## Introduction
    10  
    11  Boskos is inited with a config of resources, one JSON entry per line, from `-config`
    12  
    13  A resource object looks like
    14  ```go
    15  type Resource struct {
    16          Type       string             `json:"type"`
    17          Name       string             `json:"name"`
    18          State      string             `json:"state"`
    19          Owner      string             `json:"owner"`
    20          LastUpdate time.Time          `json:"lastupdate"`
    21          UserData   map[string]string  `json:"userdata"`
    22  }
    23  ```
    24  
    25  Type can be GCPProject, cluster, or even a dota2 server, anything that you
    26  want to be a group of resources. Name is a unique identifier of the resource.
    27  State is a string that tells the current status of the resource.
    28  
    29  User Data is here for customization. In Mason as an example, we create new
    30  resources from existing ones (creating a cluster inside a GCP project), but
    31  in order to acquire the right resources, we need to store some information in the
    32  final resource UserData. It is up to the implementation to parse the string into the
    33  right struct. UserData can be updated using the update API call. All resource
    34  user data is returned as part of acquisition (calling acquire or acquirebystate)
    35  
    36  
    37  ## API
    38  
    39  ###   `POST /acquire`
    40  
    41  Use `/acquire` when you want to get hold of some resource.
    42  
    43  #### Required Parameters
    44  
    45  | Name    | Type     | Description                                 |
    46  | ------- | -------- | ------------------------------------------- |
    47  | `type`  | `string` | type of requested resource                  |
    48  | `state` | `string` | current state of the requested resource     |
    49  | `dest`  | `string` | destination state of the requested resource |
    50  | `owner` | `string` | requester of the resource                   |
    51  
    52  Example: `/acquire?type=gce-project&state=free&dest=busy&owner=user`.
    53  
    54  On a successful request, `/acquire` will return HTTP 200 and a valid Resource JSON object.
    55  
    56  ###   `POST /acquirebystate`
    57  
    58  Use `/acquirebystate` when you want to get hold of a set of resources in a given
    59  state.
    60  
    61  #### Required Parameters
    62  
    63  | Name    | Type     | Description                                 |
    64  | ------- | -------- | ------------------------------------------- |
    65  | `state` | `string` | current state of the requested resource     |
    66  | `dest`  | `string` | destination state of the requested resource |
    67  | `owner` | `string` | requester of the resource                   |
    68  | `names` | `string` | comma separated list of resource names      |
    69  
    70  Example: `/acquirebystate?state=free&dest=busy&owner=user&names=res1,res2`.
    71  
    72  On a successful request, `/acquirebystate` will return HTTP 200 and a valid list of Resources JSON object.
    73  
    74  ###   `POST /release`
    75  
    76  Use `/release` when you finish use some resource. Owner need to match current owner.
    77  
    78  #### Required Parameters
    79  
    80  | Name    | Type     | Description                                |
    81  | ------- | -------- | ------------------------------------------ |
    82  | `name`  | `string` | name of finished resource                  |
    83  | `owner` | `string` | owner of the resource                      |
    84  | `dest`  | `string` | destination state of the released resource |
    85  
    86  Example: `/release?name=k8s-jkns-foo&dest=dirty&owner=user`
    87  
    88  ###   `POST /update`
    89  
    90  Use `/update` to update resource last-update timestamp. Owner need to match current owner.
    91  
    92  #### Required Parameters
    93  
    94  | Name    | Type     | Description                    |
    95  | ------- | -------- | ------------------------------ |
    96  | `name`  | `string` | name of target resource        |
    97  | `owner` | `string` | owner of the resource          |
    98  | `state` | `string` | current state of the resource  |
    99  
   100  
   101  #### Optional Parameters
   102  In order to update user data, just marshall the user data into the request body.
   103  
   104  Example: `/update?name=k8s-jkns-foo&state=free&owner=user`
   105  
   106  ###   `POST /reset`
   107  
   108  Use `/reset` to reset a group of expired resource to certain state.
   109  
   110  #### Required Parameters
   111  
   112  | Name     | Type          | Description                                         |
   113  | -------- | ------------- | --------------------------------------------------- |
   114  | `type`   | `string`      | type of resource in interest                        |
   115  | `state`  | `string`      | current state of the expired resource               |
   116  | `dest`   | `string`      | destination state of the expired resource           |
   117  | `expire` | `durationStr` | resource has not been updated since before `expire` |
   118  
   119  Note: `durationStr` is any string can be parsed by [`time.ParseDuration()`](https://golang.org/pkg/time/#ParseDuration)
   120  
   121  On a successful request, `/reset` will return HTTP 200 and a list of [Owner:Resource] pairs, which can be unmarshalled into `map[string]string{}`
   122  
   123  Example: `/reset?type=gce-project&state=busy&dest=dirty&expire=20m`
   124  
   125  ###   `GET /metric`
   126  
   127  Use `/metric` to retrieve a metric.
   128  
   129  #### Required Parameters
   130  
   131  | Name   | Type     | Description                |
   132  | ------ | -------- | -------------------------- |
   133  | `type` | `string` | type of requested resource |
   134  
   135  On a successful request, `/metric` will return HTTP 200 and a JSON object containing the count of projects in each state, the count of projects with each owner (or without an owner), and the sum of state moved to after `/done` (Todo). A sample object will look like:
   136  
   137  ```json
   138  {
   139          "type" : "project",
   140          "Current":
   141          {
   142                  "total"   : 35,
   143                  "free"    : 20,
   144                  "dirty"   : 10,
   145                  "injured" : 5
   146          },
   147          "Owners":
   148          {
   149                  "fejta" : 1,
   150                  "Senlu" : 1,
   151                  "sig-testing" : 20,
   152                  "Janitor" : 10,
   153                  "None" : 20
   154          }
   155  }
   156  ```
   157  
   158  ## Config update:
   159  1. Edit resources.yaml, and send a PR.
   160  
   161  1. After PR is LG'd, make sure your branch is synced up with master.
   162  
   163  1. run `make update-config` to update the configmap.
   164  
   165  1. Boskos updates its config every 10min. Newly added resources will be available after next update cycle.
   166  Newly deleted resource will be removed in a future update cycle if the resource is not owned by any user.
   167  
   168  ## Other Components:
   169  
   170  [`Reaper`] looks for resources that owned by someone, but have not been updated for a period of time,
   171  and reset the stale resources to dirty state for the [`Janitor`] component to pick up. It will prevent
   172  state leaks if a client process is killed unexpectedly.
   173  
   174  [`Janitor`] looks for dirty resources from boskos, and will kick off sub-janitor process to clean up the
   175  resource, finally return them back to boskos in a clean state.
   176  
   177  [`Metrics`] is a separate service, which can display json metric results, and has HTTP endpoint
   178  opened for prometheus monitoring.
   179  
   180  [`Mason`] updates virtual resources with existing resources. An example would be
   181  a cluster. In order to create a GKE cluster you need a GCP Project. Mason will look for specific
   182  resources and release leased resources as dirty (such that Janitor can pick it up) and ask for
   183  brand new resources in order to convert them in the final resource states. Mason
   184  comes with its own client to ease usage. The mason client takes care of
   185  acquiring and release all the right resources from the User Data information.
   186  
   187  [`Storage`] There could be multiple implementation on how resources and mason
   188  config are stored. Since we have multiple components with storage needs, we have
   189  now shared storage implementation. In memory and in Cluster via k8s custom
   190  resource definition.
   191  
   192  [`crds`] General client library to store data on k8s custom resource definition.
   193  In theory those could be use outside of Boskos.
   194  
   195  For the boskos server that handles k8s e2e jobs, the status is available from the [`Velodrome dashboard`]
   196  
   197  
   198  ## Local test:
   199  1. Start boskos with a fake config.yaml, with `go run boskos.go -config=/path/to/config.yaml`
   200  
   201  1. Sent some local requests to boskos:
   202  ```
   203  curl 'http://127.0.0.1:8080/acquire?type=project&state=free&dest=busy&owner=user'
   204  ```
   205  
   206  ## K8s test:
   207  1. Create and navigate to your own cluster
   208  
   209  1. `make deployment`
   210  
   211  1. `make service`
   212  
   213  1. `kubectl create configmap projects --from-file=config=projects`
   214  
   215  1. `kubectl describe svc boskos` to make sure boskos is running
   216  
   217  1. Test from another pod within the cluster
   218  ```
   219  kubectl run curl --image=radial/busyboxplus:curl -i --tty
   220  Waiting for pod default/curl-XXXXX to be running, status is Pending, pod ready: false
   221  If you don't see a command prompt, try pressing enter.
   222  [ root@curl-XXXXX:/ ]$ curl 'http://boskos/acquire?type=project&state=free&dest=busy&owner=user'
   223  ````
   224  
   225  [`Reaper`]: ./reaper
   226  [`Janitor`]: ./janitor
   227  [`Metrics`]: ./metrics
   228  [`Mason`]: ./mason
   229  [`Storage`]: ./storage
   230  [`crds`]: ./crds
   231  [`Velodrome dashboard`]: http://velodrome.k8s.io/dashboard/db/boskos-dashboard