feat(cf): Add artifacts for user-defined services
MODIFY
clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverter.java
clouddriver-cloudfoundry/src/main/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverter.java
@@ -77,6 +77,10 @@ public class DeployCloudFoundryServiceAtomicOperationConverter extends AbstractC
}
converted.setUserProvidedServiceAttributes(userProvidedAttrs);
break;
+ case "userProvidedArtifact":
+ converted.setServiceType("userProvided");
+ downloadAndProcessManifest(manifest, credentialsRepository, myMap -> converted.setUserProvidedServiceAttributes(convertUserProvidedServiceManifest(myMap)));
+ break;
}
return converted;
}
@@ -88,9 +92,14 @@ public class DeployCloudFoundryServiceAtomicOperationConverter extends AbstractC
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.convertValue(manifestMap, new TypeReference<ServiceManifest>() {
});
-
+ if (manifest.getService() == null) {
+ throw new IllegalArgumentException("Manifest is missing the service");
+ } else if (manifest.getServiceName() == null) {
+ throw new IllegalArgumentException("Manifest is missing the service name");
+ } else if(manifest.getServicePlan() == null) {
+ throw new IllegalArgumentException("Manifest is missing the service plan");
+ }
DeployCloudFoundryServiceDescription.ServiceAttributes attrs = new DeployCloudFoundryServiceDescription.ServiceAttributes();
-
attrs.setService(manifest.getService());
attrs.setServiceName(manifest.getServiceName());
attrs.setServicePlan(manifest.getServicePlan());
@@ -99,6 +108,25 @@ public class DeployCloudFoundryServiceAtomicOperationConverter extends AbstractC
return attrs;
}
+ @VisibleForTesting
+ DeployCloudFoundryServiceDescription.UserProvidedServiceAttributes convertUserProvidedServiceManifest(Map manifestMap) {
+ UserProvidedServiceManifest manifest = new ObjectMapper()
+ .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .convertValue(manifestMap, new TypeReference<UserProvidedServiceManifest>() {
+ });
+ if (manifest.getServiceName() == null) {
+ throw new IllegalArgumentException("Manifest is missing the service name");
+ }
+ DeployCloudFoundryServiceDescription.UserProvidedServiceAttributes attrs = new DeployCloudFoundryServiceDescription.UserProvidedServiceAttributes();
+ attrs.setServiceName(manifest.getServiceName());
+ attrs.setSyslogDrainUrl(manifest.getSyslogDrainUrl());
+ attrs.setRouteServiceUrl(manifest.getRouteServiceUrl());
+ attrs.setTags(manifest.getTags());
+ attrs.setCredentialsMap(parseParameters(manifest.getCredentialsMap()));
+ return attrs;
+ }
+
private Map<String, Object> parseParameters(String parameterString) {
if (!StringUtils.isBlank(parameterString)) {
try {
@@ -114,13 +142,10 @@ public class DeployCloudFoundryServiceAtomicOperationConverter extends AbstractC
@Data
private static class ServiceManifest {
- @Nullable
private String service;
- @Nullable
private String serviceName;
- @Nullable
private String servicePlan;
@Nullable
@@ -129,4 +154,21 @@ public class DeployCloudFoundryServiceAtomicOperationConverter extends AbstractC
@Nullable
private String parameters;
}
+
+ @Data
+ private static class UserProvidedServiceManifest {
+ private String serviceName;
+
+ @Nullable
+ private String syslogDrainUrl;
+
+ @Nullable
+ private String routeServiceUrl;
+
+ @Nullable
+ private Set<String> tags;
+
+ @Nullable
+ private String credentialsMap;
+ }
}

MODIFY
clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java
clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/deploy/converters/DeployCloudFoundryServiceAtomicOperationConverterTest.java
@@ -108,6 +108,7 @@ class DeployCloudFoundryServiceAtomicOperationConverterTest {
void convertManifestMapToServiceAttributes() {
final Map input = HashMap.of(
"service", "my-service",
+ "service_name", "my-service-name",
"service_plan", "my-service-plan",
"tags", List.of(
"my-tag"
@@ -118,6 +119,7 @@ class DeployCloudFoundryServiceAtomicOperationConverterTest {
assertThat(converter.convertManifest(input)).isEqualToComparingFieldByFieldRecursively(
new DeployCloudFoundryServiceDescription.ServiceAttributes()
.setService("my-service")
+ .setServiceName("my-service-name")
.setServicePlan("my-service-plan")
.setTags(Collections.singleton("my-tag"))
.setParameterMap(HashMap.<String, Object>of(
@@ -126,10 +128,91 @@ class DeployCloudFoundryServiceAtomicOperationConverterTest {
);
}
+ @Test
+ void convertManifestMapToServiceAttributesMissingServiceThrowsException() {
+ final Map input = HashMap.of(
+ "service_name", "my-service-name",
+ "service_plan", "my-service-plan",
+ "tags", List.of(
+ "my-tag"
+ ).asJava(),
+ "parameters", "{\"foo\": \"bar\"}"
+ ).toJavaMap();
+
+ assertThrows(IllegalArgumentException.class, () -> converter.convertManifest(input), "Manifest is missing the service");
+ }
+
+ @Test
+ void convertManifestMapToServiceAttributesMissingServiceNameThrowsException() {
+ final Map input = HashMap.of(
+ "service_name", "my-service-name",
+ "service_plan", "my-service-plan",
+ "tags", List.of(
+ "my-tag"
+ ).asJava(),
+ "parameters", "{\"foo\": \"bar\"}"
+ ).toJavaMap();
+
+ assertThrows(IllegalArgumentException.class, () -> converter.convertManifest(input), "Manifest is missing the service name");
+ }
+
+ @Test
+ void convertManifestMapToServiceAttributesMissingServicePlanThrowsException() {
+ final Map input = HashMap.of(
+ "service", "my-service",
+ "service_name", "my-service-name",
+ "tags", List.of(
+ "my-tag"
+ ).asJava(),
+ "parameters", "{\"foo\": \"bar\"}"
+ ).toJavaMap();
+
+ assertThrows(IllegalArgumentException.class, () -> converter.convertManifest(input), "Manifest is missing the service plan");
+ }
+
+ @Test
+ void convertCupsManifestMapToUserProvidedServiceAttributes() {
+ final Map input = HashMap.of(
+ "service_name", "my-service-name",
+ "syslog_drain_url", "test-syslog-drain-url",
+ "route_service_url", "test-route-service-url",
+ "tags", List.of(
+ "my-tag"
+ ).asJava(),
+ "credentials_map", "{\"foo\": \"bar\"}"
+ ).toJavaMap();
+
+ assertThat(converter.convertUserProvidedServiceManifest(input)).isEqualToComparingFieldByFieldRecursively(
+ new DeployCloudFoundryServiceDescription.UserProvidedServiceAttributes()
+ .setServiceName("my-service-name")
+ .setSyslogDrainUrl("test-syslog-drain-url")
+ .setRouteServiceUrl("test-route-service-url")
+ .setTags(Collections.singleton("my-tag"))
+ .setCredentialsMap(HashMap.<String, Object>of(
+ "foo", "bar"
+ ).toJavaMap())
+ );
+ }
+
+ @Test
+ void convertCupsManifestMapToUserProvidedServiceAttributesMissingServiceNameThrowsException() {
+ final Map input = HashMap.of(
+ "syslog_drain_url", "test-syslog-drain-url",
+ "route_service_url", "test-route-service-url",
+ "tags", List.of(
+ "my-tag"
+ ).asJava(),
+ "credentials_map", "{\"foo\": \"bar\"}"
+ ).toJavaMap();
+
+ assertThrows(IllegalArgumentException.class, () -> converter.convertUserProvidedServiceManifest(input), "Manifest is missing the service name");
+ }
+
@Test
void convertManifestMapToServiceAttributesEmptyParamString() {
final Map input = HashMap.of(
"service", "my-service",
+ "service_name", "my-service-name",
"service_plan", "my-service-plan",
"tags", List.of(
"my-tag"
@@ -140,6 +223,7 @@ class DeployCloudFoundryServiceAtomicOperationConverterTest {
assertThat(converter.convertManifest(input)).isEqualToComparingFieldByFieldRecursively(
new DeployCloudFoundryServiceDescription.ServiceAttributes()
.setService("my-service")
+ .setServiceName("my-service-name")
.setServicePlan("my-service-plan")
.setTags(Collections.singleton("my-tag"))
);

DELETE
clouddriver-cloudfoundry/src/test/java/com/netflix/spinnaker/clouddriver/cloudfoundry/security/CloudFoundryCredentialsTest.java
-/*
- * Copyright 2018 Pivotal, 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.netflix.spinnaker.clouddriver.cloudfoundry.security;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.Test;
-
-class CloudFoundryCredentialsTest {
- @Test
- void serialize() throws JsonProcessingException {
- CloudFoundryCredentials creds = new CloudFoundryCredentials("pws", "some.uri.example.com", "some.uri.example.com", "api.run.pivotal.io", "fakeuser", "fakepasword", "dev");
- new ObjectMapper().writeValueAsString(creds);
- }
-}

feat(cf): Add artifacts for user-defined services (#3343)

Co-Authored-By: Jammy Louie <jlouie@pivotal.io>