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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-57116] Fix empty yamls introduced on upgrade to 1.15.1 #462

Merged
merged 2 commits into from
May 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<java.level>8</java.level>
<jenkins.version>2.138.4</jenkins.version>
<no-test-jar>false</no-test-jar>
<surefire.rerunFailingTestsCount>1</surefire.rerunFailingTestsCount>
<surefire.rerunFailingTestsCount>0</surefire.rerunFailingTestsCount>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlossg was there a flaky test we were using the rerun option for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there have been some flaky tests in the past, but I'd rather avoid rerunning and fix them, and we have 2 different builds happening

<pipeline-model-definition.version>1.3.7</pipeline-model-definition.version>
</properties>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;

import org.apache.commons.lang.StringUtils;
import org.csanchez.jenkins.plugins.kubernetes.model.TemplateEnvVar;
import org.csanchez.jenkins.plugins.kubernetes.pod.retention.PodRetention;
Expand All @@ -27,6 +24,9 @@
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;

import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractDescribableImpl;
Expand Down Expand Up @@ -709,9 +709,15 @@ protected Object readResolve() {
yaml = null;
}

// JENKINS-57116 remove empty items from yamls
if (!yamls.isEmpty() && StringUtils.isBlank(yamls.get(0))) {
setYamls(yamls);
}

if (showRawYaml == null) {
showRawYaml = Boolean.TRUE;
}

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import static org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -58,6 +60,7 @@
import io.fabric8.kubernetes.api.model.VolumeMount;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientException;

