/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.domain.packagerepository; import java.util.HashMap; import java.util.Map; import com.thoughtworks.go.config.BasicCruiseConfig; import com.thoughtworks.go.config.ConfigSaveValidationContext; import com.thoughtworks.go.config.helper.ConfigurationHolder; import com.thoughtworks.go.domain.config.PluginConfiguration; import com.thoughtworks.go.domain.config.Configuration; import com.thoughtworks.go.domain.config.ConfigurationKey; import com.thoughtworks.go.domain.config.ConfigurationProperty; import com.thoughtworks.go.domain.config.ConfigurationValue; import com.thoughtworks.go.domain.config.EncryptedConfigurationValue; import com.thoughtworks.go.domain.config.RepositoryMetadataStoreHelper; import com.thoughtworks.go.security.GoCipher; import com.thoughtworks.go.plugin.access.packagematerial.PackageMetadataStore; import com.thoughtworks.go.plugin.access.packagematerial.RepositoryMetadataStore; import com.thoughtworks.go.plugin.access.packagematerial.PackageConfiguration; import com.thoughtworks.go.plugin.access.packagematerial.PackageConfigurations; import org.junit.Before; import org.junit.Test; import static com.thoughtworks.go.domain.packagerepository.ConfigurationPropertyMother.create; import static com.thoughtworks.go.plugin.access.packagematerial.PackageConfiguration.PART_OF_IDENTITY; import static com.thoughtworks.go.plugin.access.packagematerial.PackageConfiguration.SECURE; import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; public class PackageRepositoryTest extends PackageMaterialTestBase { @Before public void setUp() throws Exception { RepositoryMetadataStoreHelper.clear(); } @Test public void shouldCheckEqualityOfPackageRepository() { Configuration configuration = new Configuration(); Packages packages = new Packages(new PackageDefinition()); PackageRepository packageRepository = createPackageRepository("plugin-id", "version", "id", "name", configuration, packages); assertThat(packageRepository, is(createPackageRepository("plugin-id", "version", "id", "name", configuration, packages))); } @Test public void shouldCheckForFieldAssignments() { Configuration configuration = new Configuration(); Packages packages = new Packages(new PackageDefinition()); PackageRepository packageRepository = createPackageRepository("plugin-id", "version", "id", "name", configuration, packages); assertThat(packageRepository.getPluginConfiguration().getId(), is("plugin-id")); assertThat(packageRepository.getPluginConfiguration().getVersion(), is("version")); assertThat(packageRepository.getId(), is("id")); assertThat(packageRepository.getName(), is("name")); } @Test public void shouldSetRepositoryOnAllAssociatedPackages() { Configuration configuration = new Configuration(); PackageDefinition packageDefinition = new PackageDefinition(); PackageRepository packageRepository = createPackageRepository("plugin-id", "version", "id", "name", configuration, new Packages(packageDefinition)); packageRepository.setRepositoryReferenceOnPackages(); assertThat(packageDefinition.getRepository(), is(packageRepository)); } @Test public void shouldOnlyDisplayFieldsWhichAreNonSecureAndPartOfIdentityInGetConfigForDisplayWhenPluginExists() throws Exception { PackageConfigurations repositoryConfiguration = new PackageConfigurations(); repositoryConfiguration.addConfiguration(new PackageConfiguration("key1").with(PART_OF_IDENTITY, true).with(SECURE, false)); repositoryConfiguration.addConfiguration(new PackageConfiguration("key2").with(PART_OF_IDENTITY, false).with(SECURE, false)); repositoryConfiguration.addConfiguration(new PackageConfiguration("key3").with(PART_OF_IDENTITY, true).with(SECURE, true)); repositoryConfiguration.addConfiguration(new PackageConfiguration("key4").with(PART_OF_IDENTITY, false).with(SECURE, true)); repositoryConfiguration.addConfiguration(new PackageConfiguration("key5").with(PART_OF_IDENTITY, true).with(SECURE, false)); RepositoryMetadataStore.getInstance().addMetadataFor("plugin1", repositoryConfiguration); Configuration configuration = new Configuration(create("key1", false, "value1"), create("key2", false, "value2"), create("key3", true, "value3"), create("key4", true, "value4"), create("key5", false, "value5")); PackageRepository repository = PackageRepositoryMother.create("repo1", "repo1-name", "plugin1", "1", configuration); assertThat(repository.getConfigForDisplay(), is("Repository: [key1=value1, key5=value5]")); } @Test public void shouldConvertKeysToLowercaseInGetConfigForDisplay() throws Exception { RepositoryMetadataStore.getInstance().addMetadataFor("some-plugin", new PackageConfigurations()); PackageMetadataStore.getInstance().addMetadataFor("some-plugin", new PackageConfigurations()); Configuration configuration = new Configuration(create("kEY1", false, "vALue1"), create("KEY_MORE_2", false, "VALUE_2"), create("key_3", false, "value3")); PackageRepository repository = PackageRepositoryMother.create("repo1", "repo1-name", "some-plugin", "1", configuration); assertThat(repository.getConfigForDisplay(), is("Repository: [key1=vALue1, key_more_2=VALUE_2, key_3=value3]")); } @Test public void shouldNotDisplayEmptyValuesInGetConfigForDisplay() throws Exception { RepositoryMetadataStore.getInstance().addMetadataFor("some-plugin", new PackageConfigurations()); PackageMetadataStore.getInstance().addMetadataFor("some-plugin", new PackageConfigurations()); Configuration configuration = new Configuration(create("rk1", false, ""), create("rk2", false, "some-non-empty-value"), create("rk3", false, null)); PackageRepository repository = PackageRepositoryMother.create("repo-id", "repo", "some-plugin", "version", configuration); assertThat(repository.getConfigForDisplay(), is("Repository: [rk2=some-non-empty-value]")); } @Test public void shouldDisplayAllNonSecureFieldsInGetConfigForDisplayWhenPluginDoesNotExist() { Configuration configuration = new Configuration(create("key1", false, "value1"), create("key2", true, "value2"), create("key3", false, "value3")); PackageRepository repository = PackageRepositoryMother.create("repo1", "repo1-name", "some-plugin-which-does-not-exist", "1", configuration); assertThat(repository.getConfigForDisplay(), is("WARNING! Plugin missing for Repository: [key1=value1, key3=value3]")); } @Test public void shouldMakeConfigurationSecureBasedOnMetadata() throws Exception { GoCipher goCipher = new GoCipher(); /*secure property is set based on metadata*/ ConfigurationProperty secureProperty = new ConfigurationProperty(new ConfigurationKey("key1"), new ConfigurationValue("value1"), null, goCipher); ConfigurationProperty nonSecureProperty = new ConfigurationProperty(new ConfigurationKey("key2"), new ConfigurationValue("value2"), null, goCipher); PackageDefinition packageDefinition = new PackageDefinition("go", "name", new Configuration(secureProperty, nonSecureProperty)); //meta data of package PackageConfigurations packageConfigurations = new PackageConfigurations(); packageConfigurations.addConfiguration(new PackageConfiguration("key1").with(SECURE, true)); packageConfigurations.addConfiguration(new PackageConfiguration("key2").with(SECURE, false)); PackageMetadataStore.getInstance().addMetadataFor("plugin-id", packageConfigurations); /*secure property is set based on metadata*/ ConfigurationProperty secureRepoProperty = new ConfigurationProperty(new ConfigurationKey("key1"), new ConfigurationValue("value1"), null, goCipher); ConfigurationProperty nonSecureRepoProperty = new ConfigurationProperty(new ConfigurationKey("key2"), new ConfigurationValue("value2"), null, goCipher); PackageRepository packageRepository = createPackageRepository("plugin-id", "version", "id", "name", new Configuration(secureRepoProperty, nonSecureRepoProperty), new Packages(packageDefinition)); //meta data of repo PackageConfigurations repositoryConfiguration = new PackageConfigurations(); repositoryConfiguration.addConfiguration(new PackageConfiguration("key1").with(SECURE, true)); repositoryConfiguration.addConfiguration(new PackageConfiguration("key2").with(SECURE, false)); RepositoryMetadataStore.getInstance().addMetadataFor("plugin-id", repositoryConfiguration); packageRepository.applyPackagePluginMetadata(); //assert package properties assertThat(secureProperty.isSecure(), is(true)); assertThat(secureProperty.getEncryptedConfigurationValue(), is(notNullValue())); assertThat(secureProperty.getEncryptedValue(), is(goCipher.encrypt("value1"))); assertThat(nonSecureProperty.isSecure(), is(false)); assertThat(nonSecureProperty.getValue(), is("value2")); //assert repository properties assertThat(secureRepoProperty.isSecure(), is(true)); assertThat(secureRepoProperty.getEncryptedConfigurationValue(), is(notNullValue())); assertThat(secureRepoProperty.getEncryptedValue(), is(goCipher.encrypt("value1"))); assertThat(nonSecureRepoProperty.isSecure(), is(false)); assertThat(nonSecureRepoProperty.getValue(), is("value2")); } @Test public void shouldNotUpdateSecurePropertyWhenPluginIsMissing() { GoCipher goCipher = new GoCipher(); ConfigurationProperty secureProperty = new ConfigurationProperty(new ConfigurationKey("key1"), null, new EncryptedConfigurationValue("value"), goCipher); ConfigurationProperty nonSecureProperty = new ConfigurationProperty(new ConfigurationKey("key2"), new ConfigurationValue("value2"), null, goCipher); PackageDefinition packageDefinition = new PackageDefinition("go", "name", new Configuration(secureProperty, nonSecureProperty)); ConfigurationProperty nonSecureRepoProperty = new ConfigurationProperty(new ConfigurationKey("key1"), new ConfigurationValue("value1"), null, goCipher); ConfigurationProperty secureRepoProperty = new ConfigurationProperty(new ConfigurationKey("key2"), null, new EncryptedConfigurationValue("value"), goCipher); PackageRepository packageRepository = createPackageRepository("plugin-id", "version", "id", "name", new Configuration(secureRepoProperty, nonSecureRepoProperty), new Packages(packageDefinition)); packageRepository.applyPackagePluginMetadata(); assertThat(secureProperty.getEncryptedConfigurationValue(), is(notNullValue())); assertThat(secureProperty.getConfigurationValue(), is(nullValue())); assertThat(nonSecureProperty.getConfigurationValue(), is(notNullValue())); assertThat(nonSecureProperty.getEncryptedConfigurationValue(), is(nullValue())); assertThat(secureRepoProperty.getEncryptedConfigurationValue(), is(notNullValue())); assertThat(secureRepoProperty.getConfigurationValue(), is(nullValue())); assertThat(nonSecureRepoProperty.getConfigurationValue(), is(notNullValue())); assertThat(nonSecureRepoProperty.getEncryptedConfigurationValue(), is(nullValue())); } @Test public void shouldSetConfigAttributesAsAvailable() throws Exception { //metadata setup PackageConfigurations repositoryConfiguration = new PackageConfigurations(); repositoryConfiguration.add(new PackageConfiguration("url")); repositoryConfiguration.add(new PackageConfiguration("username")); repositoryConfiguration.add(new PackageConfiguration("password").with(SECURE, true)); repositoryConfiguration.add(new PackageConfiguration("secureKeyNotChanged").with(SECURE, true)); RepositoryMetadataStore.getInstance().addMetadataFor("yum", repositoryConfiguration); String name = "go-server"; String repoId = "repo-id"; String pluginId = "yum"; ConfigurationHolder url = new ConfigurationHolder("url", "http://test.com"); ConfigurationHolder username = new ConfigurationHolder("username", "user"); String oldEncryptedValue = "oldEncryptedValue"; ConfigurationHolder password = new ConfigurationHolder("password", "pass", oldEncryptedValue, true, "1"); ConfigurationHolder secureKeyNotChanged = new ConfigurationHolder("secureKeyNotChanged", "pass", oldEncryptedValue, true, "0"); Map attributes = createPackageRepositoryConfiguration(name, pluginId, repoId, url, username, password, secureKeyNotChanged); PackageRepository packageRepository = new PackageRepository(); Packages packages = new Packages(); packageRepository.setPackages(packages); packageRepository.setConfigAttributes(attributes); assertThat(packageRepository.getName(), is(name)); assertThat(packageRepository.getId(), is(repoId)); assertThat(packageRepository.getPluginConfiguration().getId(), is(pluginId)); assertThat(packageRepository.getConfiguration().get(0).getConfigurationKey().getName(), is(url.name)); assertThat(packageRepository.getConfiguration().get(0).getConfigurationValue().getValue(), is(url.value)); assertThat(packageRepository.getConfiguration().get(1).getConfigurationKey().getName(), is(username.name)); assertThat(packageRepository.getConfiguration().get(1).getConfigurationValue().getValue(), is(username.value)); assertThat(packageRepository.getConfiguration().get(2).getConfigurationKey().getName(), is(password.name)); assertThat(packageRepository.getConfiguration().get(2).getEncryptedValue(), is(new GoCipher().encrypt(password.value))); assertThat(packageRepository.getConfiguration().get(2).getConfigurationValue(), is(nullValue())); assertThat(packageRepository.getConfiguration().get(3).getConfigurationKey().getName(), is(secureKeyNotChanged.name)); assertThat(packageRepository.getConfiguration().get(3).getEncryptedValue(), is(oldEncryptedValue)); assertThat(packageRepository.getConfiguration().get(3).getConfigurationValue(), is(nullValue())); assertSame(packageRepository.getPackages(), packages); } @Test public void shouldValidateIfNameIsMissing() { PackageRepository packageRepository = new PackageRepository(); packageRepository.validate(new ConfigSaveValidationContext(new BasicCruiseConfig(), null)); assertThat(packageRepository.errors().getAllOn("name"), is(asList("Please provide name"))); } @Test public void shouldAddPackageDefinitionToRepo() { PackageRepository repository = PackageRepositoryMother.create("repo1"); String existingPackageId = repository.getPackages().get(0).getId(); PackageDefinition pkg = PackageDefinitionMother.create("pkg"); repository.addPackage(pkg); assertThat(repository.getPackages().size(), is(2)); assertThat(repository.getPackages().get(0).getId(), is(existingPackageId)); assertThat(repository.getPackages().get(1).getId(), is(pkg.getId())); } @Test public void shouldFindPackageById() throws Exception { PackageRepository repository = PackageRepositoryMother.create("repo-id2", "repo2", "plugin-id", "1.0", null); PackageDefinition p1 = PackageDefinitionMother.create("id1", "pkg1", null, repository); PackageDefinition p2 = PackageDefinitionMother.create("id2", "pkg2", null, repository); Packages packages = new Packages(p1, p2); repository.setPackages(packages); assertThat(repository.findPackage("id2"), is(p2)); } @Test public void shouldClearConfigurationsWhichAreEmptyAndNoErrors() throws Exception { PackageRepository packageRepository = new PackageRepository(); packageRepository.getConfiguration().add(new ConfigurationProperty(new ConfigurationKey("name-one"), new ConfigurationValue())); packageRepository.getConfiguration().add(new ConfigurationProperty(new ConfigurationKey("name-two"), new EncryptedConfigurationValue())); packageRepository.getConfiguration().add(new ConfigurationProperty(new ConfigurationKey("name-three"), null, new EncryptedConfigurationValue(), null)); ConfigurationProperty configurationProperty = new ConfigurationProperty(new ConfigurationKey("name-four"), null, new EncryptedConfigurationValue(), null); configurationProperty.addErrorAgainstConfigurationValue("error"); packageRepository.getConfiguration().add(configurationProperty); packageRepository.clearEmptyConfigurations(); assertThat(packageRepository.getConfiguration().size(), is(1)); assertThat(packageRepository.getConfiguration().get(0).getConfigurationKey().getName(), is("name-four")); } @Test public void shouldValidateName() throws Exception { PackageRepository packageRepository = new PackageRepository(); packageRepository.setName("some name"); packageRepository.validate(new ConfigSaveValidationContext(null)); assertThat(packageRepository.errors().isEmpty(), is(false)); assertThat(packageRepository.errors().getAllOn(PackageRepository.NAME).get(0), is("Invalid PackageRepository name 'some 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 shouldRemoveGivenPackageFromTheRepository() throws Exception { PackageDefinition packageDefinitionOne = new PackageDefinition("pid1", "pname1", null); PackageDefinition packageDefinitionTwo = new PackageDefinition("pid2", "pname2", null); PackageRepository packageRepository = new PackageRepository(); packageRepository.addPackage(packageDefinitionOne); packageRepository.addPackage(packageDefinitionTwo); packageRepository.removePackage("pid1"); assertThat(packageRepository.getPackages().size(), is(1)); assertThat(packageRepository.getPackages(), hasItems(packageDefinitionTwo)); } @Test public void shouldThrowErrorWhenGivenPackageNotFoundDuringRemove() throws Exception { PackageRepository packageRepository = new PackageRepository(); try { packageRepository.removePackage("invalid"); } catch (RuntimeException e) { assertThat(e.getMessage(), is("Could not find package with id:[invalid]")); } } @Test public void shouldFindPackageDefinitionBasedOnParams() throws Exception { PackageRepository packageRepository = PackageRepositoryMother.create("repo-id1", "packageRepository", "plugin-id", "1.0", null); PackageDefinition packageDefinitionOne = PackageDefinitionMother.create("pid1", packageRepository); PackageDefinition packageDefinitionTwo = PackageDefinitionMother.create("pid2", packageRepository); packageRepository.getPackages().addAll(asList(packageDefinitionOne, packageDefinitionTwo)); Map attributes = new HashMap(); attributes.put("packageId", "pid1"); PackageDefinition actualPackageDefinition = packageRepository.findOrCreatePackageDefinition(attributes); assertThat(actualPackageDefinition, is(packageDefinitionOne)); } @Test public void shouldCreatePackageBasedOnParams() throws Exception { PackageRepository packageRepository = PackageRepositoryMother.create("repo-id1", "packageRepository", "plugin-id", "1.0", null); Map packageDefAttr = createPackageDefinitionConfiguration("package_name", "pluginId", new ConfigurationHolder("key1", "value1"), new ConfigurationHolder("key2", "value2")); Map map = new HashMap(); map.put("package_definition", packageDefAttr); PackageDefinition actualPackageDefinition = packageRepository.findOrCreatePackageDefinition(map); assertThat(actualPackageDefinition, is(PackageDefinitionMother.create(null, "package_name", new Configuration(create("key1", false, "value1"), create("key2", false, "value2")), packageRepository))); assertThat(actualPackageDefinition.getRepository(), is(packageRepository)); } @Test public void shouldValidateUniqueNames() { PackageRepository packageRepository = new PackageRepository(); packageRepository.setName("REPO"); HashMap<String, PackageRepository> nameMap = new HashMap<>(); PackageRepository original = new PackageRepository(); original.setName("repo"); nameMap.put("repo", original); packageRepository.validateNameUniqueness(nameMap); assertThat( packageRepository.errors().getAllOn(PackageRepository.NAME).contains("You have defined multiple repositories called 'REPO'. Repository names are case-insensitive and must be unique."), is(true)); assertThat(original.errors().getAllOn(PackageRepository.NAME).contains("You have defined multiple repositories called 'REPO'. Repository names are case-insensitive and must be unique."), is(true)); } @Test public void shouldValidateUniqueKeysInConfiguration() { ConfigurationProperty one = new ConfigurationProperty(new ConfigurationKey("one"), new ConfigurationValue("value1")); ConfigurationProperty duplicate1 = new ConfigurationProperty(new ConfigurationKey("ONE"), new ConfigurationValue("value2")); ConfigurationProperty duplicate2 = new ConfigurationProperty(new ConfigurationKey("ONE"), new ConfigurationValue("value3")); ConfigurationProperty two = new ConfigurationProperty(new ConfigurationKey("two"), new ConfigurationValue()); PackageRepository repository = new PackageRepository(); repository.setConfiguration(new Configuration(one, duplicate1, duplicate2, two)); repository.setName("yum"); repository.validate(null); assertThat(one.errors().isEmpty(), is(false)); assertThat(one.errors().getAllOn(ConfigurationProperty.CONFIGURATION_KEY).contains("Duplicate key 'ONE' found for Repository 'yum'"), is(true)); assertThat(duplicate1.errors().isEmpty(), is(false)); assertThat(one.errors().getAllOn(ConfigurationProperty.CONFIGURATION_KEY).contains("Duplicate key 'ONE' found for Repository 'yum'"), is(true)); assertThat(duplicate2.errors().isEmpty(), is(false)); assertThat(one.errors().getAllOn(ConfigurationProperty.CONFIGURATION_KEY).contains("Duplicate key 'ONE' found for Repository 'yum'"), is(true)); assertThat(two.errors().isEmpty(), is(true)); } @Test public void shouldGenerateIdIfNotAssigned(){ PackageRepository packageRepository = new PackageRepository(); packageRepository.ensureIdExists(); assertThat(packageRepository.getId(), is(notNullValue())); packageRepository = new PackageRepository(); packageRepository.setId("id"); packageRepository.ensureIdExists(); assertThat(packageRepository.getId(), is("id")); } private PackageRepository createPackageRepository(String pluginId, String version, String id, String name, Configuration configuration, Packages packages) { PackageRepository packageRepository = new PackageRepository(); packageRepository.setConfiguration(configuration); packageRepository.setPackages(packages); packageRepository.setPluginConfiguration(new PluginConfiguration(pluginId, version)); packageRepository.setId(id); packageRepository.setName(name); return packageRepository; } private Map createPackageRepositoryConfiguration(String name, String pluginId, String repoId, ConfigurationHolder... configurations) { Map attributes = new HashMap(); attributes.put(PackageRepository.NAME, name); attributes.put(PackageRepository.REPO_ID, repoId); HashMap pluginConfiguration = new HashMap(); pluginConfiguration.put(PluginConfiguration.ID, pluginId); attributes.put(PackageRepository.PLUGIN_CONFIGURATION, pluginConfiguration); createPackageConfigurationsFor(attributes, configurations); return attributes; } }