Skip to content

Commit

Permalink
feat(titus): delete job with just id (spinnaker#3762)
Browse files Browse the repository at this point in the history
  • Loading branch information
emjburns authored and justinrlee committed Jun 12, 2019
1 parent 1403f36 commit bb5db6c
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
*
* Copyright 2019 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.spinnaker.clouddriver.titus.deploy.converters

import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation
import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperations
import com.netflix.spinnaker.clouddriver.security.AbstractAtomicOperationsCredentialsSupport
import com.netflix.spinnaker.clouddriver.titus.TitusClientProvider
import com.netflix.spinnaker.clouddriver.titus.TitusOperation
import com.netflix.spinnaker.clouddriver.titus.deploy.description.DestroyTitusJobDescription
import com.netflix.spinnaker.clouddriver.titus.deploy.ops.DestroyTitusJobAtomicOperation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

@TitusOperation(AtomicOperations.DESTROY_JOB)
@Component
class DestroyTitusJobAtomicOperationConverter extends AbstractAtomicOperationsCredentialsSupport {

private final TitusClientProvider titusClientProvider

@Autowired
DestroyTitusJobAtomicOperationConverter(TitusClientProvider titusClientProvider) {
this.titusClientProvider = titusClientProvider
}

@Override
AtomicOperation convertOperation(Map input) {
new DestroyTitusJobAtomicOperation(titusClientProvider, convertDescription(input))
}

@Override
DestroyTitusJobDescription convertDescription(Map input) {
def converted = objectMapper.convertValue(input, DestroyTitusJobDescription)
converted.credentials = getCredentialsObject(input.credentials as String)
return converted
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
*
* Copyright 2019 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.spinnaker.clouddriver.titus.deploy.description

import com.netflix.spinnaker.clouddriver.security.resources.ServerGroupsNameable

class DestroyTitusJobDescription extends AbstractTitusCredentialsDescription {
String region
String jobId
String user
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
*
* Copyright 2019 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.spinnaker.clouddriver.titus.deploy.ops

import com.netflix.spinnaker.clouddriver.data.task.Task
import com.netflix.spinnaker.clouddriver.data.task.TaskRepository
import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation
import com.netflix.spinnaker.clouddriver.orchestration.events.DeleteServerGroupEvent
import com.netflix.spinnaker.clouddriver.orchestration.events.OperationEvent
import com.netflix.spinnaker.clouddriver.titus.TitusClientProvider
import com.netflix.spinnaker.clouddriver.titus.TitusCloudProvider
import com.netflix.spinnaker.clouddriver.titus.client.TitusClient
import com.netflix.spinnaker.clouddriver.titus.client.model.Job
import com.netflix.spinnaker.clouddriver.titus.client.model.TerminateJobRequest
import com.netflix.spinnaker.clouddriver.titus.deploy.description.DestroyTitusJobDescription

class DestroyTitusJobAtomicOperation implements AtomicOperation<Void> {
private static final String PHASE = "DESTROY_TITUS_JOB"
private final TitusClientProvider titusClientProvider
private final DestroyTitusJobDescription description
private final Collection<DeleteServerGroupEvent> events = []

DestroyTitusJobAtomicOperation(TitusClientProvider titusClientProvider, DestroyTitusJobDescription description) {
this.titusClientProvider = titusClientProvider
this.description = description
}

@Override
Void operate(List priorOutputs) {
task.updateStatus PHASE, "Destroying job: ${description.jobId}..."
TitusClient titusClient = titusClientProvider.getTitusClient(description.credentials, description.region)
Job job = titusClient.getJobAndAllRunningAndCompletedTasks(description.jobId)
if (job) {
titusClient.terminateJob((TerminateJobRequest) new TerminateJobRequest().withJobId(job.id).withUser(description.user))
events << new DeleteServerGroupEvent(
TitusCloudProvider.ID, description.credentials.name, description.region, description.jobId
)
task.updateStatus PHASE, "Successfully issued terminate job request to titus for ${job.id}"
} else {
task.updateStatus PHASE, "No titus job found wit id ${description.jobId}"
}

task.updateStatus PHASE, "Completed destroy job operation for ${description.jobId}"
null
}

@Override
Collection<OperationEvent> getEvents() {
return events
}

private static Task getTask() {
TaskRepository.threadLocalTask.get()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
*
* Copyright 2019 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.netflix.spinnaker.clouddriver.titus.deploy.validators

import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperations
import com.netflix.spinnaker.clouddriver.security.AccountCredentialsProvider
import com.netflix.spinnaker.clouddriver.titus.TitusOperation
import com.netflix.spinnaker.clouddriver.titus.credentials.NetflixTitusCredentials
import com.netflix.spinnaker.clouddriver.titus.deploy.description.DestroyTitusJobDescription
import org.springframework.stereotype.Component
import org.springframework.validation.Errors

@Component
@TitusOperation(AtomicOperations.DESTROY_JOB)
class DestroyTitusJobDescriptionValidator extends AbstractTitusDescriptionValidatorSupport<DestroyTitusJobDescription> {

DestroyTitusJobDescriptionValidator(AccountCredentialsProvider accountCredentialsProvider) {
super(accountCredentialsProvider, "destroyTitusJobDescription")
}

@Override
void validate(List priorDescriptions, DestroyTitusJobDescription description, Errors errors) {
super.validate(priorDescriptions, description, errors)

if (!description.region) {
errors.rejectValue "region", "destroyTitusJobDescription.region.empty"
}

def credentials = getAccountCredentials(description?.credentials?.name)
if (credentials && !((NetflixTitusCredentials) credentials).regions.name.contains(description.region)) {
errors.rejectValue "region", "destroyTitusJobDescription.region.not.configured", description.region, "Region not configured"
}

if (!description.jobId) {
errors.rejectValue "jobId", "destroyTitusJobDescription.jobId.empty"
}
}
}

0 comments on commit bb5db6c

Please sign in to comment.