Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore unknown root elements starting with x- #1379

Merged
merged 9 commits into from
May 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions integrations/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>config-file-provider</artifactId>
<version>3.4.1</version>
<version>3.6.3</version>
jetersen marked this conversation as resolved.
Show resolved Hide resolved
<scope>test</scope>
</dependency>

Expand Down Expand Up @@ -267,7 +267,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>terraform</artifactId>
<version>1.0.9</version>
<version>1.0.10</version>
<scope>test</scope>
<exclusions> <!-- Exclude Banned Dependency -->
<exclusion>
Expand Down
106 changes: 106 additions & 0 deletions integrations/src/test/java/io/jenkins/plugins/casc/AliasesTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package io.jenkins.plugins.casc;

import com.amazonaws.services.ec2.model.InstanceType;
import hudson.model.labels.LabelAtom;
import hudson.plugins.ec2.AMITypeData;
import hudson.plugins.ec2.AmazonEC2Cloud;
import hudson.plugins.ec2.SlaveTemplate;
import hudson.plugins.ec2.UnixData;
import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
import java.util.List;
import jenkins.model.Jenkins;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;
import org.junit.rules.RuleChain;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

public class AliasesTest {

@Rule
public RuleChain chain = RuleChain.outerRule(new EnvironmentVariables()
.set("EC2_PRIVATE_KEY", "ADMIN123"))
.around(new JenkinsConfiguredWithCodeRule());

@Test
@ConfiguredWithCode("alias1.yml")
public void configure_ec2_cloud_with_alias() throws Exception {
final AmazonEC2Cloud ec2Cloud = (AmazonEC2Cloud) Jenkins.get().getCloud("ec2-ec2");
assertNotNull(ec2Cloud);
final List<SlaveTemplate> templates = ec2Cloud.getTemplates();
assertThat(templates, hasSize(2));

SlaveTemplate slaveTemplate = templates.get(0);
assertThat(slaveTemplate.getDisplayName(), containsString("Auto configured EC2 Agent Small"));
assertFalse(slaveTemplate.getAssociatePublicIp());
assertFalse(slaveTemplate.isConnectBySSHProcess());
assertFalse(slaveTemplate.deleteRootOnTermination);
assertFalse(slaveTemplate.ebsOptimized);
assertFalse(slaveTemplate.monitoring);
assertFalse(slaveTemplate.stopOnTerminate);
assertFalse(slaveTemplate.getUseDedicatedTenancy());
assertFalse(slaveTemplate.useEphemeralDevices);
assertThat(slaveTemplate.type, is(InstanceType.T2Small));
assertThat(slaveTemplate.getAmi(), equalTo("ami-0c6bb742864ffa3f3"));
assertThat(slaveTemplate.getLabelString(), containsString("Small"));
assertThat(slaveTemplate.getLabelSet(), is(notNullValue()));
assertThat(slaveTemplate.remoteFS, equalTo("/home/ec2-user"));
assertThat(slaveTemplate.getRemoteAdmin(), equalTo("ec2-user"));
assertThat(slaveTemplate.zone, equalTo("us-east-1"));
assertThat(slaveTemplate.getSecurityGroupString(), equalTo("some-group"));

// fails here without mode specified
assertTrue(ec2Cloud.canProvision(new LabelAtom("Small")));

// Checks that the AMI type is Unix and configured
AMITypeData amiType = slaveTemplate.getAmiType();
assertTrue(amiType.isUnix());
assertTrue(amiType instanceof UnixData);
UnixData unixData = (UnixData) amiType;
assertThat(unixData.getRootCommandPrefix(), equalTo("sudo"));
assertThat(unixData.getSlaveCommandPrefix(), equalTo("sudo -u jenkins"));
assertThat(unixData.getSshPort(), equalTo("61120"));


slaveTemplate = templates.get(1);
assertThat(slaveTemplate.getDisplayName(), containsString("Auto configured EC2 Agent Large"));
assertFalse(slaveTemplate.getAssociatePublicIp());
assertFalse(slaveTemplate.isConnectBySSHProcess());
assertFalse(slaveTemplate.deleteRootOnTermination);
assertFalse(slaveTemplate.ebsOptimized);
assertFalse(slaveTemplate.monitoring);
assertFalse(slaveTemplate.stopOnTerminate);
assertFalse(slaveTemplate.getUseDedicatedTenancy());
assertFalse(slaveTemplate.useEphemeralDevices);
assertThat(slaveTemplate.type, is(InstanceType.T2Xlarge));
assertThat(slaveTemplate.getAmi(), equalTo("ami-0c6bb742864ffa3f3"));
assertThat(slaveTemplate.getLabelString(), containsString("Large"));
assertThat(slaveTemplate.getLabelSet(), is(notNullValue()));
assertThat(slaveTemplate.remoteFS, equalTo("/home/ec2-user"));
assertThat(slaveTemplate.getRemoteAdmin(), equalTo("ec2-user"));
assertThat(slaveTemplate.zone, equalTo("us-east-1"));
assertThat(slaveTemplate.getSecurityGroupString(), equalTo("some-group"));

// fails here without mode specified
assertTrue(ec2Cloud.canProvision(new LabelAtom("Large")));

// Checks that the AMI type is Unix and configured
amiType = slaveTemplate.getAmiType();
assertTrue(amiType.isUnix());
assertTrue(amiType instanceof UnixData);
unixData = (UnixData) amiType;
assertThat(unixData.getRootCommandPrefix(), equalTo("sudo"));
assertThat(unixData.getSlaveCommandPrefix(), equalTo("sudo -u jenkins"));
assertThat(unixData.getSshPort(), equalTo("61120"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
x-ec2_anchor: &ec2_anchor
associatePublicIp: false
connectBySSHProcess: false
connectionStrategy: PRIVATE_IP
deleteRootOnTermination: false
ebsOptimized: false
idleTerminationMinutes: "10"
maxTotalUses: -1
monitoring: false
numExecutors: 1
stopOnTerminate: false
useDedicatedTenancy: false
useEphemeralDevices: false
zone: "us-east-1"
ami: "ami-0c6bb742864ffa3f3"
securityGroups: "some-group"
remoteFS: "/home/ec2-user"
remoteAdmin: "ec2-user"
mode: "NORMAL"
amiType:
unixData:
rootCommandPrefix: "sudo"
slaveCommandPrefix: "sudo -u jenkins"
sshPort: "61120"

jenkins:
clouds:
- amazonEC2:
cloudName: "ec2"
instanceCapStr: 20
# this shouldn't be needed, since without explicit creds this should already be used
# but let's be explicit to avoid issues.
useInstanceProfileForCredentials: true
# Reminder: the following key has multiple lines
privateKey: "${EC2_PRIVATE_KEY}"
noDelayProvisioning: true
region: "eu-central-1"
templates:
- description: "Auto configured EC2 Agent Small"
type: "T2Small"
labelString: "Small"
<<: *ec2_anchor
- description: "Auto configured EC2 Agent Large"
type: "T2Xlarge"
labelString: "Large"
<<: *ec2_anchor
Original file line number Diff line number Diff line change
Expand Up @@ -712,11 +712,24 @@ private static void invokeWith(Mapping entries, ConfiguratorOperation function)
}

if (!entries.isEmpty()) {
final Map.Entry<String, CNode> next = entries.entrySet().iterator().next();
throw new ConfiguratorException(format("No configurator for root element <%s>", next.getKey()));
List<String> unknownKeys = new ArrayList<>();
entries.entrySet().iterator().forEachRemaining(next -> {
String key = next.getKey();
if (ignoreAliasEntry(key)) {
unknownKeys.add(key);
}
});

if (!unknownKeys.isEmpty()) {
throw new ConfiguratorException(format("No configurator for the following root elements %s", String.join(", ", unknownKeys)));
}
}
}

static boolean ignoreAliasEntry(String key) {
jetersen marked this conversation as resolved.
Show resolved Hide resolved
return key != null && !key.startsWith("x-");
}

private static void detectVaultPluginMissing() {
PluginManager pluginManager = Jenkins.get().getPluginManager();
Set<String> envKeys = System.getenv().keySet();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.jenkins.plugins.casc;

import org.junit.Test;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class IgnoreAliasEntryTest {

@Test
public void aliasNull() {
assertThat(ConfigurationAsCode.ignoreAliasEntry(null), is(false));
}

@Test
public void aliasIgnoreXAlias() {
assertThat(ConfigurationAsCode.ignoreAliasEntry("x-hello"), is(false));
}

@Test
public void warnOnUnknownKey() {
assertThat(ConfigurationAsCode.ignoreAliasEntry("bob"), is(true));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.jenkins.plugins.casc;

import java.util.Set;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.jvnet.hudson.test.JenkinsRule;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThrows;

public class UnknownRootElementTest {
@Rule
public JenkinsRule j = new JenkinsRule();

@Rule
public ExpectedException expectedException = ExpectedException.none();

@Test
public void oneUnknown() {
assertThrows("No configurator for the following root elements alice",
ConfiguratorException.class,
() -> ConfigurationAsCode.get()
.configure(getClass().getResource("unknown1.yml").toExternalForm()));
}

@Test
public void twoUnknown() {
assertThrows("No configurator for the following root elements bob, alice",
ConfiguratorException.class,
() -> ConfigurationAsCode.get()
.configure(getClass().getResource("unknown2.yml").toExternalForm()));
}

@Test
public void ignoreUnknownAlias() throws Exception {
ConfigurationAsCode.get().configure(getClass().getResource("known.yml").toExternalForm());
assertThat(j.jenkins.getSystemMessage(), is("Configured by Configuration as Code plugin"));
Set<String> agentProtocols = j.jenkins.getAgentProtocols();
assertThat(agentProtocols, hasSize(2));
}
}
9 changes: 9 additions & 0 deletions plugin/src/test/resources/io/jenkins/plugins/casc/known.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
x-alias:
message: &message
systemMessage: "Configured by Configuration as Code plugin"

jenkins:
<<: *message
agentProtocols:
- JNLP4-connect
- Ping
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alice:
hello: echo
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alice:
hello: bob

bob:
hello: alice