private void validateElasticProfileId(JobConfig jobConfig, PipelineConfigSaveValidationContext preprocessedConfig) { String elasticProfileId = jobConfig.getElasticProfileId(); if (elasticProfileId != null && !preprocessedConfig.isValidProfileId(elasticProfileId)) { String message = String.format("No profile defined corresponding to profile_id '%s'", elasticProfileId); jobConfig.addError("elasticProfileId", message); this.errors().addAll(jobConfig.errors()); } }
private void validateFetchTasks(JobConfig jobConfig, PipelineConfigSaveValidationContext contextForTasks) { for (Task task : jobConfig.getTasks()) { if (task instanceof AbstractFetchTask) { task.validate(contextForTasks); this.errors().addAll(task.errors()); } } }
private void validateTemplateName() { if (!new NameTypeValidator().isNameValid(name)) { errors().add(NAME, NameTypeValidator.errorMessage("template", name)); } }
private void validateStageApprovalAuthorization(StageConfig stageConfig, PipelineConfigSaveValidationContext contextForChildren) { Approval approval = stageConfig.getApproval(); if (!approval.validateTree(contextForChildren)) { for (ConfigErrors errors : approval.getAllErrors()) { this.errors().addAll(errors); } } }
private void validateDependenciesOfDownstreams(PipelineConfig pipelineConfig, PipelineConfigSaveValidationContext contextForStages) { PipelineConfigTreeValidator pipelineConfigTreeValidator = new PipelineConfigTreeValidator(pipelineConfig); pipelineConfigTreeValidator.validateDependencies(contextForStages); this.errors().addAll(pipelineConfig.errors()); }
private void validatePluggableArtifactConfig(JobConfig jobConfig, PipelineConfigSaveValidationContext contextForJobChildren) { for (PluggableArtifactConfig pluggableArtifactConfig : jobConfig.artifactConfigs().getPluggableArtifactConfigs()) { if (!pluggableArtifactConfig.validateTree(contextForJobChildren)) { for (ConfigErrors errors : pluggableArtifactConfig.getAllErrors()) { this.errors().addAll(errors); } } } }
public static void toJSON(OutputWriter jsonWriter, PipelineTemplateConfig pipelineTemplateConfig) { jsonWriter.addLinks(linksWriter -> linksWriter .addLink("self", Routes.PipelineTemplateConfig.name(pipelineTemplateConfig.name().toString())) .addAbsoluteLink("doc", Routes.PipelineTemplateConfig.DOC) .addLink("find", Routes.PipelineTemplateConfig.find())); if (!pipelineTemplateConfig.errors().isEmpty()) { jsonWriter.addChild("errors", errorWriter -> { HashMap<String, String> errorMapping = new HashMap<>(); new ErrorGetter(new HashMap<>()).toJSON(errorWriter, pipelineTemplateConfig); }); } jsonWriter.add("name", pipelineTemplateConfig.name()); writeStages(jsonWriter, pipelineTemplateConfig); }
@Test public void shouldErrorOutIfTemplateNameIsAlreadyPresent() { PipelineTemplateConfig template = template("template1"); TemplatesConfig templates = new TemplatesConfig(template); PipelineTemplateConfig duplicateTemplate = template("template1"); templates.add(duplicateTemplate); templates.validate(null); assertThat(template.errors().isEmpty(), is(false)); assertThat(duplicateTemplate.errors().isEmpty(), is(false)); assertThat(template.errors().on(PipelineTemplateConfig.NAME), is(String.format("Template name '%s' is not unique", template.name()))); assertThat(duplicateTemplate.errors().on(PipelineTemplateConfig.NAME), is(String.format("Template name '%s' is not unique", template.name()))); }
@Test public void shouldErrorOutIfTemplateNameIsAlreadyPresent_CaseInsensitiveMap() { PipelineTemplateConfig template = template("TEmplatE1"); TemplatesConfig templates = new TemplatesConfig(template); PipelineTemplateConfig duplicateTemplate = template("template1"); templates.add(duplicateTemplate); templates.validate(null); assertThat(template.errors().isEmpty(), is(false)); assertThat(duplicateTemplate.errors().isEmpty(), is(false)); }
@Test public void validate_shouldEnsureThatTemplateFollowsTheNameType() { BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); PipelineTemplateConfig config = new PipelineTemplateConfig(new CaseInsensitiveString(".Abc")); config.validate(ConfigSaveValidationContext.forChain(cruiseConfig)); assertThat(config.errors().isEmpty(), is(false)); assertThat(config.errors().on(PipelineTemplateConfig.NAME), is("Invalid template name '.Abc'. This must be alphanumeric and can contain underscores and periods (however, it cannot start with a period). The maximum allowed length is 255 characters.")); }
@Test public void shouldValidateWhetherTheReferredParamsAreDefinedInPipelinesUsingTheTemplate() { PipelineTemplateConfig templateWithParams = PipelineTemplateConfigMother.createTemplateWithParams("template", "param1", "param2"); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(templateWithParams); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); templateWithParams.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(templateWithParams.errors().getAllOn("params"), is(Arrays.asList("The param 'param1' is not defined in pipeline 'pipeline'", "The param 'param2' is not defined in pipeline 'pipeline'"))); }
@Test public void shouldAllowEditingOfStageNameWhenItIsNotUsedAsDependencyMaterial() throws Exception { PipelineTemplateConfig template = new PipelineTemplateConfig(new CaseInsensitiveString("template"), StageConfigMother.oneBuildPlanWithResourcesAndMaterials("stage2")); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); template.getStages().get(0).setName(new CaseInsensitiveString("updatedStageName")); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().isEmpty(), is(true)); }
@Test public void shouldAllowEditingOfJobNameWhenItIsNotUsedAsFetchArtifact() throws Exception { PipelineTemplateConfig template = new PipelineTemplateConfig(new CaseInsensitiveString("template"), StageConfigMother.oneBuildPlanWithResourcesAndMaterials("stage", "job2")); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); template.getStages().get(0).getJobs().get(0).setName(new CaseInsensitiveString("updatedJobName")); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().isEmpty(), is(true)); }
@Test public void shouldValidatePublishExternalArtifactOfATemplateInTheContextOfPipelinesUsingTheTemplate() throws Exception { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("defaultJob")); jobConfig.artifactConfigs().add(new PluggableArtifactConfig("some-id", "non-existent-store-id")); JobConfigs jobConfigs = new JobConfigs(jobConfig); StageConfig stageConfig = StageConfigMother.custom("stage", jobConfigs); PipelineTemplateConfig template = PipelineTemplateConfigMother.createTemplate("template", stageConfig); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); pipelineConfig.usingTemplate(template); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().getAllOn("storeId"), is(Arrays.asList("Artifact store with id `non-existent-store-id` does not exist. Please correct the `storeId` attribute on pipeline `pipeline`."))); }
@Test public void shouldValidateFetchTasksOfATemplateInTheContextOfPipelinesUsingTheTemplate() throws Exception { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("defaultJob")); jobConfig.addTask(new FetchTask(new CaseInsensitiveString("non-existent-pipeline"), new CaseInsensitiveString("stage"), new CaseInsensitiveString("job"), "src", "dest")); JobConfigs jobConfigs = new JobConfigs(jobConfig); StageConfig stageConfig = StageConfigMother.custom("stage", jobConfigs); PipelineTemplateConfig template = PipelineTemplateConfigMother.createTemplate("template", stageConfig); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); pipelineConfig.usingTemplate(template); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().getAllOn("pipeline"), is(Arrays.asList("\"pipeline :: stage :: defaultJob\" tries to fetch artifact from pipeline \"non-existent-pipeline\" which does not exist."))); }
@Test public void shouldValidateFetchPluggableTasksOfATemplateInTheContextOfPipelinesUsingTheTemplate() throws Exception { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("defaultJob")); jobConfig.addTask(new FetchPluggableArtifactTask(new CaseInsensitiveString("non-existent-pipeline"), new CaseInsensitiveString("stage"), new CaseInsensitiveString("job"), "artifactId")); JobConfigs jobConfigs = new JobConfigs(jobConfig); StageConfig stageConfig = StageConfigMother.custom("stage", jobConfigs); PipelineTemplateConfig template = PipelineTemplateConfigMother.createTemplate("template", stageConfig); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); pipelineConfig.usingTemplate(template); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().getAllOn("pipeline"), is(Arrays.asList("\"pipeline :: stage :: defaultJob\" tries to fetch artifact from pipeline \"non-existent-pipeline\" which does not exist."))); }
@Test public void shouldValidateStageApprovalAuthorizationOfATemplateInTheContextOfPipelinesUsingTheTemplate() throws Exception { JobConfig jobConfig = new JobConfig(new CaseInsensitiveString("defaultJob")); JobConfigs jobConfigs = new JobConfigs(jobConfig); StageConfig stageConfig = StageConfigMother.custom("stage", jobConfigs); stageConfig.setApproval(new Approval(new AuthConfig(new AdminRole(new CaseInsensitiveString("non-existent-role"))))); PipelineTemplateConfig template = PipelineTemplateConfigMother.createTemplate("template", stageConfig); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); pipelineConfig.usingTemplate(template); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().getAllOn("name"), is(Arrays.asList("Role \"non-existent-role\" does not exist."))); }
@Test public void shouldAddErrorsToRawCruiseConfigWhenTemplateHasErrors() { CruiseConfig cruiseConfig = GoConfigMother.configWithPipelines("pipeline-1"); cruiseConfig.getTemplates().add( new PipelineTemplateConfig(new CaseInsensitiveString("invalid template name"), new StageConfig(new CaseInsensitiveString("stage-1"), new JobConfigs(new JobConfig("job-1")) ))); PipelineConfig pipelineWithTemplate = new PipelineConfig(new CaseInsensitiveString("pipeline-with-template"), MaterialConfigsMother.defaultMaterialConfigs()); pipelineWithTemplate.setTemplateName(new CaseInsensitiveString("invalid template name")); cruiseConfig.getGroups().get(0).add(pipelineWithTemplate); CruiseConfig rawCruiseConfig = new Cloner().deepClone(cruiseConfig); MagicalGoConfigXmlLoader.validate(cruiseConfig); cruiseConfig.copyErrorsTo(rawCruiseConfig); ConfigErrors templateErrors = rawCruiseConfig.getTemplateByName(new CaseInsensitiveString("invalid template name")).errors(); assertThat(templateErrors.getAll().size(), is(1)); assertThat(templateErrors.getAll().get(0), is("Invalid template name 'invalid template 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.")); }
@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)); }
@Test public void shouldValidateStagePermissionsOfATemplateStageInTheContextOfPipelineUsingTheTemplate() { StageConfig stageConfig = StageConfigMother.custom("stage", new JobConfigs(new JobConfig(new CaseInsensitiveString("defaultJob")))); stageConfig.setApproval(new Approval(new AuthConfig(new AdminUser(new CaseInsensitiveString("non-admin-non-operate"))))); PipelineTemplateConfig template = PipelineTemplateConfigMother.createTemplate("template", stageConfig); PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfigWithTemplate("pipeline", "template"); pipelineConfig.usingTemplate(template); BasicCruiseConfig cruiseConfig = GoConfigMother.defaultCruiseConfig(); cruiseConfig.addTemplate(template); cruiseConfig.addPipelineWithoutValidation("group", pipelineConfig); PipelineConfigs group = cruiseConfig.findGroup("group"); group.setAuthorization(new Authorization(new ViewConfig(), new OperationConfig(new AdminUser(new CaseInsensitiveString("foo"))), new AdminsConfig())); cruiseConfig.server().security().securityAuthConfigs().add(new SecurityAuthConfig()); cruiseConfig.server().security().adminsConfig().add(new AdminUser(new CaseInsensitiveString("super-admin"))); template.validateTree(ConfigSaveValidationContext.forChain(cruiseConfig), cruiseConfig, false); assertThat(template.errors().getAllOn("name"), is(Arrays.asList("User \"non-admin-non-operate\" who is not authorized to operate pipeline group `group` can not be authorized to approve stage"))); }