@Test public void testContinuesAfterFailures() throws Exception { EXECUTOR1.shouldFail(); BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> stepResults = new ArrayList<>(3); stepResults.add(new BootstrapStepResult(STEP1.getLabel(), BootstrapStepResult.Status.FAILED)); stepResults.add(new BootstrapStepResult(STEP2.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); stepResults.add(new BootstrapStepResult(STEP3.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); BootstrapResult expected = new BootstrapResult(stepResults); Assert.assertEquals(expected, result); }
@Test public void invalidStructureFails() throws Exception { JsonObject argumentsObj = new JsonObject(); argumentsObj.addProperty("namespace", "ns"); argumentsObj.addProperty("application", "app"); argumentsObj.addProperty("type", "WORKFLOW"); argumentsObj.add("name", new JsonObject()); BootstrapStepResult result = programStarter.execute("label", argumentsObj); Assert.assertEquals(BootstrapStepResult.Status.FAILED, result.getStatus()); } }
/** * Execute the steps in the loaded bootstrap config. * * @param shouldSkip predicate that determines whether to skip a step * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap(Predicate<BootstrapStep> shouldSkip) throws InterruptedException { List<BootstrapStepResult> results = new ArrayList<>(config.getSteps().size()); if (!bootstrapping.compareAndSet(false, true)) { throw new IllegalStateException("Bootstrap already in progress."); } try { for (BootstrapStep step : config.getSteps()) { results.add(executeStep(step, shouldSkip)); } if (!config.getSteps().isEmpty()) { bootstrapStore.bootstrapped(); } return new BootstrapResult(results); } finally { bootstrapping.set(false); } }
private BootstrapStepResult executeStep(BootstrapStep step, Predicate<BootstrapStep> shouldSkip) throws InterruptedException { try { step.validate(); } catch (IllegalArgumentException e) { LOG.warn("Bootstrap step {} failed because it is malformed: {}", step.getLabel(), e.getMessage()); return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.FAILED, e.getMessage()); } if (shouldSkip.test(step)) { return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SKIPPED, null); } BootstrapStepExecutor bootstrapStepExecutor = bootstrapStepExecutors.get(step.getType()); if (bootstrapStepExecutor == null) { // should not be possible, as deserialization of the file into a BootStrapConfig should have failed return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.FAILED, String.format("Unknown bootstrap step type '%s' for '%s'.", step.getType(), step.getLabel())); } return bootstrapStepExecutor.execute(step.getLabel(), step.getArguments()); }
@Test public void testRunCondition() throws Exception { BootstrapResult result = bootstrapService.bootstrap(step -> step.getRunCondition() == BootstrapStep.RunCondition.ONCE); List<BootstrapStepResult> stepResults = new ArrayList<>(3); stepResults.add(new BootstrapStepResult(STEP1.getLabel(), BootstrapStepResult.Status.SKIPPED)); stepResults.add(new BootstrapStepResult(STEP2.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); stepResults.add(new BootstrapStepResult(STEP3.getLabel(), BootstrapStepResult.Status.SKIPPED)); Assert.assertEquals(new BootstrapResult(stepResults), result); }
@Override public BootstrapStepResult execute(String label, JsonObject argumentsObj) throws InterruptedException { T arguments; try { arguments = GSON.fromJson(argumentsObj, getArgumentsType()); } catch (JsonParseException e) { LOG.warn("Bootstrap step {} failed because its arguments are malformed: {}", label, e.getMessage()); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, String.format("Argument decoding failed. Reason: %s", e.getMessage())); } try { arguments.validate(); } catch (RuntimeException e) { LOG.warn("Bootstrap step {} failed due to invalid arguments: {}", label, e.getMessage()); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, e.getMessage()); } try { LOG.debug("Executing bootstrap step {}", label); Retries.runWithInterruptibleRetries(() -> execute(arguments), getRetryStrategy(), t -> t instanceof RetryableException); LOG.debug("Bootstrap step {} completed successfully", label); return new BootstrapStepResult(label, BootstrapStepResult.Status.SUCCEEDED); } catch (InterruptedException e) { throw e; } catch (Exception e) { LOG.warn("Bootstrap step {} failed to execute", label, e); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, e.getMessage()); } }
/** * Execute the steps in the loaded bootstrap config. * * @param shouldSkip predicate that determines whether to skip a step * @return the result of executing the bootstrap steps. * @throws IllegalStateException if bootstrapping is already in progress * @throws InterruptedException if bootstrapping was interrupted */ public BootstrapResult bootstrap(Predicate<BootstrapStep> shouldSkip) throws InterruptedException { List<BootstrapStepResult> results = new ArrayList<>(config.getSteps().size()); if (!bootstrapping.compareAndSet(false, true)) { throw new IllegalStateException("Bootstrap already in progress."); } try { for (BootstrapStep step : config.getSteps()) { results.add(executeStep(step, shouldSkip)); } if (!config.getSteps().isEmpty()) { bootstrapStore.bootstrapped(); } return new BootstrapResult(results); } finally { bootstrapping.set(false); } }
@Test public void testInvalidArgumentStructure() throws Exception { JsonObject arguments = new JsonObject(); arguments.addProperty("name", "p1"); arguments.addProperty("description", "desc"); arguments.addProperty("label", "some label"); // this is invalid, should be an object arguments.addProperty("provisioner", "native"); BootstrapStepResult result = profileCreator.execute("label", arguments); Assert.assertEquals(BootstrapStepResult.Status.FAILED, result.getStatus()); }
@Test public void testRetries() throws Exception { EXECUTOR1.setNumRetryableFailures(3); BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> expectedStepResults = new ArrayList<>(); for (BootstrapStep step : bootstrapConfig.getSteps()) { expectedStepResults.add(new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); } BootstrapResult expected = new BootstrapResult(expectedStepResults); Assert.assertEquals(expected, result); }
@Override public BootstrapStepResult execute(String label, JsonObject argumentsObj) throws InterruptedException { T arguments; try { arguments = GSON.fromJson(argumentsObj, getArgumentsType()); } catch (JsonParseException e) { LOG.warn("Bootstrap step {} failed because its arguments are malformed: {}", label, e.getMessage()); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, String.format("Argument decoding failed. Reason: %s", e.getMessage())); } try { arguments.validate(); } catch (RuntimeException e) { LOG.warn("Bootstrap step {} failed due to invalid arguments: {}", label, e.getMessage()); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, e.getMessage()); } try { LOG.debug("Executing bootstrap step {}", label); Retries.runWithInterruptibleRetries(() -> execute(arguments), getRetryStrategy(), t -> t instanceof RetryableException); LOG.debug("Bootstrap step {} completed successfully", label); return new BootstrapStepResult(label, BootstrapStepResult.Status.SUCCEEDED); } catch (InterruptedException e) { throw e; } catch (Exception e) { LOG.warn("Bootstrap step {} failed to execute", label, e); return new BootstrapStepResult(label, BootstrapStepResult.Status.FAILED, e.getMessage()); } }
@Test public void invalidStructureFails() throws Exception { JsonObject argumentsObj = new JsonObject(); argumentsObj.addProperty("namespace", "ns"); argumentsObj.addProperty("name", "app"); argumentsObj.addProperty("artifact", "name-1.0.0"); BootstrapStepResult result = appCreator.execute("label", argumentsObj); Assert.assertEquals(BootstrapStepResult.Status.FAILED, result.getStatus()); } }
@Test public void testAllSuccess() throws Exception { BootstrapResult result = bootstrapService.bootstrap(); List<BootstrapStepResult> expectedStepResults = new ArrayList<>(); for (BootstrapStep step : bootstrapConfig.getSteps()) { expectedStepResults.add(new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SUCCEEDED)); } BootstrapResult expected = new BootstrapResult(expectedStepResults); Assert.assertEquals(expected, result); Assert.assertTrue(bootstrapService.isBootstrapped()); }
private BootstrapStepResult executeStep(BootstrapStep step, Predicate<BootstrapStep> shouldSkip) throws InterruptedException { try { step.validate(); } catch (IllegalArgumentException e) { LOG.warn("Bootstrap step {} failed because it is malformed: {}", step.getLabel(), e.getMessage()); return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.FAILED, e.getMessage()); } if (shouldSkip.test(step)) { return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.SKIPPED, null); } BootstrapStepExecutor bootstrapStepExecutor = bootstrapStepExecutors.get(step.getType()); if (bootstrapStepExecutor == null) { // should not be possible, as deserialization of the file into a BootStrapConfig should have failed return new BootstrapStepResult(step.getLabel(), BootstrapStepResult.Status.FAILED, String.format("Unknown bootstrap step type '%s' for '%s'.", step.getType(), step.getLabel())); } return bootstrapStepExecutor.execute(step.getLabel(), step.getArguments()); }
@Test public void testMissingProvisionerInfo() throws Exception { SystemProfileCreator.Arguments arguments = new SystemProfileCreator.Arguments("name", "label", "desc", null); BootstrapStepResult result = profileCreator.execute("label", GSON.toJsonTree(arguments).getAsJsonObject()); Assert.assertEquals(BootstrapStepResult.Status.FAILED, result.getStatus()); }
@Test public void testAlreadyExistsDoesNotError() throws Exception { profileService.saveProfile(ProfileId.NATIVE, Profile.NATIVE); BootstrapStepResult result = nativeProfileCreator.execute("label", new JsonObject()); BootstrapStepResult expected = new BootstrapStepResult("label", BootstrapStepResult.Status.SUCCEEDED); Assert.assertEquals(expected, result); Assert.assertEquals(Profile.NATIVE, profileService.getProfile(ProfileId.NATIVE)); } }
@Test public void testAllPreferenceSet() throws Exception { Map<String, String> preferences = new HashMap<>(); preferences.put("p1", "v1"); preferences.put("p2", "v2"); SystemPreferenceSetter.Arguments arguments = new SystemPreferenceSetter.Arguments(preferences); BootstrapStepResult result = systemPreferenceSetter.execute("label", GSON.toJsonTree(arguments).getAsJsonObject()); Assert.assertEquals(BootstrapStepResult.Status.SUCCEEDED, result.getStatus()); Assert.assertEquals(preferences, preferencesService.getProperties()); }
@Test public void testCreation() throws Exception { try { profileService.getProfile(ProfileId.NATIVE); Assert.fail("Native profile should not exist."); } catch (NotFoundException e) { // expected } BootstrapStepResult result = nativeProfileCreator.execute("label", new JsonObject()); BootstrapStepResult expected = new BootstrapStepResult("label", BootstrapStepResult.Status.SUCCEEDED); Assert.assertEquals(expected, result); Assert.assertEquals(Profile.NATIVE, profileService.getProfile(ProfileId.NATIVE)); }
@Test public void testExistingIsUnmodified() throws Exception { Map<String, String> preferences = new HashMap<>(); preferences.put("p1", "v1"); preferencesService.setProperties(preferences); preferences.put("p2", "v2"); preferences.put("p1", "v3"); SystemPreferenceSetter.Arguments arguments = new SystemPreferenceSetter.Arguments(preferences); BootstrapStepResult result = systemPreferenceSetter.execute("label", GSON.toJsonTree(arguments).getAsJsonObject()); Assert.assertEquals(BootstrapStepResult.Status.SUCCEEDED, result.getStatus()); Map<String, String> expected = new HashMap<>(); // p1 should not have been overridden expected.put("p1", "v1"); expected.put("p2", "v2"); Assert.assertEquals(expected, preferencesService.getProperties()); } }
@Test public void test() throws Exception { try { namespaceAdmin.get(NamespaceId.DEFAULT); Assert.fail("Default namespace should not exist."); } catch (NamespaceNotFoundException e) { // expected } // test that it creates the default namespace BootstrapStepResult result = defaultNamespaceCreator.execute("label", new JsonObject()); BootstrapStepResult expected = new BootstrapStepResult("label", BootstrapStepResult.Status.SUCCEEDED); Assert.assertEquals(expected, result); Assert.assertEquals(NamespaceMeta.DEFAULT, namespaceAdmin.get(NamespaceId.DEFAULT)); // test trying to create when it's already there won't error result = defaultNamespaceCreator.execute("label", new JsonObject()); expected = new BootstrapStepResult("label", BootstrapStepResult.Status.SUCCEEDED); Assert.assertEquals(expected, result); Assert.assertEquals(NamespaceMeta.DEFAULT, namespaceAdmin.get(NamespaceId.DEFAULT)); } }
@Test public void testMissingProfileName() throws Exception { List<ProvisionerPropertyValue> properties = new ArrayList<>(); properties.add(new ProvisionerPropertyValue("name1", "val1", true)); properties.add(new ProvisionerPropertyValue("name2", "val2", true)); ProvisionerInfo provisionerInfo = new ProvisionerInfo(MockProvisioner.NAME, properties); SystemProfileCreator.Arguments arguments = new SystemProfileCreator.Arguments("", "label", "desc", provisionerInfo); BootstrapStepResult result = profileCreator.execute("label", GSON.toJsonTree(arguments).getAsJsonObject()); Assert.assertEquals(BootstrapStepResult.Status.FAILED, result.getStatus()); }