# Build a project This scenario tests the controller API to simulate a build. SCENARIO build a project Set up the controller. GIVEN an RSA key pair for token signing AND controller config uses statedir at the state directory AND an access token for user with scopes ... uapi_pipelines_post ... uapi_projects_post ... uapi_projects_id_pipelines_id_put ... uapi_projects_id_pipelines_id_get ... uapi_projects_id_builds_get ... uapi_workers_id_get ... uapi_builds_get ... uapi_builds_id_get ... uapi_logs_id_get AND a running ick controller Add up a project with some named pipelines. WHEN user makes request POST /pipelines with a valid token and body ... { ... "pipeline": "construct", ... "actions": [ ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ] ... } THEN result has status code 201 WHEN user makes request POST /projects with a valid token and body ... { ... "project": "rome", ... "parameters": { ... "foo": "bar" ... }, ... "pipelines": ["construct"] ... } THEN result has status code 201 Add a second project so we know each project gets its own work steps. WHEN user makes request POST /projects with a valid token and body ... { ... "project": "constantinople", ... "parameters": { ... "hey": "there" ... }, ... "pipelines": ["construct"] ... } THEN result has status code 201 There are no builds for the project yet, and is idle. WHEN user makes request GET /projects/rome/pipelines/construct THEN result has status code 200 AND body matches { "status": "idle" } WHEN user makes request GET /builds THEN result has status code 200 AND body matches { "builds": [] } Register a worker. GIVEN an access token for worker-manager with scopes ... uapi_workers_post ... uapi_work_post ... uapi_work_id_get WHEN worker-manager makes request POST /workers with a valid token and body ... { ... "worker": "obelix" ... } THEN result has status code 201 Trigger build. First with an invalid status, then a real one. WHEN user makes request PUT /projects/rome/pipelines/construct ... with a valid token and body { "status": "VANDALS!" } THEN result has status code 400 WHEN user makes request PUT /projects/rome/pipelines/construct ... with a valid token and body { "status": "triggered" } THEN result has status code 200 Worker wants work and gets the first step to run. If the worker asks again, it gets the same answer. **FIXME: should the name of the worker be in the path or can we get it in the access token?** Note that the controller has inserted a special additional step to get the worker to construct a new workspace for the build. WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "action": "create_workspace" ... } ... } WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "action": "create_workspace" ... } ... } User can now see pipeline is running and which worker is building it. WHEN user makes request GET /projects/rome/pipelines/construct THEN result has status code 200 AND body matches ... { ... "status": "building" ... } WHEN user makes request GET /workers/obelix THEN result has status code 200 AND body matches ... { ... "worker": "obelix", ... "doing": { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "action": "create_workspace" ... } ... } ... } WHEN user makes request GET /builds THEN result has status code 200 AND body matches ... { ... "builds": [ ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": 0, ... "parameters": { ... "foo": "bar" ... }, ... "status": "building", ... "log": "/logs/rome/1" ... } ... ] ... } WHEN user makes request GET /logs/rome/1 THEN result has status code 200 AND result has header Content-Type: text/plain AND body text is "" Worker reports workspace creation is done. Note the zero exit code. WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 Worker requests more work, and gets the first actual build step. WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "shell": "day 1" ... } ... } Worker reports some build output. Note the null exit code. The step hasn't finished yet. WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": null, ... "stdout": "hey ho", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 Worker-manager still gets the same step, since the first build step didnt't finish. WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "shell": "day 1" ... } ... } The build log is immediately accessible. WHEN user makes request GET /logs/rome/1 THEN result has status code 200 AND result has header Content-Type: text/plain AND body text is "hey ho" Report the step is done, and successfully. WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": ", hey ho\n", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN user makes request GET /logs/rome/1 THEN result has status code 200 AND result has header Content-Type: text/plain AND body text is "hey ho, hey ho\n" The build status now shows the next step as the active one. WHEN user makes request GET /builds THEN result has status code 200 AND body matches ... { ... "builds": [ ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": 2, ... "parameters": { ... "foo": "bar" ... }, ... "status": "building", ... "log": "/logs/rome/1" ... } ... ] ... } Now there's another step to do. WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "shell": "day 2" ... } ... } User sees changed status. WHEN user makes request GET /workers/obelix THEN result has status code 200 AND body matches ... { ... "worker": "obelix", ... "doing": { ... "build_id": "rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "shell": "day 2" ... }, ... "log": "/logs/rome/1" ... } ... } Report it done. WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": "to the gold mine we go!\n", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 Now there's no more work to do. WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches {} The pipeline status indicates success. WHEN user makes request GET /projects/rome/pipelines/construct THEN result has status code 200 AND body matches { "status": "idle" } Also, there's a build with a log. Also, the build status shows there's no current action. WHEN user makes request GET /builds THEN result has status code 200 AND body matches ... { ... "builds": [ ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": null, ... "parameters": { ... "foo": "bar" ... }, ... "status": 0 ... } ... ] ... } WHEN user makes request GET /builds/rome/1 THEN result has status code 200 AND body matches ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": null, ... "parameters": { ... "foo": "bar" ... }, ... "status": 0 ... } WHEN user makes request GET /logs/rome/1 THEN result has status code 200 AND result has header Content-Type: text/plain AND body text is "hey ho, hey ho\nto the gold mine we go!\n" Start build again. This should become build number 2. WHEN user makes request PUT /projects/rome/pipelines/construct ... with a valid token and body { "status": "triggered" } THEN result has status code 200 WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/2", ... "log": "/logs/rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "action": "create_workspace" ... } ... } WHEN user makes request GET /builds THEN result has status code 200 AND body matches ... { ... "builds": [ ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": null, ... "parameters": { ... "foo": "bar" ... }, ... "status": 0 ... }, ... { ... "build_id": "rome/2", ... "build_number": 2, ... "log": "/logs/rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": 0, ... "parameters": { ... "foo": "bar" ... }, ... "status": "building" ... } ... ] ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 AND body matches ... { ... "build_id": "rome/2", ... "log": "/logs/rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "parameters": { ... "foo": "bar" ... }, ... "step": { ... "shell": "day 1" ... } ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": "hey ho", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN worker-manager makes request GET /work/obelix THEN result has status code 200 WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "exit_code": 0, ... "stdout": "hey ho", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN user makes request GET /builds THEN result has status code 200 AND body matches ... { ... "builds": [ ... { ... "build_id": "rome/1", ... "build_number": 1, ... "log": "/logs/rome/1", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": null, ... "parameters": { ... "foo": "bar" ... }, ... "status": 0 ... }, ... { ... "build_id": "rome/2", ... "build_number": 2, ... "log": "/logs/rome/2", ... "worker": "obelix", ... "project": "rome", ... "pipeline": "construct", ... "actions": [ ... { "action": "create_workspace" }, ... { "shell": "day 1" }, ... { "shell": "day 2" } ... ], ... "current_action": null, ... "parameters": { ... "foo": "bar" ... }, ... "status": 0 ... } ... ] ... } FINALLY stop ick controller # Build two projects sequentially This scenario tests the controller API to simulate a build. SCENARIO build two projects sequentially Set up the controller. GIVEN an RSA key pair for token signing AND controller config uses statedir at the state directory AND an access token for user with scopes ... uapi_pipelines_post ... uapi_projects_post ... uapi_projects_id_pipelines_id_put ... uapi_projects_id_pipelines_id_get ... uapi_projects_id_builds_get ... uapi_workers_id_get ... uapi_builds_get ... uapi_builds_id_get ... uapi_logs_id_get AND a running ick controller Add a couple of projects. WHEN user makes request POST /pipelines with a valid token and body ... { ... "pipeline": "do_something", ... "actions": [ ... { "shell": "something" } ... ] ... } THEN result has status code 201 WHEN user makes request POST /projects with a valid token and body ... { ... "project": "first", ... "pipelines": ["do_something"] ... } THEN result has status code 201 WHEN user makes request POST /projects with a valid token and body ... { ... "project": "second", ... "pipelines": ["do_something"] ... } THEN result has status code 201 Register a worker. GIVEN an access token for worker-manager with scopes ... uapi_workers_post ... uapi_work_post ... uapi_work_id_get WHEN worker-manager makes request POST /workers with a valid token and body ... { ... "worker": "obelix" ... } THEN result has status code 201 Build the first project. WHEN user makes request PUT /projects/first/pipelines/do_something ... with a valid token and body { "status": "triggered" } THEN result has status code 200 WHEN worker-manager makes request GET /work/obelix THEN result is step ... { ... "action": "create_workspace" ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "first/1", ... "worker": "obelix", ... "project": "first", ... "pipeline": "do_something", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN worker-manager makes request GET /work/obelix THEN result is step ... { ... "shell": "something" ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "first/1", ... "worker": "obelix", ... "project": "first", ... "pipeline": "do_something", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN user requests list of builds THEN the list of builds is ["first/1"] Build second project. WHEN user makes request PUT /projects/second/pipelines/do_something ... with a valid token and body { "status": "triggered" } THEN result has status code 200 WHEN worker-manager makes request GET /work/obelix THEN result is step ... { ... "action": "create_workspace" ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "second/1", ... "worker": "obelix", ... "project": "second", ... "pipeline": "do_something", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN worker-manager makes request GET /work/obelix THEN result is step ... { ... "shell": "something" ... } WHEN worker-manager makes request POST /work with a valid token and body ... { ... "build_id": "second/1", ... "worker": "obelix", ... "project": "second", ... "pipeline": "do_something", ... "exit_code": 0, ... "stdout": "", ... "stderr": "", ... "timestamp": "2017-10-27T17:08:49" ... } THEN result has status code 201 WHEN user requests list of builds THEN the list of builds is ["first/1", "second/1"] Finish up. FINALLY stop ick controller