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