Skip to content

Commit

Permalink
add a default bounce expiration
Browse files Browse the repository at this point in the history
  • Loading branch information
ssalinas committed Jan 27, 2016
1 parent 240bc2f commit dae47a5
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 24 deletions.
Expand Up @@ -73,6 +73,8 @@ public class SingularityConfiguration extends Configuration {
@JsonProperty("database")
private DataSourceFactory databaseConfiguration;

private int defaultBounceExpirationMinutes = 60;

@NotNull
private SlavePlacement defaultSlavePlacement = SlavePlacement.GREEDY;

Expand Down Expand Up @@ -339,6 +341,14 @@ public Optional<DataSourceFactory> getDatabaseConfiguration() {
return Optional.fromNullable(databaseConfiguration);
}

public int getDefaultBounceExpirationMinutes() {
return defaultBounceExpirationMinutes;
}

public void setDefaultBounceExpirationMinutes(int defaultBounceExpirationMinutes) {
this.defaultBounceExpirationMinutes = defaultBounceExpirationMinutes;
}

public SlavePlacement getDefaultSlavePlacement() {
return defaultSlavePlacement;
}
Expand Down
Expand Up @@ -8,6 +8,7 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
Expand Down Expand Up @@ -151,7 +152,7 @@ public SingularityRequestParent bounce(@PathParam("requestId") String requestId)
@ApiOperation(value="Bounce a specific Singularity request. A bounce launches replacement task(s), and then kills the original task(s) if the replacement(s) are healthy.",
response=SingularityRequestParent.class)
public SingularityRequestParent bounce(@ApiParam("The request ID to bounce") @PathParam("requestId") String requestId,
@ApiParam("Bounce request options") Optional<SingularityBounceRequest> bounceRequest) {
@ApiParam("Bounce request options") Optional<SingularityBounceRequest> maybeBounceRequest) {
SingularityRequestWithState requestWithState = fetchRequestWithState(requestId);

authorizationHelper.checkForAuthorization(requestWithState.getRequest(), user, SingularityAuthorizationScope.WRITE);
Expand All @@ -162,7 +163,25 @@ public SingularityRequestParent bounce(@ApiParam("The request ID to bounce") @Pa

SlavePlacement placement = requestWithState.getRequest().getSlavePlacement().or(configuration.getDefaultSlavePlacement());

final boolean isIncrementalBounce = bounceRequest.isPresent() && bounceRequest.get().getIncremental().or(false);
SingularityBounceRequest bounceRequest;

if (maybeBounceRequest.isPresent()) {
bounceRequest = new SingularityBounceRequest(
maybeBounceRequest.get().getIncremental(),
maybeBounceRequest.get().getSkipHealthchecks(),
maybeBounceRequest.get().getDurationMillis().or(Optional.of(TimeUnit.MINUTES.toMillis(configuration.getDefaultBounceExpirationMinutes()))),
maybeBounceRequest.get().getActionId().or(Optional.of(UUID.randomUUID().toString())),
maybeBounceRequest.get().getMessage());
} else {
bounceRequest = new SingularityBounceRequest(
Optional.<Boolean>absent(),
Optional.<Boolean>absent(),
Optional.of(TimeUnit.MINUTES.toMillis(configuration.getDefaultBounceExpirationMinutes())),
Optional.of(UUID.randomUUID().toString()),
Optional.<String>absent());
}

final boolean isIncrementalBounce = bounceRequest.getIncremental().or(false);

if (placement != SlavePlacement.GREEDY && placement != SlavePlacement.OPTIMISTIC) {
int currentActiveSlaveCount = slaveManager.getNumObjectsAtState(MachineState.ACTIVE);
Expand All @@ -171,34 +190,18 @@ public SingularityRequestParent bounce(@ApiParam("The request ID to bounce") @Pa
checkBadRequest(currentActiveSlaveCount >= requiredSlaveCount, "Not enough active slaves to successfully complete a bounce of request %s (minimum required: %s, current: %s). Consider deploying, or changing the slave placement strategy instead.", requestId, requiredSlaveCount, currentActiveSlaveCount);
}

final Optional<Boolean> skipHealthchecks = bounceRequest.isPresent() ? bounceRequest.get().getSkipHealthchecks() : Optional.<Boolean> absent();

Optional<String> message = Optional.absent();
Optional<String> actionId = Optional.absent();

if (bounceRequest.isPresent()) {
actionId = bounceRequest.get().getActionId();
message = bounceRequest.get().getMessage();

if (bounceRequest.get().getDurationMillis().isPresent() && !actionId.isPresent()) {
actionId = Optional.of(UUID.randomUUID().toString());
}
}

final String deployId = getAndCheckDeployId(requestId);

SingularityCreateResult createResult = requestManager.createCleanupRequest(
new SingularityRequestCleanup(JavaUtils.getUserEmail(user), isIncrementalBounce ? RequestCleanupType.INCREMENTAL_BOUNCE : RequestCleanupType.BOUNCE,
System.currentTimeMillis(), Optional.<Boolean> absent(), requestId, Optional.of(deployId), skipHealthchecks, message, actionId));
System.currentTimeMillis(), Optional.<Boolean> absent(), requestId, Optional.of(deployId), bounceRequest.getSkipHealthchecks(), bounceRequest.getMessage(), bounceRequest.getActionId()));

checkConflict(createResult != SingularityCreateResult.EXISTED, "%s is already bouncing", requestId);

requestManager.bounce(requestWithState.getRequest(), System.currentTimeMillis(), JavaUtils.getUserEmail(user), message);
requestManager.bounce(requestWithState.getRequest(), System.currentTimeMillis(), JavaUtils.getUserEmail(user), bounceRequest.getMessage());

if (bounceRequest.isPresent() && bounceRequest.get().getDurationMillis().isPresent()) {
requestManager.saveExpiringObject(new SingularityExpiringBounce(requestId, deployId, JavaUtils.getUserEmail(user),
System.currentTimeMillis(), bounceRequest.get(), actionId.get()));
}
requestManager.saveExpiringObject(new SingularityExpiringBounce(requestId, deployId, JavaUtils.getUserEmail(user),
System.currentTimeMillis(), bounceRequest, bounceRequest.getActionId().get()));

return fillEntireRequest(requestWithState);
}
Expand Down
Expand Up @@ -32,6 +32,7 @@ public class IndexView extends View {
private final Integer slaveHttpPort;
private final Integer slaveHttpsPort;

private final int defaultBounceExpirationMinutes;
private final long defaultHealthcheckIntervalSeconds;
private final long defaultHealthcheckTimeoutSeconds;
private final long defaultDeployHealthTimeoutSeconds;
Expand Down Expand Up @@ -77,6 +78,7 @@ public IndexView(String singularityUriBase, String appRoot, SingularityConfigura

this.navColor = configuration.getUiConfiguration().getNavColor();

this.defaultBounceExpirationMinutes = configuration.getDefaultBounceExpirationMinutes();
this.defaultHealthcheckIntervalSeconds = configuration.getHealthcheckIntervalSeconds();
this.defaultHealthcheckTimeoutSeconds = configuration.getHealthcheckTimeoutSeconds();
this.defaultDeployHealthTimeoutSeconds = configuration.getDeployHealthyBySeconds();
Expand Down Expand Up @@ -154,6 +156,10 @@ public Boolean getLoadBalancingEnabled() {
return loadBalancingEnabled;
}

public int getDefaultBounceExpirationMinutes() {
return defaultBounceExpirationMinutes;
}

public long getDefaultHealthcheckIntervalSeconds() {
return defaultHealthcheckIntervalSeconds;
}
Expand Down Expand Up @@ -213,6 +219,7 @@ public String toString() {
", title='" + title + '\'' +
", slaveHttpPort=" + slaveHttpPort +
", slaveHttpsPort=" + slaveHttpsPort +
", defaultBounceExpirationMinutes=" + defaultBounceExpirationMinutes +
", defaultHealthcheckIntervalSeconds=" + defaultHealthcheckIntervalSeconds +
", defaultHealthcheckTimeoutSeconds=" + defaultHealthcheckTimeoutSeconds +
", defaultDeployHealthTimeoutSeconds=" + defaultDeployHealthTimeoutSeconds +
Expand Down
1 change: 1 addition & 0 deletions SingularityUI/app/assets/_index.mustache
Expand Up @@ -23,6 +23,7 @@
loadBalancingEnabled: {{{loadBalancingEnabled}}},
defaultCpus: {{{defaultCpus}}},
defaultMemory: {{{defaultMemory}}},
defaultBounceExpirationMinutes: {{{defaultBounceExpirationMinutes}}},
defaultHealthcheckIntervalSeconds: {{{defaultHealthcheckIntervalSeconds}}},
defaultHealthcheckTimeoutSeconds: {{{defaultHealthcheckTimeoutSeconds}}},
defaultDeployHealthTimeoutSeconds: {{{defaultDeployHealthTimeoutSeconds}}},
Expand Down
4 changes: 3 additions & 1 deletion SingularityUI/app/models/Request.coffee
Expand Up @@ -432,7 +432,9 @@ class Request extends Model

promptBounce: (callback) =>
vex.dialog.confirm
message: bounceTemplate id: @get "id"
message: bounceTemplate
id: @get "id"
config: config
input: """
<input name="message" id="bounce-message" type="text" placeholder="Message (optional)" />
"""
Expand Down
2 changes: 1 addition & 1 deletion SingularityUI/app/templates/vex/requestBounce.hbs
Expand Up @@ -12,6 +12,6 @@
<input type="checkbox" name="skip-healthchecks" id="skip-healthchecks"> Skip healthchecks during bounce
</label>
<div class="vex-dialog-input expiration-input">
<input name="duration" id="bounce-expiration" type="text" placeholder="Expiration (optional)" />
<input name="duration" id="bounce-expiration" type="text" placeholder="Expiration (optional - default {{ config.defaultBounceExpirationMinutes }}m)" />
</div>
<span class="help">If an expiration duration is specified, this bounce will be aborted if not finished. Accepts any english time duration. (Days, Hr, Min...)</span>
1 change: 1 addition & 0 deletions SingularityUI/config.coffee
Expand Up @@ -45,6 +45,7 @@ exports.config =
navColor: process.env.SINGULARITY_NAV_COLOR
defaultCpus: process.env.SINGUALRITY_DEFAULT_CPUS ? 1
defaultMemory: process.env.SINGULARITY_DEFAULT_MEMORY ? 128
defaultBounceExpirationMinutes: process.env.SINGULARITY_DEFAULT_BOUNCE_EXPIRATION_MINUTES ? 60
defaultHealthcheckIntervalSeconds: process.env.SINGULARITY_DEFAULT_HEALTHCHECK_INTERVAL_SECONDS ? 5
defaultHealthcheckTimeoutSeconds: process.env.SINGULARITY_HEALTHCHECK_TIMEOUT_SECONDS ? 5
defaultDeployHealthTimeoutSeconds: process.env.SINGULARITY_DEPLOY_HEALTH_TIMEOUT_SECONDS ? 120
Expand Down

0 comments on commit dae47a5

Please sign in to comment.