Skip to content

Commit

Permalink
✨ : extract runner code to gaia-runner
Browse files Browse the repository at this point in the history
  • Loading branch information
juwit committed Oct 23, 2020
1 parent 103efbf commit c37dc1f
Show file tree
Hide file tree
Showing 23 changed files with 236 additions and 1,111 deletions.
2 changes: 1 addition & 1 deletion src/main/client/app/pages/stacks/job/job-step.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
<app-console
:id="'logs-' + id"
:css-style="'max-height: 300px'"
:logs="step.logs"
:logs="step.logs.join('')"
/>
</b-collapse>
</div>
Expand Down
30 changes: 4 additions & 26 deletions src/main/client/app/pages/stacks/job/job.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
applyJob,
deleteJob,
getJob,
planJob,
retryJob,
} from '@/shared/api/jobs-api';
import { getStack } from '@/shared/api/stacks-api';
Expand Down Expand Up @@ -83,6 +82,7 @@
},
isSecondStepDoable() {
return this.job.status
&& !this.job.status.includes('PENDING')
&& !this.job.status.includes('STARTED')
&& !this.job.status.includes('FAILED')
&& !this.job.status.includes('APPLY');
Expand All @@ -91,29 +91,20 @@
async created() {
[this.stack, this.job] = await Promise.all([getStack(this.stackId), this.refreshJobUntilCompletion()]);
this.loaded = true;
if (!this.job.status) {
await this.planJob();
}
this.refreshIntervalId = setInterval(this.refreshJobUntilCompletion, INTERVAL_TIMEOUT);
},
destroyed() {
clearInterval(this.refreshIntervalId);
},
methods: {
async planJob() {
await planJob(this.jobId);
await this.waitUntilJobStarted();
this.refreshIntervalId = setInterval(this.refreshJobUntilCompletion, INTERVAL_TIMEOUT);
},
async applyJob() {
await applyJob(this.jobId);
await this.waitUntilJobStarted();
this.refreshIntervalId = setInterval(this.refreshJobUntilCompletion, INTERVAL_TIMEOUT);
},
async retryJob() {
await retryJob(this.jobId);
await this.waitUntilJobStarted();
this.refreshIntervalId = setInterval(this.refreshJobUntilCompletion, INTERVAL_TIMEOUT);
},
Expand All @@ -132,24 +123,11 @@
},
async refreshJobUntilCompletion() {
this.job = await getJob(this.jobId);
if (this.job.status && !this.job.status.includes('STARTED')) {
if (this.job.status.includes('FINISHED') || this.job.status.includes('FAILED')) {
clearInterval(this.refreshIntervalId);
}
return this.job;
},
// wait until the job is in "started" state
async waitUntilJobStarted() {
const poll = async (resolve) => {
this.job = await getJob(this.jobId);
if (this.job.status && this.job.status.includes('STARTED')) {
resolve();
} else {
setTimeout(() => poll(resolve), 500);
}
};
return new Promise(poll);
},
},
};
</script>
136 changes: 0 additions & 136 deletions src/main/java/io/gaia_app/runner/DockerRunner.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
* A builder class to create stack commands
*/
@Component
public class StackCommandBuilder {
public class RunnerCommandBuilder {

private Settings settings;
private RunnerApiSecurityConfig.RunnerApiSecurityProperties runnerApiSecurityProperties;
private Mustache terraformMustache;
private List<RegistryOAuth2Provider> registryOAuth2Providers;

@Autowired
StackCommandBuilder(Settings settings, Mustache terraformMustache, List<RegistryOAuth2Provider> registryOAuth2Providers, RunnerApiSecurityConfig.RunnerApiSecurityProperties runnerApiSecurityProperties) {
RunnerCommandBuilder(Settings settings, Mustache terraformMustache, List<RegistryOAuth2Provider> registryOAuth2Providers, RunnerApiSecurityConfig.RunnerApiSecurityProperties runnerApiSecurityProperties) {
this.settings = settings;
this.terraformMustache = terraformMustache;
this.registryOAuth2Providers = registryOAuth2Providers;
Expand Down
131 changes: 127 additions & 4 deletions src/main/java/io/gaia_app/runner/RunnerController.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package io.gaia_app.runner;

import io.gaia_app.credentials.CredentialsService;
import io.gaia_app.stacks.bo.*;
import io.gaia_app.stacks.repository.JobRepository;
import io.gaia_app.stacks.repository.StackRepository;
import io.gaia_app.stacks.repository.StepRepository;
import io.gaia_app.stacks.workflow.JobWorkflow;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* Controller for the operations that are called by the runner only
Expand All @@ -17,9 +26,123 @@ public class RunnerController {
@Autowired
private StackRepository stackRepository;

@Autowired
private JobRepository jobRepository;

@Autowired
private StepRepository stepRepository;

@Autowired
private CredentialsService credentialsService;

@Autowired
private RunnerCommandBuilder runnerCommandBuilder;

@GetMapping(value = "/stacks/{id}.tfvars", produces = "text/plain")
public String tfvars(@PathVariable String id){
var stack = stackRepository.findById(id).orElseThrow();
return stack.tfvars();
}

/**
* Gets the first job step that can be run by the runner (one in "pending" state)
*/
@GetMapping("/steps/request")
public Map<String, Object> findFirstRunnableJob() {
var job = this.jobRepository.findFirstByStatusEqualsOrStatusEquals(JobStatus.PLAN_PENDING, JobStatus.APPLY_PENDING)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
var stack = this.stackRepository.findById(job.getStackId()).orElseThrow();

// get the workflow
var workflow = new JobWorkflow(job);
// start the workflow
var step = workflow.startWorkflow();

// saving the job
this.jobRepository.save(job);
this.stepRepository.save(step);

var script = "";
// generate the script
if(job.getType() == JobType.RUN){
if(step.getType() == StepType.PLAN) {
script = runnerCommandBuilder.buildPlanScript(job, stack, stack.getModule());
}
else {
script = runnerCommandBuilder.buildApplyScript(job, stack, stack.getModule());
}
}
else { // destroy
if(step.getType() == StepType.PLAN) {
script = runnerCommandBuilder.buildPlanDestroyScript(job, stack, stack.getModule());
}
else {
script = runnerCommandBuilder.buildDestroyScript(job, stack, stack.getModule());
}
}

List<String> env = Collections.emptyList();
if(stack.getCredentialsId() != null){
var credentials = this.credentialsService.load(stack.getCredentialsId()).orElse(null);
if(credentials != null){
env = credentials.toEnv();
}
}

return Map.of(
"step", step,
"script", script,
"env", env,
"image", job.getTerraformImage().image());
}

/**
* Updates the step logs
*/
@PutMapping("/steps/{stepId}/logs")
public void updateLogs(@PathVariable String stepId, @RequestBody String logs) {
var step = this.stepRepository.findById(stepId).orElseThrow();
step.getLogs().add(logs);
this.stepRepository.save(step);
}

/**
* Updates the step status
*/
@PutMapping("/steps/{stepId}/status")
public void updateStepStatus(@PathVariable String stepId, @RequestBody int status) {
var step = this.stepRepository.findById(stepId).orElseThrow();

// reload the job to check workflow status
var job = this.jobRepository.findById(step.getJobId()).orElseThrow();

// rebuild the workflow
var workflow = new JobWorkflow(job);
workflow.setCurrentStep(step);
workflow.next(status);

// save the job & step to update their status
this.stepRepository.save(step);
this.jobRepository.save(job);
}

/**
* Updates the job state
*/
@PutMapping("/steps/{stepId}/start")
public void startStep(@PathVariable String stepId) {
// getting step
var step = this.stepRepository.findById(stepId).orElseThrow();

// reload the job to check workflow status
var job = this.jobRepository.findById(step.getJobId()).orElseThrow();

// rebuild the workflow and start it
var workflow = new JobWorkflow(job);
workflow.startWorkflow();

// save the job & step to update their status
this.stepRepository.save(step);
this.jobRepository.save(job);
}
}
Loading

0 comments on commit c37dc1f

Please sign in to comment.