public class PodTemplateUtils {

Expand Down Expand Up @@ -505,9 +508,19 @@ public static String substitute(String s, Map<String, String> properties, String
}

public static Pod parseFromYaml(String yaml) {
String s = yaml;
try (KubernetesClient client = new DefaultKubernetesClient()) {
Pod podFromYaml = client.pods().load(new ByteArrayInputStream((yaml == null ? "" : yaml).getBytes(UTF_8)))
.get();
// JENKINS-57116
if (StringUtils.isBlank(s)) {
LOGGER.log(Level.WARNING, "[JENKINS-57116] Trying to parse invalid yaml: \"{0}\"", yaml);
s = "{}";
}
Pod podFromYaml;
try (InputStream is = new ByteArrayInputStream(s.getBytes(UTF_8))) {
podFromYaml = client.pods().load(is).get();
} catch (IOException | KubernetesClientException e) {
throw new RuntimeException(String.format("Failed to parse yaml: \"%s\"", yaml), e);
}
LOGGER.log(Level.FINEST, "Parsed pod template from yaml: {0}", podFromYaml);
// yaml can be just a fragment, avoid NPEs
if (podFromYaml.getMetadata() == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.csanchez.jenkins.plugins.kubernetes.model.KeyValueEnvVar;
Expand All @@ -40,6 +41,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;

Expand Down Expand Up @@ -69,11 +71,21 @@ public class KubernetesTest {

@Before
public void before() throws Exception {
r.configRoundtrip();
cloud = r.jenkins.clouds.get(KubernetesCloud.class);
assertNotNull(cloud);
}

@Test
@LocalData()
@Issue("JENKINS-57116")
public void upgradeFrom_1_15_1() throws Exception {
List<PodTemplate> templates = cloud.getTemplates();
assertPodTemplates(templates);
PodTemplate template = templates.get(0);
assertEquals(Collections.emptyList(), template.getYamls());
assertNull(template.getYaml());
}

@Test
@LocalData()
public void upgradeFrom_1_10() throws Exception {
Expand All @@ -84,6 +96,8 @@ public void upgradeFrom_1_10() throws Exception {
assertEquals(new Default(), template.getPodRetention());
assertEquals(cloud.DEFAULT_WAIT_FOR_POD_SEC, cloud.getWaitForPodSec());
assertTrue(template.isShowRawYaml());
assertEquals(Collections.emptyList(), template.getYamls());
assertNull(template.getYaml());
}

@Test
Expand All @@ -106,8 +120,10 @@ public void upgradeFrom_1_1() throws Exception {
public void upgradeFrom_0_12() throws Exception {
List<PodTemplate> templates = cloud.getTemplates();
assertPodTemplates(templates);
PodTemplate template = templates.get(0);
assertEquals(Arrays.asList(new KeyValueEnvVar("pod_a_key", "pod_a_value"),
new KeyValueEnvVar("pod_b_key", "pod_b_value")), templates.get(0).getEnvVars());
new KeyValueEnvVar("pod_b_key", "pod_b_value")), template.getEnvVars());
assertEquals(Collections.emptyList(), template.getYamls());
assertEquals(cloud.DEFAULT_WAIT_FOR_POD_SEC, cloud.getWaitForPodSec());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.csanchez.jenkins.plugins.kubernetes.model.SecretEnvVar;
import org.csanchez.jenkins.plugins.kubernetes.volumes.HostPathVolume;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;

import com.google.common.collect.ImmutableMap;

Expand All @@ -60,6 +61,7 @@
import io.fabric8.kubernetes.api.model.Toleration;
import io.fabric8.kubernetes.api.model.VolumeMount;
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
import io.fabric8.kubernetes.client.KubernetesClientException;

public class PodTemplateUtilsTest {

Expand Down Expand Up @@ -689,4 +691,12 @@ public void shouldCombineAllToolLocations() {
assertThat(result.getNodeProperties(), hasItems(nodeProperties1.get(0),nodeProperties2.get(0)));

}

@Test
@Issue("JENKINS-57116")
public void testParseYaml() {
PodTemplateUtils.parseFromYaml("{}");
PodTemplateUtils.parseFromYaml(null);
PodTemplateUtils.parseFromYaml("");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?xml version='1.1' encoding='UTF-8'?>
<hudson>
<disabledAdministrativeMonitors/>
<version>2.138.4</version>
<installStateName>DEVELOPMENT</installStateName>
<numExecutors>2</numExecutors>
<mode>NORMAL</mode>
<useSecurity>true</useSecurity>
<authorizationStrategy class="hudson.security.AuthorizationStrategy$Unsecured"/>
<securityRealm class="hudson.security.SecurityRealm$None"/>
<disableRememberMe>false</disableRememberMe>
<projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
<workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULLNAME}</workspaceDir>
<buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
<jdks/>
<viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
<myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
<clouds>
<org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud plugin="[email protected]">
<name>kubernetes</name>
<defaultsProviderTemplate></defaultsProviderTemplate>
<templates>
<org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
<inheritFrom></inheritFrom>
<name>java</name>
<namespace></namespace>
<privileged>false</privileged>
<capOnlyOnAlivePods>false</capOnlyOnAlivePods>
<alwaysPullImage>false</alwaysPullImage>
<instanceCap>2147483647</instanceCap>
<slaveConnectTimeout>100</slaveConnectTimeout>
<idleMinutes>0</idleMinutes>
<activeDeadlineSeconds>0</activeDeadlineSeconds>
<label>java</label>
<nodeSelector></nodeSelector>
<nodeUsageMode>NORMAL</nodeUsageMode>
<customWorkspaceVolumeEnabled>false</customWorkspaceVolumeEnabled>
<workspaceVolume class="org.csanchez.jenkins.plugins.kubernetes.volumes.workspace.EmptyDirWorkspaceVolume">
<memory>false</memory>
</workspaceVolume>
<volumes>
<org.csanchez.jenkins.plugins.kubernetes.volumes.EmptyDirVolume>
<mountPath>/mnt</mountPath>
<memory>false</memory>
</org.csanchez.jenkins.plugins.kubernetes.volumes.EmptyDirVolume>
<org.csanchez.jenkins.plugins.kubernetes.volumes.HostPathVolume>
<mountPath>/host</mountPath>
<hostPath>/mnt/host</hostPath>
</org.csanchez.jenkins.plugins.kubernetes.volumes.HostPathVolume>
</volumes>
<containers>
<org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
<name>jnlp</name>
<image>jenkins/jnlp-slave</image>
<privileged>false</privileged>
<alwaysPullImage>false</alwaysPullImage>
<workingDir>/home/jenkins</workingDir>
<command></command>
<args>${computer.jnlpmac} ${computer.name}</args>
<ttyEnabled>false</ttyEnabled>
<resourceRequestCpu>500m</resourceRequestCpu>
<resourceRequestMemory>250Mi</resourceRequestMemory>
<resourceLimitCpu>500m</resourceLimitCpu>
<resourceLimitMemory>250Mi</resourceLimitMemory>
<envVars>
<org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<key>a</key>
<value>b</value>
</org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<key>c</key>
<value>d</value>
</org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
</envVars>
<ports/>
<livenessProbe>
<execArgs></execArgs>
<timeoutSeconds>0</timeoutSeconds>
<initialDelaySeconds>0</initialDelaySeconds>
<failureThreshold>0</failureThreshold>
<periodSeconds>0</periodSeconds>
<successThreshold>0</successThreshold>
</livenessProbe>
</org.csanchez.jenkins.plugins.kubernetes.ContainerTemplate>
</containers>
<envVars>
<org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<key>a</key>
<value>b</value>
</org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
<key>c</key>
<value>d</value>
</org.csanchez.jenkins.plugins.kubernetes.PodEnvVar>
</envVars>
<annotations>
<org.csanchez.jenkins.plugins.kubernetes.PodAnnotation>
<key>aa</key>
<value>bb</value>
</org.csanchez.jenkins.plugins.kubernetes.PodAnnotation>
</annotations>
<imagePullSecrets>
<org.csanchez.jenkins.plugins.kubernetes.PodImagePullSecret>
<name></name>
</org.csanchez.jenkins.plugins.kubernetes.PodImagePullSecret>
</imagePullSecrets>
<yamls>
<string></string>
</yamls>
<podRetention class="org.csanchez.jenkins.plugins.kubernetes.pod.retention.Default"/>
</org.csanchez.jenkins.plugins.kubernetes.PodTemplate>
</templates>
<serverUrl>https://192.168.64.1</serverUrl>
<skipTlsVerify>true</skipTlsVerify>
<addMasterProxyEnvVars>false</addMasterProxyEnvVars>
<capOnlyOnAlivePods>false</capOnlyOnAlivePods>
<namespace>default</namespace>
<containerCap>10</containerCap>
<retentionTimeout>5</retentionTimeout>
<connectTimeout>0</connectTimeout>
<readTimeout>0</readTimeout>
<usageRestricted>false</usageRestricted>
<maxRequestsPerHost>32</maxRequestsPerHost>
<waitForPodSec>600</waitForPodSec>
<podRetention class="org.csanchez.jenkins.plugins.kubernetes.pod.retention.Never"/>
</org.csanchez.jenkins.plugins.kubernetes.KubernetesCloud>
</clouds>
<quietPeriod>5</quietPeriod>
<scmCheckoutRetryCount>0</scmCheckoutRetryCount>
<views>
<hudson.model.AllView>
<owner class="hudson" reference="../../.."/>
<name>all</name>
<filterExecutors>false</filterExecutors>
<filterQueue>false</filterQueue>
<properties class="hudson.model.View$PropertyList"/>
</hudson.model.AllView>
</views>
<primaryView>all</primaryView>
<slaveAgentPort>0</slaveAgentPort>
<label></label>
<nodeProperties/>
<globalNodeProperties/>
</hudson>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version='1.0' encoding='UTF-8'?>
<com.cloudbees.plugins.credentials.SystemCredentialsProvider plugin="[email protected]">
<domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash">
<entry>
<com.cloudbees.plugins.credentials.domains.Domain>
<specifications/>
</com.cloudbees.plugins.credentials.domains.Domain>
<java.util.concurrent.CopyOnWriteArrayList>
<org.csanchez.jenkins.plugins.kubernetes.OpenShiftBearerTokenCredentialImpl plugin="[email protected]">
<scope>GLOBAL</scope>
<id>token</id>
<description></description>
<username>myusername</username>
<password>TBRF5XYf8ZzxjIllyloGBQ==</password>
</org.csanchez.jenkins.plugins.kubernetes.OpenShiftBearerTokenCredentialImpl>
<org.csanchez.jenkins.plugins.kubernetes.ServiceAccountCredential plugin="[email protected]">
<scope>GLOBAL</scope>
<id>kubernetes-service-account</id>
<description></description>
</org.csanchez.jenkins.plugins.kubernetes.ServiceAccountCredential>
<org.csanchez.jenkins.plugins.kubernetes.OpenShiftTokenCredentialImpl plugin="[email protected]">
<scope>GLOBAL</scope>
<id>openshift-oauth-token</id>
<description></description>
<secret>mytoken</secret>
</org.csanchez.jenkins.plugins.kubernetes.OpenShiftTokenCredentialImpl>
</java.util.concurrent.CopyOnWriteArrayList>
</entry>
</domainCredentialsMap>
</com.cloudbees.plugins.credentials.SystemCredentialsProvider>