Skip to content

Commit 34e05b6

Browse files
Pluggable SCM - get, create, update (#1508)
* Changed Configuration Property Builder to accomodate for all types of plugins. * The endpoints are now accessible by admins and pipeline group admins. * Refactored to extract a superclass.
1 parent 1ef3be4 commit 34e05b6

File tree

27 files changed

+1412
-54
lines changed

27 files changed

+1412
-54
lines changed

common/src/com/thoughtworks/go/serverhealth/HealthStateType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ public static HealthStateType commandRepositoryUpgradeIssue() {
9595
return new HealthStateType("COMMAND_REPOSITORY_UPGRADE_ERROR", 406, HealthStateScope.GLOBAL);
9696
}
9797

98+
public static HealthStateType notFound() {
99+
return new HealthStateType("NOT_FOUND", 404, HealthStateScope.GLOBAL);
100+
}
101+
98102
public boolean equals(Object that) {
99103
if (this == that) { return true; }
100104
if (that == null) {return false; }

config/config-api/src/com/thoughtworks/go/config/builder/ConfigurationPropertyBuilder.java

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,10 @@ public ConfigurationPropertyBuilder() {
1818
this.cipher = new GoCipher();
1919
}
2020

21-
public ConfigurationProperty create(String key, String value, String encryptedValue, Property pluginConfiguration) {
22-
if(pluginConfiguration == null) {
23-
return createInAbsenceOfProperty(key, value, encryptedValue);
24-
}
21+
public ConfigurationProperty create(String key, String value, String encryptedValue, Boolean isSecure) {
2522

2623
ConfigurationProperty configurationProperty = new ConfigurationProperty();
2724
configurationProperty.setConfigurationKey(new ConfigurationKey(key));
28-
Boolean isSecure = pluginConfiguration.getOption(Property.SECURE);
2925

3026
if (isNotBlank(value) && isNotBlank(encryptedValue)) {
3127
configurationProperty.addError("configurationValue", "You may only specify `value` or `encrypted_value`, not both!");
@@ -59,20 +55,6 @@ public ConfigurationProperty create(String key, String value, String encryptedVa
5955
return configurationProperty;
6056
}
6157

62-
private ConfigurationProperty createInAbsenceOfProperty(String key, String value, String encryptedValue) {
63-
ConfigurationProperty configurationProperty = new ConfigurationProperty();
64-
configurationProperty.setConfigurationKey(new ConfigurationKey(key));
65-
66-
if (isNotBlank(encryptedValue)) {
67-
configurationProperty.setEncryptedConfigurationValue(new EncryptedConfigurationValue(encryptedValue));
68-
}
69-
70-
if (isNotBlank(value)) {
71-
configurationProperty.setConfigurationValue(new ConfigurationValue(value));
72-
}
73-
return configurationProperty;
74-
}
75-
7658
private String encrypt(String data) {
7759
try {
7860
return cipher.encrypt(data);

config/config-api/src/com/thoughtworks/go/config/pluggabletask/PluggableTask.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,26 @@ public void addConfigurations(List<ConfigurationProperty> configurations) {
121121
String encryptedValue = property.getEncryptedValue() != null ? property.getEncryptedValue().getValue() : null;
122122
String configValue = property.getConfigurationValue() != null ? property.getConfigValue() : null;
123123

124-
configuration.add(this.builder.create(configKey, configValue, encryptedValue, propertyFor(configKey)));
124+
TaskPreference taskPreference = taskPreference();
125+
if(isValidPluginConfiguration(configKey, taskPreference)) {
126+
configuration.add(this.builder.create(configKey, configValue, encryptedValue, pluginConfigurationFor(configKey, taskPreference).getOption(Property.SECURE)));
127+
} else
128+
{
129+
configuration.add(property);
130+
}
125131
}
126132
}
127133

128-
private Property propertyFor(String key) {
129-
TaskPreference taskPreference = PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId());
130-
if(taskPreference != null) {
131-
return taskPreference.getConfig().get(key);
132-
}
133-
return null;
134+
private boolean isValidPluginConfiguration(String configKey, TaskPreference taskPreference) {
135+
return taskPreference != null && pluginConfigurationFor(configKey, taskPreference) != null;
136+
}
137+
138+
private Property pluginConfigurationFor(String configKey, TaskPreference taskPreference) {
139+
return taskPreference.getConfig().get(configKey);
140+
}
141+
142+
private TaskPreference taskPreference() {
143+
return PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId());
134144
}
135145

136146
@Override
@@ -168,7 +178,7 @@ public String getTypeForDisplay() {
168178
public List<TaskProperty> getPropertiesForDisplay() {
169179
ArrayList<TaskProperty> taskProperties = new ArrayList<>();
170180
if (PluggableTaskConfigStore.store().hasPreferenceFor(pluginConfiguration.getId())) {
171-
TaskPreference preference = PluggableTaskConfigStore.store().preferenceFor(pluginConfiguration.getId());
181+
TaskPreference preference = taskPreference();
172182
List<? extends Property> propertyDefinitions = preference.getConfig().list();
173183
for (Property propertyDefinition : propertyDefinitions) {
174184
ConfigurationProperty configuredProperty = configuration.getProperty(propertyDefinition.getKey());

config/config-api/src/com/thoughtworks/go/domain/scm/SCM.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.gson.annotations.Expose;
2121
import com.google.gson.annotations.SerializedName;
2222
import com.thoughtworks.go.config.*;
23+
import com.thoughtworks.go.config.builder.ConfigurationPropertyBuilder;
2324
import com.thoughtworks.go.config.materials.AbstractMaterialConfig;
2425
import com.thoughtworks.go.config.validation.NameTypeValidator;
2526
import com.thoughtworks.go.domain.ConfigErrors;
@@ -56,6 +57,7 @@ public class SCM implements Serializable, Validatable {
5657
public static final String ERRORS_KEY = "errors";
5758

5859
private ConfigErrors errors = new ConfigErrors();
60+
private ConfigurationPropertyBuilder builder;
5961

6062
@ConfigAttribute(value = "id", allowNull = true)
6163
private String id;
@@ -77,6 +79,7 @@ public class SCM implements Serializable, Validatable {
7779
private Configuration configuration = new Configuration();
7880

7981
public SCM() {
82+
this.builder = new ConfigurationPropertyBuilder();
8083
}
8184

8285
public SCM(String id, PluginConfiguration pluginConfiguration, Configuration configuration) {
@@ -85,6 +88,7 @@ public SCM(String id, PluginConfiguration pluginConfiguration, Configuration con
8588
this.configuration = configuration;
8689
}
8790

91+
8892
public String getId() {
8993
return id;
9094
}
@@ -130,6 +134,31 @@ public void setConfiguration(Configuration configuration) {
130134
this.configuration = configuration;
131135
}
132136

137+
public void addConfigurations(List<ConfigurationProperty> configurations) {
138+
for (ConfigurationProperty property : configurations) {
139+
String configKey = property.getConfigurationKey() != null ? property.getConfigKeyName() : null;
140+
String encryptedValue = property.getEncryptedValue() != null ? property.getEncryptedValue().getValue() : null;
141+
String configValue = property.getConfigurationValue() != null ? property.getConfigValue() : null;
142+
143+
SCMConfigurations scmConfigurations = SCMMetadataStore.getInstance().getConfigurationMetadata(getPluginId());
144+
if (isValidPluginConfiguration(configKey, scmConfigurations)) {
145+
configuration.add(this.builder.create(configKey, configValue, encryptedValue, scmConfigurationFor(configKey, scmConfigurations).getOption(SCMConfiguration.SECURE)));
146+
}
147+
else {
148+
configuration.add(property);
149+
}
150+
151+
}
152+
}
153+
154+
private boolean isValidPluginConfiguration(String configKey, SCMConfigurations scmConfigurations) {
155+
return doesPluginExist() && scmConfigurationFor(configKey, scmConfigurations) != null;
156+
}
157+
158+
private SCMConfiguration scmConfigurationFor(String configKey, SCMConfigurations scmConfigurations) {
159+
return scmConfigurations.get(configKey);
160+
}
161+
133162
@Override
134163
public boolean equals(Object o) {
135164
if (this == o) {
@@ -173,6 +202,7 @@ public void validate(ValidationContext validationContext) {
173202
} else if (new NameTypeValidator().isNameInvalid(name)) {
174203
errors().add(NAME, NameTypeValidator.errorMessage("SCM", name));
175204
}
205+
configuration.validateTree();
176206
configuration.validateUniqueness(String.format("SCM '%s'", name));
177207
}
178208

@@ -296,6 +326,10 @@ public void clearEmptyConfigurations() {
296326
configuration.clearEmptyConfigurations();
297327
}
298328

329+
public List<ConfigErrors> getAllErrors() {
330+
return ErrorCollector.getAllErrors(this);
331+
}
332+
299333
@PostConstruct
300334
public void ensureIdExists() {
301335
if (StringUtil.isBlank(getId())) {

config/config-api/test/com/thoughtworks/go/config/builder/ConfigurationPropertyBuilderTest.java

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public void shouldCreateConfigurationPropertyWithEncyrptedValueForSecureProperty
1515
Property key = new Property("key");
1616
key.with(Property.SECURE, true);
1717

18-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, "enc_value", key);
18+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, "enc_value", true);
1919

2020
assertThat(property.getConfigKeyName(), is("key"));
2121
assertThat(property.getEncryptedValue().getValue(), is("enc_value"));
@@ -27,7 +27,7 @@ public void shouldCreateWithEncyrptedValueForOnlyPlainTextInputForSecureProperty
2727
Property key = new Property("key");
2828
key.with(Property.SECURE, true);
2929

30-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", null, key);
30+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", null, true);
3131

3232
assertThat(property.getConfigKeyName(), is("key"));
3333
assertThat(property.getEncryptedValue().getValue(), is(new GoCipher().encrypt("value")));
@@ -39,7 +39,7 @@ public void shouldCreatePropertyInAbsenceOfPlainAndEncryptedTextInputForSecurePr
3939
Property key = new Property("key");
4040
key.with(Property.SECURE, true);
4141

42-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, null, key);
42+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, null, true);
4343

4444
assertThat(property.getConfigKeyName(), is("key"));
4545
assertNull(property.getEncryptedValue());
@@ -51,7 +51,7 @@ public void shouldCreateWithErrorsIfBothPlainAndEncryptedTextInputAreSpecifiedFo
5151
Property key = new Property("key");
5252
key.with(Property.SECURE, true);
5353

54-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", "enc_value", key);
54+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", "enc_value", true);
5555

5656
assertThat(property.errors().get("configurationValue").get(0), is("You may only specify `value` or `encrypted_value`, not both!"));
5757
assertThat(property.errors().get("encryptedValue").get(0), is("You may only specify `value` or `encrypted_value`, not both!"));
@@ -64,7 +64,7 @@ public void shouldCreateWithErrorsIfBothPlainAndEncryptedTextInputAreSpecifiedFo
6464
Property key = new Property("key");
6565
key.with(Property.SECURE, false);
6666

67-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", "enc_value", key);
67+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", "enc_value", false);
6868

6969
assertThat(property.errors().get("configurationValue").get(0), is("You may only specify `value` or `encrypted_value`, not both!"));
7070
assertThat(property.errors().get("encryptedValue").get(0), is("You may only specify `value` or `encrypted_value`, not both!"));
@@ -77,7 +77,7 @@ public void shouldCreateWithErrorsInPresenceOfEncryptedTextInputForUnSecuredProp
7777
Property key = new Property("key");
7878
key.with(Property.SECURE, false);
7979

80-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, "enc_value", key);
80+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", null, "enc_value", false);
8181

8282
assertThat(property.errors().get("encryptedValue").get(0), is("encrypted_value cannot be specified to a unsecured property."));
8383
assertThat(property.getEncryptedValue().getValue(), is("enc_value"));
@@ -88,18 +88,9 @@ public void shouldCreateWithValueForAUnsecuredProperty() {
8888
Property key = new Property("key");
8989
key.with(Property.SECURE, false);
9090

91-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", null, key);
91+
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", null, false);
9292

9393
assertThat(property.getConfigurationValue().getValue(), is("value"));
9494
assertNull(property.getEncryptedValue());
9595
}
96-
97-
@Test
98-
public void shouldCreateInAbsenceOfProperty() {
99-
ConfigurationProperty property = new ConfigurationPropertyBuilder().create("key", "value", "enc_value", null);
100-
101-
assertThat(property.getConfigurationValue().getValue(), is("value"));
102-
assertThat(property.getEncryptedValue().getValue(), is("enc_value"));
103-
}
104-
10596
}

config/config-api/test/com/thoughtworks/go/config/pluggabletask/PluggableTaskTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.thoughtworks.go.domain.packagerepository.ConfigurationPropertyMother;
2626
import com.thoughtworks.go.plugin.access.pluggabletask.PluggableTaskConfigStore;
2727
import com.thoughtworks.go.plugin.access.pluggabletask.TaskPreference;
28+
import com.thoughtworks.go.plugin.api.config.Option;
2829
import com.thoughtworks.go.plugin.api.config.Property;
2930
import com.thoughtworks.go.plugin.api.response.validation.ValidationResult;
3031
import com.thoughtworks.go.plugin.api.task.Task;
@@ -294,6 +295,8 @@ public void shouldAddConfigurationProperties() {
294295
TaskConfig taskConfig = new TaskConfig();
295296
Configuration configuration = new Configuration();
296297
ConfigurationPropertyBuilder builder = mock(ConfigurationPropertyBuilder.class);
298+
Property property = new Property("key");
299+
property.with(Property.SECURE, false);
297300

298301
PluggableTaskConfigStore.store().setPreferenceFor(pluginConfiguration.getId(), taskPreference);
299302
TaskConfigProperty taskConfigProperty = taskConfig.addProperty("key");
@@ -304,8 +307,7 @@ public void shouldAddConfigurationProperties() {
304307
pluggableTask.addConfigurations(configurationProperties);
305308

306309
assertThat(configuration.size(), is(2));
307-
verify(builder).create("key", "value", "encValue", taskConfigProperty);
308-
verify(builder).create(null, null, null, null);
310+
verify(builder).create("key", "value", "encValue", false);
309311
}
310312

311313
@Test
@@ -320,7 +322,6 @@ public void shouldAddConfigurationPropertiesForAInvalidPlugin() {
320322
pluggableTask.addConfigurations(configurationProperties);
321323

322324
assertThat(configuration.size(), is(1));
323-
verify(builder).create("key", "value", "encValue", null);
324325
}
325326

326327
@Test

config/config-api/test/com/thoughtworks/go/domain/scm/SCMTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,19 @@ public void shouldGenerateIdIfNotAssigned() {
385385
assertThat(scm.getId(), is("id"));
386386
}
387387

388+
@Test
389+
public void shouldAddConfigurationPropertiesForAnyPlugin() {
390+
List<ConfigurationProperty> configurationProperties = Arrays.asList(ConfigurationPropertyMother.create("key", "value", "encValue"));
391+
Configuration configuration = new Configuration();
392+
SCM scm = SCMMother.create("id", "name", "does_not_exist", "1.1", configuration);
393+
394+
assertThat(configuration.size(), is(0));
395+
396+
scm.addConfigurations(configurationProperties);
397+
398+
assertThat(configuration.size(), is(1));
399+
}
400+
388401
@Test
389402
public void shouldGetSCMTypeCorrectly() {
390403
SCM scm = SCMMother.create("scm-id");
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2016 ThoughtWorks, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.thoughtworks.go.config.update;
18+
19+
import com.thoughtworks.go.config.CruiseConfig;
20+
import com.thoughtworks.go.domain.scm.SCM;
21+
import com.thoughtworks.go.domain.scm.SCMs;
22+
import com.thoughtworks.go.server.domain.Username;
23+
import com.thoughtworks.go.server.service.GoConfigService;
24+
import com.thoughtworks.go.server.service.materials.PluggableScmService;
25+
import com.thoughtworks.go.server.service.result.LocalizedOperationResult;
26+
27+
public class CreateSCMConfigCommand extends SCMConfigCommand {
28+
29+
public CreateSCMConfigCommand(SCM globalScmConfig, PluggableScmService pluggableScmService, LocalizedOperationResult result, Username currentUser, GoConfigService goConfigService) {
30+
super(globalScmConfig, pluggableScmService, goConfigService, currentUser, result);
31+
}
32+
33+
@Override
34+
public void update(CruiseConfig modifiedConfig) throws Exception {
35+
SCMs scms = modifiedConfig.getSCMs();
36+
scms.add(globalScmConfig);
37+
modifiedConfig.setSCMs(scms);
38+
}
39+
40+
}

0 commit comments

Comments
 (0)