diff --git a/clouddriver-core/src/main/java/com/netflix/spinnaker/clouddriver/core/ProjectClustersService.java b/clouddriver-core/src/main/java/com/netflix/spinnaker/clouddriver/core/ProjectClustersService.java index 746778d7639..add627d695b 100644 --- a/clouddriver-core/src/main/java/com/netflix/spinnaker/clouddriver/core/ProjectClustersService.java +++ b/clouddriver-core/src/main/java/com/netflix/spinnaker/clouddriver/core/ProjectClustersService.java @@ -299,7 +299,7 @@ static class ApplicationClusterModel { new OptionalConsumer<>( (DeployedBuild b) -> { b.deployed = Math.max(b.deployed, serverGroup.getCreatedTime()); - List images = getServerGroupBuildInfoImages(imageSummaries); + List images = getServerGroupBuildInfoImages(imageSummaries); if (images != null) { images.forEach( image -> { @@ -376,9 +376,10 @@ static class DeployedBuild { public String job; public String buildNumber; public Long deployed; - public List images; + public List images; - public DeployedBuild(String host, String job, String buildNumber, Long deployed, List images) { + public DeployedBuild( + String host, String job, String buildNumber, Long deployed, List images) { this.host = host; this.job = job; this.buildNumber = buildNumber; @@ -426,7 +427,7 @@ private static JenkinsBuildInfo extractJenkinsBuildInfo( return new JenkinsBuildInfo(buildNumber, host, job); } - private static List getServerGroupBuildInfoImages( + private static List getServerGroupBuildInfoImages( List imageSummaries) { if (imageSummaries.isEmpty()) { return null; @@ -437,7 +438,17 @@ private static List getServerGroupBuildInfoImages( return null; } - return (List) buildInfo.get("images"); + try { + // Some ImageSummary implementations use immutable image collections, so this needs to be + // copied to a mutable one. Notably, KubernetesImageSummary images are immutable. + return new ArrayList<>((List) buildInfo.get("images")); + } catch (ClassCastException e) { + log.warn( + "Expected List for buildInfo images list, but was not. serverGroup={}", + imageSummary.getServerGroupName(), + e); + return new ArrayList<>(); + } } private static class OptionalConsumer implements Consumer> {