@Test public void shouldErrorOutWhenTryingToAddTwoStagesWithSameName() { BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); PipelineTemplateConfig pipelineTemplateConfig = new PipelineTemplateConfig(new CaseInsensitiveString("template"), StageConfigMother.manualStage("stage1"), StageConfigMother.manualStage("stage1")); pipelineTemplateConfig.validate(ConfigSaveValidationContext.forChain(cruiseConfig)); assertThat(pipelineTemplateConfig.get(0).errors().isEmpty(), is(false)); assertThat(pipelineTemplateConfig.get(1).errors().isEmpty(), is(false)); assertThat(pipelineTemplateConfig.get(0).errors().on(StageConfig.NAME), is("You have defined multiple stages called 'stage1'. Stage names are case-insensitive and must be unique.")); assertThat(pipelineTemplateConfig.get(1).errors().on(StageConfig.NAME), is("You have defined multiple stages called 'stage1'. Stage names are case-insensitive and must be unique.")); }
@Test public void shouldValidateTree(){ EnvironmentVariablesConfig variables = mock(EnvironmentVariablesConfig.class); JobConfigs jobConfigs = mock(JobConfigs.class); Approval approval = mock(Approval.class); StageConfig stageConfig = new StageConfig(new CaseInsensitiveString("stage$"), jobConfigs, approval); stageConfig.setVariables(variables); stageConfig.validateTree(PipelineConfigSaveValidationContext.forChain(true, "group", new PipelineConfig(), stageConfig)); assertThat(stageConfig.errors().on(StageConfig.NAME), contains("Invalid stage name 'stage$'")); ArgumentCaptor<PipelineConfigSaveValidationContext> captor = ArgumentCaptor.forClass(PipelineConfigSaveValidationContext.class); verify(jobConfigs).validateTree(captor.capture()); PipelineConfigSaveValidationContext childContext = captor.getValue(); assertThat(childContext.getParent(), is(stageConfig)); verify(approval).validateTree(childContext); verify(variables).validateTree(childContext); }
public static void toJSON(OutputWriter jsonWriter, StageConfig stageConfig) { if (!stageConfig.errors().isEmpty()) { jsonWriter.addChild("errors", errorWriter -> { new ErrorGetter(new HashMap<>()).toJSON(errorWriter, stageConfig); }); } jsonWriter.addIfNotNull("name", stageConfig.name()); jsonWriter.add("fetch_materials", stageConfig.isFetchMaterials()); jsonWriter.add("clean_working_directory", stageConfig.isCleanWorkingDir()); jsonWriter.add("never_cleanup_artifacts", stageConfig.isArtifactCleanupProhibited()); jsonWriter.addChild("approval", approvalWriter -> ApprovalRepresenter.toJSON(approvalWriter, stageConfig.getApproval())); jsonWriter.addChildList("environment_variables", envVarsWriter -> EnvironmentVariableRepresenter.toJSON(envVarsWriter, stageConfig.getVariables())); jsonWriter.addChildList("jobs", getJobs(stageConfig)); }
public static void toJSON(OutputWriter jsonWriter, StageConfig stageConfig) { if (!stageConfig.errors().isEmpty()) { jsonWriter.addChild("errors", errorWriter -> { new ErrorGetter(new HashMap<>()).toJSON(errorWriter, stageConfig); }); } jsonWriter.addIfNotNull("name", stageConfig.name()); jsonWriter.add("fetch_materials", stageConfig.isFetchMaterials()); jsonWriter.add("clean_working_directory", stageConfig.isCleanWorkingDir()); jsonWriter.add("never_cleanup_artifacts", stageConfig.isArtifactCleanupProhibited()); jsonWriter.addChild("approval", approvalWriter -> ApprovalRepresenter.toJSON(approvalWriter, stageConfig.getApproval())); jsonWriter.addChildList("environment_variables", envVarsWriter -> EnvironmentVariableRepresenter.toJSON(envVarsWriter, stageConfig.getVariables())); jsonWriter.addChildList("jobs", getJobs(stageConfig)); }
@Test public void shouldEnsureStageNameUniqueness() { CruiseConfig cruiseConfig = new BasicCruiseConfig(); PipelineConfig pipelineConfig = goConfigMother.addPipeline(cruiseConfig, "pipeline1", "stage", "build"); JobConfig jobConfig = new JobConfig("my-build"); jobConfig.addTask(new ExecTask("ls", "-la", "tmp")); StageConfig stageConfig = new StageConfig(new CaseInsensitiveString("stage"), new JobConfigs(jobConfig)); pipelineConfig.addStageWithoutValidityAssertion(stageConfig); pipelineConfig.validate(null); assertThat(stageConfig.errors().getAllOn("name"), is(singletonList("You have defined multiple stages called 'stage'. Stage names are case-insensitive and must be unique."))); assertThat(pipelineConfig.get(0).errors().getAllOn("name"), is(singletonList("You have defined multiple stages called 'stage'. Stage names are case-insensitive and must be unique."))); assertThat(cruiseConfig.validateAfterPreprocess().get(0).getAllOn("name"), is(singletonList("You have defined multiple stages called 'stage'. Stage names are case-insensitive and must be unique."))); }
@Test public void shouldFailValidationWhenNameIsBlank(){ StageConfig stageConfig = new StageConfig(); stageConfig.validate(null); assertThat(stageConfig.errors().on(StageConfig.NAME), contains("Invalid stage name 'null'")); stageConfig.setName(null); stageConfig.validate(null); assertThat(stageConfig.errors().on(StageConfig.NAME), contains("Invalid stage name 'null'")); stageConfig.setName(new CaseInsensitiveString("")); stageConfig.validate(null); assertThat(stageConfig.errors().on(StageConfig.NAME), contains("Invalid stage name 'null'")); }
@Test public void shouldAddValidateTreeErrorsOnStageConfigIfPipelineIsAssociatedToATemplate(){ Approval approval = mock(Approval.class); JobConfigs jobConfigs = mock(JobConfigs.class); ConfigErrors jobErrors = new ConfigErrors(); jobErrors.add("KEY", "ERROR"); when(jobConfigs.errors()).thenReturn(jobErrors); StageConfig stageConfig = new StageConfig(new CaseInsensitiveString("stage$"), jobConfigs, approval); PipelineConfig pipelineConfig = new PipelineConfig(); pipelineConfig.setTemplateName(new CaseInsensitiveString("template")); stageConfig.validateTree(PipelineConfigSaveValidationContext.forChain(true, "group", pipelineConfig, stageConfig)); assertThat(stageConfig.errors().on(StageConfig.NAME), contains("Invalid stage name 'stage$'")); }
protected void shouldCollectAllTheErrorsInTheChildrenHelper(CruiseConfig config) { SecurityAuthConfig ldapConfig = new SecurityAuthConfig("ldap", "cd.go.authorization.ldap"); ldapConfig.errors().add("uri", "invalid ldap uri"); ldapConfig.errors().add("searchBase", "invalid search base"); config.server().security().securityAuthConfigs().add(ldapConfig); PipelineConfig pipelineConfig = config.pipelineConfigByName(new CaseInsensitiveString("pipeline-1")); pipelineConfig.errors().add("base", "Some base errors"); P4MaterialConfig p4MaterialConfig = new P4MaterialConfig("localhost:1999", "view"); p4MaterialConfig.setConfigAttributes(Collections.singletonMap(ScmMaterialConfig.FOLDER, "p4_folder")); pipelineConfig.addMaterialConfig(p4MaterialConfig); p4MaterialConfig.errors().add("materialName", "material name does not follow pattern"); StageConfig stage = pipelineConfig.first(); stage.errors().add("role", "Roles must be proper"); List<ConfigErrors> allErrors = config.validateAfterPreprocess(); assertThat(allErrors.size(), is(5)); assertThat(allErrors.get(0).on("uri"), is("invalid ldap uri")); assertThat(allErrors.get(0).on("searchBase"), is("invalid search base")); assertThat(allErrors.get(1).on("base"), is("Some base errors")); assertThat(allErrors.get(2).on("role"), is("Roles must be proper")); assertThat(allErrors.get(3).on(ScmMaterialConfig.FOLDER), is("Destination directory is required when specifying multiple scm materials")); assertThat(allErrors.get(4).on("materialName"), is("material name does not follow pattern")); }
@Test public void shouldHandleNullStageNamesWhileValidating() { StageConfig s1 = new StageConfig(); StageConfig s2 = new StageConfig(new CaseInsensitiveString("s2"), new JobConfigs()); PipelineConfig pipeline = new PipelineConfig(new CaseInsensitiveString("p1"), new MaterialConfigs(), s1, s2); pipeline.validate(null); assertThat(s1.errors().on(StageConfig.NAME).contains("Invalid stage name 'null'"), is(true)); }
@Test public void getAllErrors_shouldCollectAllErrorsInTheChildren() { CruiseConfig config = GoConfigMother.configWithPipelines("pipeline-1"); SecurityAuthConfig ldapConfig = new SecurityAuthConfig("ldap", "cd.go.authorization.ldap"); ldapConfig.errors().add("uri", "invalid ldap uri"); ldapConfig.errors().add("searchBase", "invalid search base"); config.server().security().securityAuthConfigs().add(ldapConfig); PipelineConfig pipelineConfig = config.pipelineConfigByName(new CaseInsensitiveString("pipeline-1")); pipelineConfig.errors().add("base", "Some base errors"); P4MaterialConfig p4MaterialConfig = new P4MaterialConfig("localhost:1999", "view"); pipelineConfig.addMaterialConfig(p4MaterialConfig); p4MaterialConfig.errors().add("materialName", "material name does not follow pattern"); StageConfig stage = pipelineConfig.first(); stage.errors().add("role", "Roles must be proper"); List<ConfigErrors> allErrors = config.getAllErrors(); assertThat(allErrors.size(), is(4)); assertThat(allErrors.get(0).on("uri"), is("invalid ldap uri")); assertThat(allErrors.get(0).on("searchBase"), is("invalid search base")); assertThat(allErrors.get(1).on("base"), is("Some base errors")); assertThat(allErrors.get(2).on("role"), is("Roles must be proper")); assertThat(allErrors.get(3).on("materialName"), is("material name does not follow pattern")); }
@Test public void getAllErrors_shouldIgnoreErrorsOnElementToBeSkipped() { CruiseConfig config = GoConfigMother.configWithPipelines("pipeline-1"); SecurityAuthConfig ldapConfig = new SecurityAuthConfig("ldap", "cd.go.authorization.ldap"); ldapConfig.errors().add("uri", "invalid ldap uri"); ldapConfig.errors().add("searchBase", "invalid search base"); config.server().security().securityAuthConfigs().add(ldapConfig); PipelineConfig pipelineConfig = config.pipelineConfigByName(new CaseInsensitiveString("pipeline-1")); pipelineConfig.errors().add("base", "Some base errors"); P4MaterialConfig p4MaterialConfig = new P4MaterialConfig("localhost:1999", "view"); pipelineConfig.addMaterialConfig(p4MaterialConfig); p4MaterialConfig.errors().add("materialName", "material name does not follow pattern"); StageConfig stage = pipelineConfig.first(); stage.errors().add("role", "Roles must be proper"); List<ConfigErrors> allErrors = config.getAllErrorsExceptFor(p4MaterialConfig); assertThat(allErrors.size(), is(3)); assertThat(allErrors.get(0).on("uri"), is("invalid ldap uri")); assertThat(allErrors.get(0).on("searchBase"), is("invalid search base")); assertThat(allErrors.get(1).on("base"), is("Some base errors")); assertThat(allErrors.get(2).on("role"), is("Roles must be proper")); }
@Test public void shouldPopulateErrorMessagesWhenHasJobNamesRepeated() { CruiseConfig config = new BasicCruiseConfig(); PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline", "stage-1", "con-job"); config.addPipeline("group-foo", pipelineConfig); StageConfig stageConfig = pipelineConfig.get(0); JobConfig newJob = new JobConfig("foo!"); StageConfig newlyAddedStage = new StageConfig(new CaseInsensitiveString("."), new JobConfigs(newJob)); pipelineConfig.addStageWithoutValidityAssertion(newlyAddedStage); stageConfig.getJobs().addJobWithoutValidityAssertion(new JobConfig(new CaseInsensitiveString("con-job"), new ResourceConfigs(), new ArtifactConfigs(), new Tasks(new ExecTask("ls", "-la", "foo")))); List<ConfigErrors> allErrors = config.validateAfterPreprocess(); assertThat(allErrors.size(), is(4)); assertThat(allErrors.get(0).on(JobConfig.NAME), is("You have defined multiple jobs called 'con-job'. Job names are case-insensitive and must be unique.")); assertThat(allErrors.get(1).on(JobConfig.NAME), is("You have defined multiple jobs called 'con-job'. Job names are case-insensitive and must be unique.")); assertThat(allErrors.get(2).on(StageConfig.NAME), is("Invalid stage name '.'. This must be alphanumeric and can contain underscores and periods (however, it cannot start with a period). The maximum allowed length is 255 characters.")); assertThat(allErrors.get(3).on(JobConfig.NAME), is("Invalid job name 'foo!'. This must be alphanumeric and may contain underscores and periods. The maximum allowed length is 255 characters.")); assertThat(stageConfig.getJobs().get(0).errors().on(JobConfig.NAME), is("You have defined multiple jobs called 'con-job'. Job names are case-insensitive and must be unique.")); assertThat(stageConfig.getJobs().get(1).errors().on(JobConfig.NAME), is("You have defined multiple jobs called 'con-job'. Job names are case-insensitive and must be unique.")); assertThat(newlyAddedStage.errors().on(StageConfig.NAME), is("Invalid stage name '.'. This must be alphanumeric and can contain underscores and periods (however, it cannot start with a period). The maximum allowed length is 255 characters.")); assertThat(newJob.errors().on(JobConfig.NAME), is("Invalid job name 'foo!'. This must be alphanumeric and may contain underscores and periods. The maximum allowed length is 255 characters.")); }
@Test public void shouldCopyErrorsForFieldsOnPipelineConfig(){ PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig("pipeline", MaterialConfigsMother.defaultMaterialConfigs(), new JobConfigs(JobConfigMother.createJobConfigWithJobNameAndEmptyResources())); pipelineConfig.setVariables(new EnvironmentVariablesConfig(asList(new EnvironmentVariableConfig("name", "value")))); PipelineConfig pipelineWithErrors = new Cloner().deepClone(pipelineConfig); pipelineWithErrors.getVariables().get(0).addError("name", "error on environment variable"); pipelineWithErrors.first().addError("name", "error on stage"); pipelineWithErrors.first().getJobs().first().addError("name", "error on job"); BasicCruiseConfig.copyErrors(pipelineWithErrors, pipelineConfig); assertThat(pipelineConfig.getVariables().get(0).errors().on("name"), is("error on environment variable")); assertThat(pipelineConfig.first().errors().on("name"), is("error on stage")); assertThat(pipelineConfig.first().getJobs().first().errors().on("name"), is("error on job")); }
@Test public void getAllErrors_shouldRetainAllErrorsWhenNoSubjectGiven() { CruiseConfig config = GoConfigMother.configWithPipelines("pipeline-1"); SecurityAuthConfig ldapConfig = new SecurityAuthConfig("ldap", "cd.go.authorization.ldap"); ldapConfig.errors().add("uri", "invalid ldap uri"); ldapConfig.errors().add("searchBase", "invalid search base"); config.server().security().securityAuthConfigs().add(ldapConfig); PipelineConfig pipelineConfig = config.pipelineConfigByName(new CaseInsensitiveString("pipeline-1")); pipelineConfig.errors().add("base", "Some base errors"); P4MaterialConfig p4MaterialConfig = new P4MaterialConfig("localhost:1999", "view"); pipelineConfig.addMaterialConfig(p4MaterialConfig); p4MaterialConfig.errors().add("materialName", "material name does not follow pattern"); StageConfig stage = pipelineConfig.first(); stage.errors().add("role", "Roles must be proper"); List<ConfigErrors> allErrors = config.getAllErrorsExceptFor(null); assertThat(allErrors.size(), is(4)); }
@Test public void shouldHandlePipelinesWithTemplates() { CruiseConfig cruiseConfig = GoConfigMother.configWithPipelines("pipeline-1"); cruiseConfig.getTemplates().add( new PipelineTemplateConfig(new CaseInsensitiveString("template-1"), new StageConfig(new CaseInsensitiveString("invalid stage name"), new JobConfigs(new JobConfig("job-1")) ))); PipelineConfig pipelineWithTemplate = new PipelineConfig(new CaseInsensitiveString("pipeline-with-template"), MaterialConfigsMother.defaultMaterialConfigs()); pipelineWithTemplate.setTemplateName(new CaseInsensitiveString("template-1")); cruiseConfig.getGroups().get(0).add(pipelineWithTemplate); CruiseConfig rawCruiseConfig = new Cloner().deepClone(cruiseConfig); MagicalGoConfigXmlLoader.validate(cruiseConfig); cruiseConfig.copyErrorsTo(rawCruiseConfig); assertThat(rawCruiseConfig.pipelineConfigByName(new CaseInsensitiveString("pipeline-with-template")).errors().isEmpty(), is(true)); assertThat(cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("pipeline-with-template")).getStage(new CaseInsensitiveString("invalid stage name")).errors().isEmpty(), is(false)); assertThat(rawCruiseConfig.getTemplateByName(new CaseInsensitiveString("template-1")).errors().isEmpty(), is(true)); }