@Test public void shouldNotUpdateEnvironmentIfEditingOverAStaleCopy() throws Exception { configHelper.addEnvironments("prod"); String staleMd5 = goConfigDao.md5OfConfigFile(); service.updateEnvironment( "prod", environmentConfig("uat1"), new Username(new CaseInsensitiveString("foo")), staleMd5); assertThat("md5 should be stale", goConfigDao.md5OfConfigFile(), is(not(staleMd5))); HttpLocalizedOperationResult result = service.updateEnvironment( "prod", environmentConfig("uat2"), new Username(new CaseInsensitiveString("foo")), staleMd5); assertThat(result.isSuccessful(), is(false)); assertThat( result.message(localizer), is( "Failed to update environment 'prod'. " + ConfigFileHasChangedException.CONFIG_CHANGED_PLEASE_REFRESH)); }
@Test public void shouldReturnConflictIfGetRequestUsesIncorrectConfigMD5() throws Exception { String oldMd5 = goConfigDao.md5OfConfigFile(); configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String newMd5 = goConfigDao.md5OfConfigFile(); controller.getBuildAsXmlPartial("pipeline", "stage", 1, oldMd5, response); assertValidContentAndStatus( SC_CONFLICT, RESPONSE_CHARSET, ConfigFileHasChangedException.CONFIG_CHANGED_PLEASE_REFRESH); assertThat(response.getHeader(XmlAction.X_CRUISE_CONFIG_MD5), is(newMd5)); }
@Test public void shouldReturnXmlAndErrorMessageWhenPostOfPipelineAsInvalidPartialXml() throws Exception { groupName = BasicPipelineConfigs.DEFAULT_GROUP; configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String badXml = "<pipeline name=\"cruise\" labeltemplate=\"invalid\">\n" + " <materials>\n" + " <svn url=\"file:///tmp/foo\" checkexternals=\"true\" />\n" + " </materials>\n" + " <stage name=\"dev\">\n" + " <jobs>\n" + " <job name=\"linux\" />\n" + " <job name=\"windows\" />\n" + " </jobs>\n" + " </stage>\n" + "</pipeline>"; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postPipelineAsXmlPartial(0, groupName, badXml, md5, response); assertThat(response.getStatus(), is(SC_CONFLICT)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map<String, String> json = (Map) mav.getModel().get("json"); assertThat(json.get("result").toString(), containsString("Label is invalid")); assertThat(json.get("originalContent"), is(badXml)); }
@Test public void shouldGetBuildAsPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String md5 = goConfigDao.md5OfConfigFile(); controller.getBuildAsXmlPartial("pipeline", "stage", 1, null, response); assertValidContentAndStatus(SC_OK, "text/xml", "<job name=\"build2\" />"); assertThat(response.getHeader(XmlAction.X_CRUISE_CONFIG_MD5), is(md5)); }
@Test public void shouldPostGroupWithChangedNameAsPartialXml() throws Exception { configHelper.addPipelineWithGroup("group", "pipeline", "dev", "linux", "windows"); String newXml = RENAMED_GROUP; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postGroupAsXmlPartial("group", newXml, md5, response); assertThat(response.getStatus(), is(SC_OK)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); assertResponseMessage(mav, "Group changed successfully."); }
@Test public void shouldPostStageAsPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String newXml = NEW_STAGE; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postStageAsXmlPartial("pipeline", 0, newXml, md5, response); assertThat(response.getStatus(), is(SC_OK)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map json = (Map) mav.getModel().get("json"); new JsonTester(json).shouldContain("{ 'result' : 'Stage changed successfully.' }"); }
@Test public void shouldGetConfigAsXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); controller.getCurrentConfigXml(null, response); ByteArrayOutputStream os = new ByteArrayOutputStream(); new MagicalGoConfigXmlWriter(new ConfigCache(), registry, metricsProbeService) .write(goConfigDao.loadForEditing(), os, true); assertValidContentAndStatus(SC_OK, "text/xml", os.toString()); assertThat( response.getHeader(XmlAction.X_CRUISE_CONFIG_MD5), is(goConfigDao.md5OfConfigFile())); }
@Test public void shouldReturnXmlAndErrorMessageWhenInvalidPostOfStageAsPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postStageAsXmlPartial("pipeline", 4, NEW_STAGE, md5, response); assertThat(response.getStatus(), is(SC_NOT_FOUND)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map<String, Object> json = (Map) mav.getModel().get("json"); Map<String, Object> jsonMap = new LinkedHashMap<>(); jsonMap.put("result", "Stage does not exist."); jsonMap.put("originalContent", NEW_STAGE); assertThat(json, is(jsonMap)); }
private String setUpPipelineGroupsWithAdminPermissions() throws IOException { setCurrentUser("ram"); assertThat(CaseInsensitiveString.str(UserHelper.getUserName().getUsername()), is("ram")); configHelper.addPipelineWithGroup("studios", "go", "stage", "build1", "build2"); configHelper.setAdminPermissionForGroup("studios", "barrow"); configHelper.addPipelineWithGroup("consulting", "bcg", "stage", "build1", "build2"); configHelper.setAdminPermissionForGroup("consulting", "ram"); configHelper.addTemplate("newTemplate", "stage"); return goConfigDao.md5OfConfigFile(); }
@Test public void shouldReturnXmlAndErrorMessageWhenInvalidPostOfBuildAsPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String newXml = "<job name=\"build3\" />"; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postBuildAsXmlPartial("pipeline", "stage", 4, newXml, md5, response); assertThat(response.getStatus(), is(SC_NOT_FOUND)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map json = (Map) mav.getModel().get("json"); new JsonTester(json) .shouldContain( "{ 'result' : 'Build does not exist.'," + " 'originalContent' : '" + newXml + "' }"); }
@Test public void shouldModifyExistingPipelineTemplateWhenPostedAsPartial() throws Exception { configHelper.addPipelineWithGroup( "some-group", "some-pipeline", "some-dev", "some-linux", "some-windows"); configHelper.addAgent("some-home", "UUID"); String newXml = NEW_TEMPLATES; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postGroupAsXmlPartial("Pipeline Templates", newXml, md5, response); assertResponseMessage(mav, "Template changed successfully."); assertThat(response.getStatus(), is(SC_OK)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); assertThat(configHelper.currentConfig().getTemplates().size(), is(1)); }
@Test public void shouldReturnXmlAndErrorMessageWhenPostOfStageAsInvalidPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String badXml = "<;askldjfa;dsklfja;sdjas;lkdf"; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postStageAsXmlPartial("pipeline", 0, badXml, md5, response); assertThat(response.getStatus(), is(SC_CONFLICT)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map json = (Map) mav.getModel().get("json"); new JsonTester(json) .shouldContain( "{ 'result' : 'Error on line 1 of document : The markup in the document preceding the root element must be well-formed. Nested exception: The markup in the document preceding the root element must be well-formed.'," + " 'originalContent' : '" + badXml + "' }"); }
@Test public void shouldConflictWhenGivenMd5IsDifferent() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); controller.getCurrentConfigXml("crapy_md5", response); ByteArrayOutputStream os = new ByteArrayOutputStream(); new MagicalGoConfigXmlWriter( new ConfigCache(), ConfigElementImplementationRegistryMother.withNoPlugins(), metricsProbeService) .write(goConfigDao.loadForEditing(), os, true); assertValidContentAndStatus( SC_CONFLICT, "text/plain; charset=utf-8", CONFIG_CHANGED_PLEASE_REFRESH); assertThat( response.getHeader(XmlAction.X_CRUISE_CONFIG_MD5), is(goConfigDao.md5OfConfigFile())); }
@Test public void shouldReturnBadRequestForUpdateWhenUsingInvalidEnvName() { configHelper.addEnvironments("foo-env"); HttpLocalizedOperationResult result = service.updateEnvironment( "foo-env", env( "foo env", new ArrayList<String>(), new ArrayList<Map<String, String>>(), new ArrayList<String>()), new Username(new CaseInsensitiveString("any")), goConfigDao.md5OfConfigFile()); assertThat(result.httpCode(), is(HttpServletResponse.SC_BAD_REQUEST)); assertThat( result.message(localizer), containsString("Failed to update environment 'foo-env'.")); }
@Test public void shouldReturnXmlAndErrorMessageWhenPostOfBuildWithDuplicatedNameAsPartialXml() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String newXml = "<job name=\"build2\" />"; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postBuildAsXmlPartial("pipeline", "stage", 0, newXml, md5, response); assertThat(response.getStatus(), is(SC_CONFLICT)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map<String, Object> json = (Map) mav.getModel().get("json"); Map<String, Object> expected = new LinkedHashMap<>(); expected.put( "result", "Duplicate unique value [build2] declared for identity constraint \"uniqueJob\" of element \"jobs\"."); expected.put("originalContent", newXml); assertThat(json, is(expected)); }
@Test public void shouldReturnTheCorrectLocalizedMessageForUpdateWhenDuplicateEnvironmentExists() { configHelper.addEnvironments("foo-env"); configHelper.addEnvironments("bar-env"); HttpLocalizedOperationResult result = service.updateEnvironment( "bar-env", env( "foo-env", new ArrayList<String>(), new ArrayList<Map<String, String>>(), new ArrayList<String>()), new Username(new CaseInsensitiveString("any")), goConfigDao.md5OfConfigFile()); assertThat( result.message(localizer), is( "Failed to update environment 'bar-env'. Duplicate unique value [foo-env] declared for identity constraint \"uniqueEnvironmentName\" of element \"environments\".")); }
@Test public void shouldUpdateExistingEnvironment() throws Exception { BasicEnvironmentConfig uat = environmentConfig("uat"); goConfigService.addPipeline( PipelineConfigMother.createPipelineConfig("foo", "dev", "job"), "foo-grp"); goConfigService.addPipeline( PipelineConfigMother.createPipelineConfig("bar", "dev", "job"), "foo-grp"); Username user = Username.ANONYMOUS; agentConfigService.addAgent(new AgentConfig("uuid-1", "host-1", "192.168.1.2"), user); agentConfigService.addAgent(new AgentConfig("uuid-2", "host-2", "192.168.1.3"), user); uat.addPipeline(new CaseInsensitiveString("foo")); uat.addAgent("uuid-2"); uat.addEnvironmentVariable("env-one", "ONE"); uat.addEnvironmentVariable("env-two", "TWO"); goConfigService.addEnvironment(new BasicEnvironmentConfig(new CaseInsensitiveString("dev"))); goConfigService.addEnvironment(new BasicEnvironmentConfig(new CaseInsensitiveString("qa"))); goConfigService.addEnvironment(uat); goConfigService.addEnvironment( new BasicEnvironmentConfig(new CaseInsensitiveString("acceptance"))); goConfigService.addEnvironment( new BasicEnvironmentConfig(new CaseInsensitiveString("function_testing"))); EnvironmentConfig newUat = new BasicEnvironmentConfig(new CaseInsensitiveString("prod")); newUat.addPipeline(new CaseInsensitiveString("bar")); newUat.addAgent("uuid-1"); newUat.addEnvironmentVariable("env-three", "THREE"); HttpLocalizedOperationResult result = service.updateEnvironment( "uat", newUat, new Username(new CaseInsensitiveString("foo")), goConfigDao.md5OfConfigFile()); EnvironmentConfig updatedEnv = service.named("prod"); assertThat(updatedEnv.name(), is(new CaseInsensitiveString("prod"))); assertThat(updatedEnv.getAgents().getUuids(), is(Arrays.asList("uuid-1"))); assertThat(updatedEnv.getPipelineNames(), is(Arrays.asList(new CaseInsensitiveString("bar")))); EnvironmentVariablesConfig updatedVariables = new EnvironmentVariablesConfig(); updatedVariables.add("env-three", "THREE"); assertThat(updatedEnv.getVariables(), is(updatedVariables)); EnvironmentsConfig currentEnvironments = goConfigService.getCurrentConfig().getEnvironments(); assertThat(currentEnvironments.indexOf(updatedEnv), is(2)); assertThat(currentEnvironments.size(), is(5)); }
@Test public void shouldReturnErrorMessageIfConfigFileChangesBeforePostBuildAsPartialXml() throws Exception { String md5 = goConfigDao.md5OfConfigFile(); configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String newXml = "<job name=\"build3\" />"; ModelAndView mav = controller.postBuildAsXmlPartial("pipeline", "stage", 0, newXml, md5, response); assertThat(response.getStatus(), is(SC_CONFLICT)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map json = (Map) mav.getModel().get("json"); new JsonTester(json) .shouldContain( "{ 'result' : '" + ConfigFileHasChangedException.CONFIG_CHANGED_PLEASE_REFRESH + "'," + " 'originalContent' : '" + newXml + "' }"); }
@Test public void shouldReturnErrorMessageWhenPostOfJobContainsDotForExecWorkingDir() throws Exception { configHelper.addPipeline("pipeline", "stage", "build1", "build2"); String badXml = "<job name=\"build3\" >" + "<tasks>" + "<exec command=\"ant\" workingdir=\".\"/>" + "</tasks>" + "</job>"; String md5 = goConfigDao.md5OfConfigFile(); ModelAndView mav = controller.postBuildAsXmlPartial("pipeline", "stage", 0, badXml, md5, response); assertThat(response.getStatus(), is(SC_CONFLICT)); assertThat(response.getContentType(), is(RESPONSE_CHARSET_JSON)); Map json = (Map) mav.getModel().get("json"); JsonValue jsonValue = JsonUtils.from(json); assertThat(unescapeJavaScript(jsonValue.getString("originalContent")), is(badXml)); assertThat( unescapeJavaScript(jsonValue.getString("result")), containsString("File path is invalid")); }
@Test public void shouldReturnTheCorrectLocalizedMessageWhenUserDoesNotHavePermissionToUpdate() throws IOException { configHelper.addEnvironments("foo"); configHelper.turnOnSecurity(); configHelper.addAdmins("super_hero"); HttpLocalizedOperationResult result = service.updateEnvironment( "foo", env( "foo-env", new ArrayList<String>(), new ArrayList<Map<String, String>>(), new ArrayList<String>()), new Username(new CaseInsensitiveString("evil_hacker")), goConfigDao.md5OfConfigFile()); assertThat( result.message(localizer), is( "Failed to update environment 'foo'. User 'evil_hacker' does not have permission to update environments")); }
@Test public void shouldGetPipelineAsPartialXml() throws Exception { // get the pipeline XML configHelper.addPipeline("pipeline", "dev", "linux", "windows"); groupName = BasicPipelineConfigs.DEFAULT_GROUP; controller.getPipelineAsXmlPartial(0, groupName, null, response); String xml = response.getContentAsString(); assertThat(xml, containsString("pass")); // save the pipeline XML MockHttpServletResponse postResponse = new MockHttpServletResponse(); String modifiedXml = xml.replace("pass", "secret"); controller.postPipelineAsXmlPartial( 0, groupName, modifiedXml, goConfigDao.md5OfConfigFile(), postResponse); // get the pipeline XML again MockHttpServletResponse getResponse = new MockHttpServletResponse(); controller.getPipelineAsXmlPartial(0, groupName, null, getResponse); assertThat(getResponse.getContentAsString(), containsString("secret")); assertThat(getResponse.getContentAsString(), is(modifiedXml)); }
@Test public void shouldGetTemplateAsPartialXmlOnlyIfUserHasAdminRights() throws Exception { // get the pipeline XML configHelper.addPipeline("pipeline", "dev", "linux", "windows"); configHelper.addTemplate("new-template", "dev"); controller.getPipelineAsXmlPartial( 0, TemplatesConfig.PIPELINE_TEMPLATES_FAKE_GROUP_NAME, null, response); String xml = response.getContentAsString(); assertThat(xml, containsString("new-template")); // save the pipeline XML MockHttpServletResponse postResponse = new MockHttpServletResponse(); String modifiedXml = xml.replace("new-template", "new-name-for-template"); controller.postPipelineAsXmlPartial( 0, TemplatesConfig.PIPELINE_TEMPLATES_FAKE_GROUP_NAME, modifiedXml, goConfigDao.md5OfConfigFile(), postResponse); // get the pipeline XML again MockHttpServletResponse getResponse = new MockHttpServletResponse(); controller.getPipelineAsXmlPartial( 0, TemplatesConfig.PIPELINE_TEMPLATES_FAKE_GROUP_NAME, null, getResponse); assertThat(getResponse.getContentAsString(), containsString("new-name-for-template")); assertThat(getResponse.getContentAsString(), is(modifiedXml)); setCurrentUser("user"); MockHttpServletResponse nonAdminResponse = new MockHttpServletResponse(); controller.getPipelineAsXmlPartial( 0, TemplatesConfig.PIPELINE_TEMPLATES_FAKE_GROUP_NAME, null, nonAdminResponse); assertThat(nonAdminResponse.getStatus(), is(SC_UNAUTHORIZED)); assertThat( nonAdminResponse.getContentAsString(), is("User 'user' does not have permission to administer pipeline templates")); }
public String configFileMd5() { return goConfigDao.md5OfConfigFile(); }