diff:
@@ -28,4 +28,5 @@ public class UpsertLambdaFunctionEventMappingDescription extends AbstractLambdaF
Boolean enabled = false;
String eventSourceArn = null;
String uuid = null;
+ String startingPosition = null;
}

diff:
@@ -82,7 +82,7 @@ public class UpsertLambdaEventSourceAtomicOperation
.withFunctionName(cache.getFunctionArn())
.withBatchSize(description.getBatchsize())
.withEnabled(description.getEnabled())
- .withStartingPosition("LATEST")
+ .withStartingPosition(description.getStartingPosition())
.withEventSourceArn(description.getEventSourceArn());
CreateEventSourceMappingResult result = client.createEventSourceMapping(request);

original_message:
fix(aws/lambda): Parameterize hard-coded startingPosition field for lambda event sources (#4872)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


message:
fix(cache): fix the CacheController
This was missed in

change_type: MODIFY

diff:
@@ -18,7 +18,7 @@ package com.netflix.spinnaker.clouddriver.controllers
import com.netflix.spinnaker.cats.cache.AgentIntrospection
import com.netflix.spinnaker.cats.cache.CacheIntrospectionStore
-import com.netflix.spinnaker.clouddriver.cache.OnDemandAgent
+import com.netflix.spinnaker.clouddriver.cache.OnDemandCacheStatus
import com.netflix.spinnaker.clouddriver.cache.OnDemandCacheUpdater
import com.netflix.spinnaker.clouddriver.cache.OnDemandType
import com.netflix.spinnaker.kork.web.exceptions.NotFoundException
@@ -45,7 +45,7 @@ class CacheController {
}?.handle(onDemandType, cloudProvider, data)
def cacheStatus = onDemandCacheResult?.status
- def httpStatus = (cacheStatus == OnDemandCacheUpdater.OnDemandCacheStatus.PENDING) ? HttpStatus.ACCEPTED : HttpStatus.OK
+ def httpStatus = (cacheStatus == OnDemandCacheStatus.PENDING) ? HttpStatus.ACCEPTED : HttpStatus.OK
return new ResponseEntity(
[

license: Apache License 2.0

repo: spinnaker/clouddriver

original_message:
fix(cache): fix the CacheController (#4881)

This was missed in #4865

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


diff:
package com.netflix.spinnaker.clouddriver.aws.security
-interface AmazonAccountsSynchronizer {
+import com.netflix.spinnaker.cats.module.CatsModule
+import com.netflix.spinnaker.clouddriver.aws.security.config.CredentialsConfig
+import com.netflix.spinnaker.clouddriver.aws.security.config.CredentialsLoader
+import com.netflix.spinnaker.clouddriver.security.AccountCredentialsRepository
- List<? extends NetflixAmazonCredentials> synchronize
+interface AmazonAccountsSynchronizer {
+ List<? extends NetflixAmazonCredentials> synchronize(
+ CredentialsLoader<? extends NetflixAmazonCredentials> credentialsLoader,
+ CredentialsConfig credentialsConfig, AccountCredentialsRepository accountCredentialsRepository,
+ DefaultAccountConfigurationProperties defaultAccountConfigurationProperties,
+ CatsModule catsModule)
}

original_message:
chore(aws): add method sig to AmazonAccountSynchronize (#4883)

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


change_type: ADD

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.converters;
+
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PublishLambdaFunctionVersionDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.ops.PublishLambdaAtomicOperation;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import com.netflix.spinnaker.clouddriver.security.AbstractAtomicOperationsCredentialsSupport;
+import java.util.Map;
+import org.springframework.stereotype.Component;
+
+@Component("publishLambdaFunctionVersion")
+public class PublishLambdaFunctionVersionAtomicOperationConverter
+ extends AbstractAtomicOperationsCredentialsSupport {
+
+ @Override
+ public AtomicOperation convertOperation(Map input) {
+ return new PublishLambdaAtomicOperation(convertDescription(input));
+ }
+
+ @Override
+ public PublishLambdaFunctionVersionDescription convertDescription(Map input) {
+ PublishLambdaFunctionVersionDescription converted =
+ getObjectMapper().convertValue(input, PublishLambdaFunctionVersionDescription.class);
+ converted.setCredentials(getCredentialsObject(input.get("credentials").toString()));
+
+ return converted;
+ }
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.description;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class PublishLambdaFunctionVersionDescription extends AbstractLambdaFunctionDescription {
+ String functionName;
+ String description;
+ String revisionId;
+}

diff:
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.lambda.deploy.ops;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.*;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PublishLambdaFunctionVersionDescription;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import java.util.List;
+
+public class PublishLambdaAtomicOperation
+ extends AbstractLambdaAtomicOperation<
+ PublishLambdaFunctionVersionDescription, PublishVersionResult>
+ implements AtomicOperation<PublishVersionResult> {
+
+ public PublishLambdaAtomicOperation(PublishLambdaFunctionVersionDescription description) {
+ super(description, "PUBLISH_LAMBDA_FUNCTION_VERSION");
+ }
+
+ @Override
+ public PublishVersionResult operate(List priorOutputs) {
+ updateTaskStatus("Initializing Atomic Operation AWS Lambda for PublishVersion...");
+ return publishFunctionVersion(
+ description.getFunctionName(), description.getDescription(), description.getRevisionId());
+ }
+
+ private PublishVersionResult publishFunctionVersion(
+ String functionName, String description, String revisionId) {
+ AWSLambda client = getLambdaClient();
+ PublishVersionRequest req =
+ new PublishVersionRequest()
+ .withFunctionName(functionName)
+ .withDescription(description)
+ .withRevisionId(revisionId);
+
+ PublishVersionResult result = client.publishVersion(req);
+ updateTaskStatus("Finished Atomic Operation AWS Lambda for PublishVersion...");
+ return result;
+ }
+}

original_message:
fix(aws): add missing atomic operation for lambda publish version (#4890)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


diff:
@@ -139,7 +139,7 @@ public class LambdaCachingAgent implements CachingAgent, AccountAware, OnDemandA
attributes.put("account", account.getName());
attributes.put("region", region);
attributes.put("revisions", listFunctionRevisions(x.getFunctionArn()));
- attributes.put("aliasConfiguration", listAliasConfiguration(x.getFunctionArn()));
+ attributes.put("aliasConfigurations", listAliasConfiguration(x.getFunctionArn()));
attributes.put(
"eventSourceMappings", listEventSourceMappingConfiguration(x.getFunctionArn()));

original_message:
fix(aws/lambda): Fix deserializing of lambda alias configurations by fixing typo in attributes map (#4885)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


diff:
@@ -23,7 +23,7 @@ import com.netflix.awsobjectmapper.AmazonObjectMapperConfigurer;
import com.netflix.spinnaker.cats.cache.Cache;
import com.netflix.spinnaker.cats.cache.CacheData;
import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
-import java.util.Map;
+import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -39,6 +39,25 @@ public class LambdaCacheClient extends AbstractCacheClient<LambdaFunction> {
@Override
protected LambdaFunction convert(CacheData cacheData) {
Map<String, Object> attributes = cacheData.getAttributes();
- return objectMapper.convertValue(attributes, LambdaFunction.class);
+ LambdaFunction lambdaFunction = objectMapper.convertValue(attributes, LambdaFunction.class);
+ // Fix broken translation of uuid fields. Perhaps this is better fixed by configuring the
+ // objectMapper right
+ List<Map> eventSourceMappings = (List<Map>) attributes.get("eventSourceMappings");
+ if (eventSourceMappings == null) {
+ return lambdaFunction;
+ }
+ Map<String, String> arnUuidMap = new HashMap<>();
+ eventSourceMappings.stream()
+ .forEach(
+ xx -> {
+ arnUuidMap.put((String) xx.get("eventSourceArn"), (String) xx.get("uuid"));
+ });
+ lambdaFunction
+ .getEventSourceMappings()
+ .forEach(
+ currMapping -> {
+ currMapping.setUUID((String) arnUuidMap.get("uuid"));
+ });
+ return lambdaFunction;
}
}

original_message:
fix (aws/lambda):  patch broken translation of uuid fields by object mapper (#4892)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
@@ -58,6 +58,7 @@ public class FunctionController {
functionProviders.stream()
.map(
functionProvider -> functionProvider.getFunction(account, region, functionName))
+ .filter(function -> function != null)
.collect(Collectors.toList());
return myFunction;
} catch (NotFoundException e) {

original_message:
fix (aws): Filter out null values in list of lambda providers (#4899)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
@@ -56,7 +56,7 @@ public class LambdaCacheClient extends AbstractCacheClient<LambdaFunction> {
.getEventSourceMappings()
.forEach(
currMapping -> {
- currMapping.setUUID((String) arnUuidMap.get("uuid"));
+ currMapping.setUUID((String) arnUuidMap.get(currMapping.getEventSourceArn()));
});
return lambdaFunction;
}

original_message:
fix (aws): Fix broken deserialization of uuid after aws lambda get (#4910)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
@@ -36,6 +36,7 @@ public class CreateLambdaFunctionConfigurationDescription
Integer timeout;
List<String> subnetIds;
List<String> securityGroupIds;
+ List<String> layers;
Map<String, String> envVariables;
Map<String, String> tags;
DeadLetterConfig deadLetterConfig;

diff:
@@ -34,6 +34,7 @@ public class CreateLambdaFunctionDescription extends AbstractLambdaFunctionDescr
String role;
String runtime;
String appName;
+ List<String> layers;
Integer memorySize;
Integer timeout;

diff:
@@ -81,6 +81,7 @@ public class CreateLambdaAtomicOperation
request.setRole(description.getRole());
request.setRuntime(description.getRuntime());
request.setTimeout(description.getTimeout());
+ request.setLayers(description.getLayers());
request.setCode(code);
request.setTags(objTag);

diff:
@@ -63,6 +63,7 @@ public class UpdateLambdaConfigurationAtomicOperation
.withRole(description.getRole())
.withTimeout(description.getTimeout())
.withDeadLetterConfig(description.getDeadLetterConfig())
+ .withLayers(description.getLayers())
.withVpcConfig(
new VpcConfig()
.withSecurityGroupIds(description.getSecurityGroupIds())

original_message:
fix (aws/lambda): add support for adding layers to lambda functions (#4952)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.converters;
+
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaProvisionedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.ops.PutLambdaProvisionedConcurrencyAtomicOperation;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import com.netflix.spinnaker.clouddriver.security.AbstractAtomicOperationsCredentialsSupport;
+import java.util.Map;
+import org.springframework.stereotype.Component;
+
+@Component("putLambdaProvisionedConcurrency")
+public class PutLambdaProvisionedConcurrencyAtomicOperationConverter
+ extends AbstractAtomicOperationsCredentialsSupport {
+
+ @Override
+ public AtomicOperation convertOperation(Map input) {
+ return new PutLambdaProvisionedConcurrencyAtomicOperation(convertDescription(input));
+ }
+
+ @Override
+ public PutLambdaProvisionedConcurrencyDescription convertDescription(Map input) {
+ PutLambdaProvisionedConcurrencyDescription converted =
+ getObjectMapper().convertValue(input, PutLambdaProvisionedConcurrencyDescription.class);
+ converted.setCredentials(getCredentialsObject(input.get("credentials").toString()));
+
+ return converted;
+ }
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.converters;
+
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaReservedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.ops.PutLambdaReservedConcurrencyAtomicOperation;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import com.netflix.spinnaker.clouddriver.security.AbstractAtomicOperationsCredentialsSupport;
+import java.util.Map;
+import org.springframework.stereotype.Component;
+
+@Component("putLambdaReservedConcurrency")
+public class PutLambdaReservedConcurrencyAtomicOperationConverter
+ extends AbstractAtomicOperationsCredentialsSupport {
+
+ @Override
+ public AtomicOperation convertOperation(Map input) {
+ return new PutLambdaReservedConcurrencyAtomicOperation(convertDescription(input));
+ }
+
+ @Override
+ public PutLambdaReservedConcurrencyDescription convertDescription(Map input) {
+ PutLambdaReservedConcurrencyDescription converted =
+ getObjectMapper().convertValue(input, PutLambdaReservedConcurrencyDescription.class);
+ converted.setCredentials(getCredentialsObject(input.get("credentials").toString()));
+
+ return converted;
+ }
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.description;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class PutLambdaProvisionedConcurrencyDescription extends AbstractLambdaFunctionDescription {
+ String functionName;
+ String qualifier;
+ int provisionedConcurrentExecutions;
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.description;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class PutLambdaReservedConcurrencyDescription extends AbstractLambdaFunctionDescription {
+ String functionName;
+ int reservedConcurrentExecutions;
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.ops;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.PutProvisionedConcurrencyConfigRequest;
+import com.amazonaws.services.lambda.model.PutProvisionedConcurrencyConfigResult;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaProvisionedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import java.util.List;
+
+public class PutLambdaProvisionedConcurrencyAtomicOperation
+ extends AbstractLambdaAtomicOperation<
+ PutLambdaProvisionedConcurrencyDescription, PutProvisionedConcurrencyConfigResult>
+ implements AtomicOperation<PutProvisionedConcurrencyConfigResult> {
+
+ public PutLambdaProvisionedConcurrencyAtomicOperation(
+ PutLambdaProvisionedConcurrencyDescription description) {
+ super(description, "PUT_LAMBDA_FUNCTION_PROVISIONED_CONCURRENCY");
+ }
+
+ @Override
+ public PutProvisionedConcurrencyConfigResult operate(List priorOutputs) {
+ updateTaskStatus("Initializing Atomic Operation AWS Lambda for PutProvisionedConcurrency...");
+ return putProvisionedFunctionConcurrency(
+ description.getFunctionName(),
+ description.getQualifier(),
+ description.getProvisionedConcurrentExecutions());
+ }
+
+ private PutProvisionedConcurrencyConfigResult putProvisionedFunctionConcurrency(
+ String functionName, String qualifier, int provisionedConcurrentExecutions) {
+ AWSLambda client = getLambdaClient();
+ PutProvisionedConcurrencyConfigRequest req =
+ new PutProvisionedConcurrencyConfigRequest()
+ .withFunctionName(functionName)
+ .withQualifier(qualifier)
+ .withProvisionedConcurrentExecutions(provisionedConcurrentExecutions);
+
+ PutProvisionedConcurrencyConfigResult result = client.putProvisionedConcurrencyConfig(req);
+ updateTaskStatus("Finished Atomic Operation AWS Lambda for PutProvisionedConcurrency...");
+ return result;
+ }
+}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.ops;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.PutFunctionConcurrencyRequest;
+import com.amazonaws.services.lambda.model.PutFunctionConcurrencyResult;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaReservedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import java.util.List;
+
+public class PutLambdaReservedConcurrencyAtomicOperation
+ extends AbstractLambdaAtomicOperation<
+ PutLambdaReservedConcurrencyDescription, PutFunctionConcurrencyResult>
+ implements AtomicOperation<PutFunctionConcurrencyResult> {
+
+ public PutLambdaReservedConcurrencyAtomicOperation(
+ PutLambdaReservedConcurrencyDescription description) {
+ super(description, "PUT_LAMBDA_FUNCTION_RESERVED_CONCURRENCY");
+ }
+
+ @Override
+ public PutFunctionConcurrencyResult operate(List priorOutputs) {
+ updateTaskStatus("Initializing Atomic Operation AWS Lambda for PutReservedConcurrency...");
+ return putReservedFunctionConcurrency(
+ description.getFunctionName(), description.getReservedConcurrentExecutions());
+ }
+
+ private PutFunctionConcurrencyResult putReservedFunctionConcurrency(
+ String functionName, int reservedConcurrentExecutions) {
+ AWSLambda client = getLambdaClient();
+ PutFunctionConcurrencyRequest req =
+ new PutFunctionConcurrencyRequest()
+ .withFunctionName(functionName)
+ .withReservedConcurrentExecutions(reservedConcurrentExecutions);
+
+ PutFunctionConcurrencyResult result = client.putFunctionConcurrency(req);
+ updateTaskStatus("Finished Atomic Operation AWS Lambda for PutReservedConcurrency...");
+ return result;
+ }
+}

original_message:
fix(aws/lambda): add atomic operations for updating lambda function concurrency (#4950)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
@@ -23,7 +23,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = false)
public class UpsertLambdaFunctionEventMappingDescription extends AbstractLambdaFunctionDescription {
String functionName;
-
+ String qualifier;
Integer batchsize = 1;
Boolean enabled = false;
String eventSourceArn = null;

diff:
@@ -22,6 +22,7 @@ import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
import com.netflix.spinnaker.clouddriver.lambda.deploy.description.UpsertLambdaFunctionEventMappingDescription;
import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
import java.util.List;
+import org.pf4j.util.StringUtils;
public class UpsertLambdaEventSourceAtomicOperation
extends AbstractLambdaAtomicOperation<UpsertLambdaFunctionEventMappingDescription, Object>
@@ -67,6 +68,12 @@ public class UpsertLambdaEventSourceAtomicOperation
.withEnabled(description.getEnabled())
.withUUID(description.getUuid());
+ if (StringUtils.isNotNullOrEmpty(description.getQualifier())) {
+ String fullArnWithQualifier =
+ String.format("%s:%s", cache.getFunctionArn(), description.getQualifier());
+ request.setFunctionName(fullArnWithQualifier);
+ }
+
UpdateEventSourceMappingResult result = client.updateEventSourceMapping(request);
updateTaskStatus("Finished Updating of AWS Lambda Function Event Mapping Operation...");
@@ -85,6 +92,12 @@ public class UpsertLambdaEventSourceAtomicOperation
.withStartingPosition(description.getStartingPosition())
.withEventSourceArn(description.getEventSourceArn());
+ if (StringUtils.isNotNullOrEmpty(description.getQualifier())) {
+ String fullArnWithQualifier =
+ String.format("%s:%s", cache.getFunctionArn(), description.getQualifier());
+ request.setFunctionName(fullArnWithQualifier);
+ }
+
CreateEventSourceMappingResult result = client.createEventSourceMapping(request);
updateTaskStatus("Finished Creation of AWS Lambda Function Event Mapping Operation...");

original_message:
fix(aws/lambda): Support upsert of  event source configurations in lambda aliases (#4956)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda.deploy.description;
+
+import com.amazonaws.services.lambda.model.InvokeResult;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class InvokeLambdaFunctionOutputDescription {
+ InvokeResult invokeResult;
+ private String responseString;
+}

diff:
@@ -21,24 +21,29 @@ import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.model.LogType;
import com.netflix.spinnaker.clouddriver.lambda.deploy.description.InvokeLambdaFunctionDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.InvokeLambdaFunctionOutputDescription;
import com.netflix.spinnaker.clouddriver.orchestration.AtomicOperation;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.util.List;
public class InvokeLambdaAtomicOperation
- extends AbstractLambdaAtomicOperation<InvokeLambdaFunctionDescription, InvokeResult>
- implements AtomicOperation<InvokeResult> {
+ extends AbstractLambdaAtomicOperation<
+ InvokeLambdaFunctionDescription, InvokeLambdaFunctionOutputDescription>
+ implements AtomicOperation<InvokeLambdaFunctionOutputDescription> {
public InvokeLambdaAtomicOperation(InvokeLambdaFunctionDescription description) {
super(description, "INVOKE_LAMBDA_FUNCTION");
}
@Override
- public InvokeResult operate(List priorOutputs) {
+ public InvokeLambdaFunctionOutputDescription operate(List priorOutputs) {
updateTaskStatus("Initializing Invoking AWS Lambda Function Operation...");
return invokeFunction(description.getFunctionName(), description.getPayload());
}
- private InvokeResult invokeFunction(String functionName, String payload) {
+ private InvokeLambdaFunctionOutputDescription invokeFunction(
+ String functionName, String payload) {
AWSLambda client = getLambdaClient();
InvokeRequest req =
new InvokeRequest()
@@ -52,7 +57,25 @@ public class InvokeLambdaAtomicOperation
}
InvokeResult result = client.invoke(req);
+ String ans = byteBuffer2String(result.getPayload(), Charset.forName("UTF-8"));
+ InvokeLambdaFunctionOutputDescription is = new InvokeLambdaFunctionOutputDescription();
+ is.setInvokeResult(result);
+ is.setResponseString(ans);
updateTaskStatus("Finished Invoking of AWS Lambda Function Operation...");
- return result;
+ return is;
+ }
+
+ public static String byteBuffer2String(ByteBuffer buf, Charset charset) {
+ if (buf == null) {
+ return null;
+ }
+ byte[] bytes;
+ if (buf.hasArray()) {
+ bytes = buf.array();
+ } else {
+ buf.rewind();
+ bytes = new byte[buf.remaining()];
+ }
+ return new String(bytes, charset);
}
}

original_message:
fix (aws/lambda) : Send back results from invoke lambda atomic operation (#4970)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>


diff:
@@ -6,6 +6,8 @@ dependencies {
implementation project(":clouddriver-security")
compileOnly "org.projectlombok:lombok"
+ testCompileOnly "org.projectlombok:lombok"
+
annotationProcessor "org.projectlombok:lombok"
testAnnotationProcessor "org.projectlombok:lombok"
@@ -17,7 +19,6 @@ dependencies {
implementation "org.apache.httpcomponents:httpcore"
implementation "org.codehaus.groovy:groovy-all"
implementation "org.springframework.boot:spring-boot-starter-web"
-
implementation "com.squareup.okhttp:okhttp"
implementation "com.squareup.okhttp:okhttp-apache"
implementation "com.squareup.okhttp:okhttp-urlconnection"
@@ -25,4 +26,15 @@ dependencies {
implementation "com.squareup.retrofit:retrofit"
implementation "com.netflix.spectator:spectator-api"
implementation "com.netflix.frigga:frigga"
+
+ testImplementation "cglib:cglib-nodep"
+ testImplementation "org.objenesis:objenesis"
+ testImplementation "org.assertj:assertj-core"
+ testImplementation "org.junit.jupiter:junit-jupiter-api"
+ testImplementation "org.junit.jupiter:junit-jupiter-params"
+ testImplementation "org.junit.platform:junit-platform-runner"
+ testImplementation "org.mockito:mockito-core"
+ testImplementation "org.spockframework:spock-core"
+ testImplementation "org.spockframework:spock-spring"
+ testImplementation "org.springframework:spring-test"
}

diff:
+/*
+ * Copyright 2018 Amazon.com, Inc. or its affiliates.
+ *
+ * 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.lambda;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.util.function.IntPredicate;
+import org.junit.jupiter.api.Test;
+import org.junit.platform.runner.JUnitPlatform;
+import org.junit.runner.RunWith;
+
+@RunWith(JUnitPlatform.class)
+public class InvokeLambdaAtomicOperationTest {
+
+ @Test
+ void dummyTest() throws IOException {
+ assertThat(
+ (IntPredicate)
+ x -> {
+ return true;
+ });
+ }
+}

original_message:
fix (aws/lambda) : Start a dummy test class for lambda. (#4971)

Co-authored-by: smaniyedath <shyam_maniyedath@intuit.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


message:
chore(kotlin): use the JDK 11 kotlin libs
I missed this in commit which switched us to targeting Java 11.

diff:
apply plugin: "kotlin"
dependencies {
- testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
+ testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
testImplementation "org.junit.jupiter:junit-jupiter-api"
testImplementation "org.junit.platform:junit-platform-runner"

original_message:
chore(kotlin): use the JDK 11 kotlin libs (#4978)

I missed this in commit #4919, which switched us to targeting Java 11.


message:
fix(gce): remove the ONLY_DOWN deprecated AutoscalingMode
* feat(gce): remove the deprecated ONLY_UP autoscaling mode
ONLY_SCALE_OUT is the replacement. We'll transform any ONLY_UP we see into ONLY_SCALE_OUT as soon as we find it so that we can pretend ONLY_UP doesn't even exist.
* fix(gce): remove the ONLY_DOWN deprecated AutoscalingMode

diff:
@@ -78,10 +78,6 @@ class GoogleAutoscalingPolicy {
static enum AutoscalingMode {
ON,
OFF,
- ONLY_UP,
- // ONLY_DOWN is being removed as an option from GCE. We can remove this option once we have
- // confirmation that all the autoscaler policies have been migrated away from it (by the GCE
- // team).
- ONLY_DOWN
+ ONLY_SCALE_OUT
}
}

diff:
@@ -930,7 +930,7 @@ abstract class AbstractGoogleServerGroupCachingAgent
output.setLoadBalancingUtilization(loadBalancing);
output.setMaxNumReplicas(input.getMaxNumReplicas());
output.setMinNumReplicas(input.getMinNumReplicas());
- output.setMode(valueOf(AutoscalingMode.class, input.getMode()));
+ output.setMode(convertAutoscalingMode(input.getMode()));
output.setScaleInControl(convertScaleInControl(input.getScaleInControl()));
return output;
}
@@ -979,6 +979,16 @@ abstract class AbstractGoogleServerGroupCachingAgent
return output;
}
+ // ONLY_UP is deprecated, but may still be around in existing autoscaling policies
+ // (as of Q4 2020), so we'll just transform it into the replacement ASAP.
+ private static AutoscalingMode convertAutoscalingMode(@Nullable String input) {
+ if (Objects.equals(input, "ONLY_UP")) {
+ return AutoscalingMode.ONLY_SCALE_OUT;
+ } else {
+ return valueOf(AutoscalingMode.class, input);
+ }
+ }
+
private static ScaleInControl convertScaleInControl(
@Nullable AutoscalingPolicyScaleInControl input) {
if (input == null) {

diff:
@@ -67,6 +67,7 @@ import com.netflix.spinnaker.clouddriver.google.cache.Keys;
import com.netflix.spinnaker.clouddriver.google.compute.GoogleComputeApiFactory;
import com.netflix.spinnaker.clouddriver.google.deploy.GoogleOperationPoller;
import com.netflix.spinnaker.clouddriver.google.model.GoogleAutoscalingPolicy;
+import com.netflix.spinnaker.clouddriver.google.model.GoogleAutoscalingPolicy.AutoscalingMode;
import com.netflix.spinnaker.clouddriver.google.model.GoogleAutoscalingPolicy.CustomMetricUtilization;
import com.netflix.spinnaker.clouddriver.google.model.GoogleInstance;
import com.netflix.spinnaker.clouddriver.google.model.GoogleServerGroup;
@@ -795,6 +796,32 @@ class AbstractGoogleServerGroupCachingAgentTest {
}
}
+ @Test
+ void serverGroupAutoscalingPolicy_onlyUpIsTransformedToOnlyScaleOut() {
+
+ AutoscalingPolicy input = new AutoscalingPolicy().setMode("ONLY_UP");
+
+ InstanceGroupManager instanceGroupManager =
+ new InstanceGroupManager().setName("myServerGroup").setZone(ZONE_URL);
+ Autoscaler autoscaler =
+ new Autoscaler().setZone(ZONE_URL).setTarget("myServerGroup").setAutoscalingPolicy(input);
+
+ Compute compute =
+ new StubComputeFactory()
+ .setInstanceGroupManagers(instanceGroupManager)
+ .setAutoscalers(autoscaler)
+ .create();
+ AbstractGoogleServerGroupCachingAgent cachingAgent =
+ createCachingAgent(
+ compute, ImmutableList.of(instanceGroupManager), ImmutableList.of(autoscaler));
+
+ CacheResult cacheResult = cachingAgent.loadData(inMemoryProviderCache());
+ GoogleServerGroup serverGroup = getOnlyServerGroup(cacheResult);
+ GoogleAutoscalingPolicy converted = serverGroup.getAutoscalingPolicy();
+
+ assertThat(converted.getMode()).isEqualTo(AutoscalingMode.ONLY_SCALE_OUT);
+ }
+
@Test
void serverGroupAutoscalingPolicy_noFields() {

original_message:
fix(gce): remove the ONLY_DOWN deprecated AutoscalingMode (#4985)

* feat(gce): remove the deprecated ONLY_UP autoscaling mode

ONLY_SCALE_OUT is the replacement. We'll transform any ONLY_UP we see into ONLY_SCALE_OUT as soon as we find it so that we can pretend ONLY_UP doesn't even exist.

* fix(gce): remove the ONLY_DOWN deprecated AutoscalingMode

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>


diff:
@@ -15,7 +15,7 @@ dependencies {
implementation "org.apache.httpcomponents:httpclient"
implementation "org.apache.httpcomponents:httpcore"
implementation "com.github.ben-manes.caffeine:guava"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "javax.servlet:javax.servlet-api"
implementation 'com.aestasit.infrastructure.sshoogr:sshoogr:0.9.25'

diff:
@@ -23,7 +23,7 @@ dependencies {
api("com.netflix.spinnaker.kork:kork-plugins-api")
api("com.netflix.spinnaker.kork:kork-credentials-api")
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

diff:
@@ -20,7 +20,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-artifacts"
implementation "com.netflix.spinnaker.kork:kork-config"
implementation "com.netflix.spinnaker.kork:kork-cloud-config-server"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.netflix.spectator:spectator-api"
implementation "com.squareup.okhttp:okhttp"
implementation "com.squareup.retrofit:retrofit"

diff:
@@ -21,7 +21,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-aws"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
implementation "com.netflix.spinnaker.kork:kork-security"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.squareup.okhttp:okhttp"
implementation "com.squareup.okhttp:okhttp-apache"
implementation "com.squareup.okhttp:okhttp-urlconnection"

diff:
@@ -13,7 +13,7 @@ dependencies {
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "org.codehaus.groovy:groovy-all"
implementation "org.springframework.boot:spring-boot-actuator"
implementation "org.springframework.boot:spring-boot-starter-web"

diff:
@@ -46,7 +46,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-artifacts"
implementation "com.netflix.spinnaker.kork:kork-credentials"
implementation "com.netflix.spinnaker.kork:kork-annotations"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.netflix.spectator:spectator-api"
implementation "com.squareup.okhttp:okhttp"
implementation "com.squareup.okhttp:okhttp-apache"

diff:
@@ -29,7 +29,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-jedis"
implementation "com.netflix.spinnaker.kork:kork-web"
implementation "com.netflix.spinnaker.kork:kork-annotations"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.squareup.okhttp:okhttp"
implementation "com.squareup.okhttp:okhttp-apache"
implementation "com.squareup.okhttp:okhttp-urlconnection"

diff:
@@ -9,7 +9,7 @@ dependencies {
implementation "com.netflix.spectator:spectator-api"
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "joda-time:joda-time:2.10.1"
implementation "org.codehaus.groovy:groovy-all"
implementation "org.springframework.boot:spring-boot-actuator"

diff:
@@ -24,7 +24,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-artifacts"
implementation "com.netflix.spinnaker.kork:kork-config"
implementation "com.netflix.spinnaker.kork:kork-cloud-config-server"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.squareup.retrofit:retrofit"
implementation "org.springframework.boot:spring-boot-actuator"
implementation "org.springframework.boot:spring-boot-starter-web"

diff:
@@ -13,7 +13,7 @@ dependencies {
implementation "com.netflix.spectator:spectator-api"
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "org.glassfish.jersey.inject:jersey-hk2:2.28"
implementation 'com.huawei:openstack4j:1.0.17'
implementation "org.glassfish.jersey.core:jersey-client:2.22.1"

diff:
@@ -75,7 +75,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-config"
implementation "com.netflix.spinnaker.kork:kork-cloud-config-server"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "io.kubernetes:client-java:7.0.0"
implementation "org.apache.commons:commons-lang3"
implementation "org.springframework.boot:spring-boot-actuator"

diff:
@@ -13,7 +13,7 @@ dependencies {
implementation "com.netflix.spectator:spectator-api"
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.oracle.oci.sdk:oci-java-sdk-core"
implementation "com.oracle.oci.sdk:oci-java-sdk-identity"
implementation "com.oracle.oci.sdk:oci-java-sdk-loadbalancer"

diff:
@@ -17,7 +17,7 @@ dependencies {
implementation "com.netflix.spinnaker.fiat:fiat-api:$fiatVersion"
implementation "com.netflix.spinnaker.fiat:fiat-core:$fiatVersion"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.netflix.spinnaker.kork:kork-core"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
implementation "com.netflix.spinnaker.kork:kork-security"

diff:
@@ -36,7 +36,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-core"
implementation "com.netflix.spinnaker.kork:kork-exceptions"
implementation "com.netflix.spinnaker.kork:kork-security"
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "com.squareup.okhttp3:okhttp:3.1.2"
implementation "io.grpc:grpc-netty-shaded:$grpcVersion"
implementation "io.grpc:grpc-protobuf:$grpcVersion"

diff:
@@ -41,7 +41,7 @@ dependencies {
implementation "com.netflix.spinnaker.kork:kork-config"
implementation "com.netflix.spinnaker.kork:kork-web"
implementation("com.netflix.spinnaker.kork:kork-plugins")
- implementation "com.netflix.spinnaker.moniker:moniker"
+ implementation "com.netflix.spinnaker.kork:kork-moniker"
implementation "commons-io:commons-io"
implementation "io.reactivex:rxjava"
implementation "io.swagger:swagger-annotations"

diff:
fiatVersion=1.26.0
-korkVersion=7.76.3
+korkVersion=7.77.0
org.gradle.parallel=true
spinnakerGradleVersion=8.9.0
targetJava11=true

original_message: chore(kork): update kork dependency (now w/ moniker) (#4995)


diff:
@@ -113,6 +113,7 @@ public class LambdaCachingAgent implements CachingAgent, AccountAware, OnDemandA
log.info("Describing items in {}", getAgentType());
AWSLambda lambda = amazonClientProvider.getAmazonLambda(account, region);
+
String nextMarker = null;
List<FunctionConfiguration> lstFunction = new ArrayList<FunctionConfiguration>();
@@ -139,9 +140,18 @@ public class LambdaCachingAgent implements CachingAgent, AccountAware, OnDemandA
attributes.put("account", account.getName());
attributes.put("region", region);
attributes.put("revisions", listFunctionRevisions(x.getFunctionArn()));
- attributes.put("aliasConfigurations", listAliasConfiguration(x.getFunctionArn()));
- attributes.put(
- "eventSourceMappings", listEventSourceMappingConfiguration(x.getFunctionArn()));
+ List<AliasConfiguration> allAliases = listAliasConfiguration(x.getFunctionArn());
+ attributes.put("aliasConfigurations", allAliases);
+ List<EventSourceMappingConfiguration> eventSourceMappings =
+ listEventSourceMappingConfiguration(x.getFunctionArn());
+ List<EventSourceMappingConfiguration> aliasEvents = new ArrayList<>();
+ for (AliasConfiguration currAlias : allAliases) {
+ List<EventSourceMappingConfiguration> currAliasEvents =
+ listEventSourceMappingConfiguration(currAlias.getAliasArn());
+ aliasEvents.addAll(currAliasEvents);
+ }
+ eventSourceMappings.addAll(aliasEvents);
+ attributes.put("eventSourceMappings", eventSourceMappings);
attributes = addConfigAttributes(attributes, x, lambda);
String functionName = x.getFunctionName();

original_message: fix(aws/lambda): Load event configurations for all aliases when reading in lambda (#5043)


diff:
@@ -105,7 +105,7 @@ public class UpdateLambdaConfigurationAtomicOperation
}
updateTaskStatus("Finished Updating of AWS Lambda Function Configuration Operation...");
if (StringUtils.isEmpty(description.getTargetGroups())) {
- if (!cache.getTargetGroups().isEmpty()) {
+ if (cache.getTargetGroups() != null && !cache.getTargetGroups().isEmpty()) {
AmazonElasticLoadBalancing loadBalancingV2 = getAmazonElasticLoadBalancingClient();
for (String groupName : cache.getTargetGroups()) {
deregisterTarget(

change_type: DELETE

diff:
-/*
- * Copyright 2018 Amazon.com, Inc. or its affiliates.
- *
- * 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.lambda;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.IOException;
-import java.util.function.IntPredicate;
-import org.junit.jupiter.api.Test;
-import org.junit.platform.runner.JUnitPlatform;
-import org.junit.runner.RunWith;
-
-@RunWith(JUnitPlatform.class)
-public class InvokeLambdaAtomicOperationTest {
-
- @Test
- void dummyTest() throws IOException {
- assertThat(
- (IntPredicate)
- x -> {
- return true;
- });
- }
-}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.CreateFunctionRequest;
+import com.amazonaws.services.lambda.model.CreateFunctionResult;
+import com.amazonaws.services.lambda.model.DeadLetterConfig;
+import com.amazonaws.services.lambda.model.FunctionCode;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.CreateLambdaFunctionDescription;
+import org.junit.jupiter.api.Test;
+
+public class CreateLambdaAtomicOperationTest {
+ @Test
+ void testPublishLambda() {
+ // given
+ CreateLambdaFunctionDescription b =
+ new CreateLambdaFunctionDescription()
+ .setS3bucket("s3://bucket")
+ .setS3key("key/key/path")
+ .setAppName("appName")
+ .setFunctionName("funcName")
+ .setDeadLetterConfig(new DeadLetterConfig().withTargetArn(""));
+ CreateLambdaAtomicOperation clao = spy(new CreateLambdaAtomicOperation(b));
+ doNothing().when(clao).updateTaskStatus(anyString());
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ doReturn(lambdaClient).when(clao).getLambdaClient();
+ CreateFunctionRequest createRequest =
+ new CreateFunctionRequest()
+ .withFunctionName("appName-funcName")
+ .withCode(new FunctionCode().withS3Bucket("s3://bucket").withS3Key("key/key/path"));
+ CreateFunctionResult createLambdaResult =
+ new CreateFunctionResult()
+ .withFunctionName("appName-funcName")
+ .withCodeSha256("abc123def456");
+ doReturn(createLambdaResult).when(lambdaClient).createFunction(createRequest);
+ // when
+ CreateFunctionResult output = clao.operate(null);
+ // then
+ verify(clao, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(createLambdaResult);
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.DeleteFunctionRequest;
+import com.amazonaws.services.lambda.model.DeleteFunctionResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.DeleteLambdaFunctionDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class DeleteLambdaAtomicOperationTest implements LambdaTestingDefaults {
+ @Test
+ void testDeleteLambda() {
+ DeleteLambdaFunctionDescription deleteDesc = new DeleteLambdaFunctionDescription();
+ deleteDesc.setFunctionName(fName).setQualifier(version).setRegion(region).setAccount(account);
+
+ DeleteLambdaAtomicOperation deleteOperation = spy(new DeleteLambdaAtomicOperation(deleteDesc));
+ doNothing().when(deleteOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+ ReflectionTestUtils.setField(deleteOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ doReturn(lambdaClient).when(deleteOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ DeleteFunctionRequest deleteRequest = new DeleteFunctionRequest();
+ deleteRequest.withQualifier(version).withFunctionName(functionArn);
+ DeleteFunctionResult mockDeleteResult = new DeleteFunctionResult();
+ doReturn(mockDeleteResult).when(lambdaClient).deleteFunction(deleteRequest);
+
+ DeleteFunctionResult output = deleteOperation.operate(null);
+ verify(deleteOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockDeleteResult);
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.DeleteEventSourceMappingRequest;
+import com.amazonaws.services.lambda.model.DeleteEventSourceMappingResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.UpsertLambdaFunctionEventMappingDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class DeleteLambdaEventSourceAtomicOperationTest implements LambdaTestingDefaults {
+ @Test
+ void testUpdateLambdaEventMapping() {
+ UpsertLambdaFunctionEventMappingDescription eventMappingDesc =
+ new UpsertLambdaFunctionEventMappingDescription();
+ eventMappingDesc
+ .setFunctionName(fName)
+ .setBatchsize(1)
+ .setEnabled(true)
+ .setEventSourceArn(eventArn)
+ .setUuid(eventUuid)
+ .setRegion(region)
+ .setAccount(account);
+ ;
+ DeleteLambdaEventSourceAtomicOperation deleteEventSourceOperation =
+ spy(new DeleteLambdaEventSourceAtomicOperation(eventMappingDesc));
+ doNothing().when(deleteEventSourceOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+
+ ReflectionTestUtils.setField(
+ deleteEventSourceOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+ doReturn(lambdaClient).when(deleteEventSourceOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ DeleteEventSourceMappingRequest testRequest = new DeleteEventSourceMappingRequest();
+ testRequest.setUUID(eventUuid);
+
+ DeleteEventSourceMappingResult mockDeleteEventResult = new DeleteEventSourceMappingResult();
+ doReturn(mockDeleteEventResult).when(lambdaClient).deleteEventSourceMapping(testRequest);
+
+ Object output = deleteEventSourceOperation.operate(null);
+ verify(deleteEventSourceOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockDeleteEventResult);
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.InvokeRequest;
+import com.amazonaws.services.lambda.model.InvokeResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.InvokeLambdaFunctionDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.InvokeLambdaFunctionOutputDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class InvokeLambdaAtomicOperationTest implements LambdaTestingDefaults {
+ @Test
+ void testInvokeLambda() {
+ InvokeLambdaFunctionDescription invokeDesc = new InvokeLambdaFunctionDescription();
+ invokeDesc.setFunctionName(fName).setQualifier(version).setRegion(region).setAccount(account);
+
+ InvokeLambdaAtomicOperation invokeOperation = spy(new InvokeLambdaAtomicOperation(invokeDesc));
+ doNothing().when(invokeOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+ ReflectionTestUtils.setField(invokeOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ doReturn(lambdaClient).when(invokeOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ InvokeRequest invokeRequest = new InvokeRequest();
+ invokeRequest.withQualifier(version).withFunctionName(functionArn);
+ InvokeResult mockDeleteResult = new InvokeResult();
+ doReturn(mockDeleteResult).when(lambdaClient).invoke(invokeRequest);
+
+ InvokeLambdaFunctionOutputDescription output = invokeOperation.operate(null);
+ verify(invokeOperation, atLeastOnce()).updateTaskStatus(anyString());
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import com.amazonaws.services.lambda.model.AliasConfiguration;
+import com.amazonaws.services.lambda.model.EventSourceMappingConfiguration;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import java.util.ArrayList;
+import java.util.List;
+
+public interface LambdaTestingDefaults {
+
+ String fName = "app1-stack1-detail1-function1";
+ String functionArn = "function1:arn";
+ String region = "us-west-2";
+ String account = "account-1";
+ String version = "1";
+ String eventArn = "arn-1";
+ String eventUuid = "uuid-1";
+ String revisionId = "1";
+ String revisionDesc = "Revision Desc";
+ String aliasName = "fAlias";
+ String aliasArn = "alias-arn-1";
+ String aliasDesc = "Alias Description";
+
+ default LambdaFunction getMockedFunctionDefintion() {
+ LambdaFunction cachedFunction = new LambdaFunction();
+ cachedFunction.setFunctionName(fName);
+ cachedFunction.setFunctionArn(functionArn);
+ cachedFunction.setRegion(region);
+ cachedFunction.setAccount(account);
+ cachedFunction.setAliasConfigurations(getMockAliases());
+ cachedFunction.setEventSourceMappings(getMockEventSourceList());
+ return cachedFunction;
+ }
+
+ default List<AliasConfiguration> getMockAliases() {
+ AliasConfiguration es = new AliasConfiguration();
+ es.setAliasArn(aliasArn);
+ es.setDescription(aliasDesc);
+ es.setName(aliasName);
+ es.setRevisionId(revisionId);
+ List<AliasConfiguration> le = new ArrayList();
+ le.add(es);
+ return le;
+ }
+
+ default List<EventSourceMappingConfiguration> getMockEventSourceList() {
+ EventSourceMappingConfiguration es = new EventSourceMappingConfiguration();
+ es.setUUID(eventUuid);
+ es.setEventSourceArn(eventArn);
+ List<EventSourceMappingConfiguration> le = new ArrayList();
+ le.add(es);
+ return le;
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.PublishVersionRequest;
+import com.amazonaws.services.lambda.model.PublishVersionResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PublishLambdaFunctionVersionDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class PublishLambdaAtomicOperationTest implements LambdaTestingDefaults {
+
+ @Test
+ void testPublishLambda() {
+ PublishLambdaFunctionVersionDescription publishDesc =
+ new PublishLambdaFunctionVersionDescription();
+ publishDesc
+ .setFunctionName(fName)
+ .setDescription(revisionDesc)
+ .setRevisionId(revisionId)
+ .setRegion(region)
+ .setAccount(account);
+ ;
+
+ PublishLambdaAtomicOperation publishOperation =
+ spy(new PublishLambdaAtomicOperation(publishDesc));
+ doNothing().when(publishOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+
+ ReflectionTestUtils.setField(
+ publishOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+ doReturn(lambdaClient).when(publishOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ PublishVersionRequest testRequest = new PublishVersionRequest();
+ testRequest.setFunctionName(fName);
+ testRequest.setRevisionId(revisionId);
+ testRequest.setDescription(revisionDesc);
+
+ PublishVersionResult mockPublishResult = new PublishVersionResult();
+ doReturn(mockPublishResult).when(lambdaClient).publishVersion(testRequest);
+
+ PublishVersionResult output = publishOperation.operate(null);
+ verify(publishOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockPublishResult);
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.PutFunctionConcurrencyRequest;
+import com.amazonaws.services.lambda.model.PutFunctionConcurrencyResult;
+import com.amazonaws.services.lambda.model.PutProvisionedConcurrencyConfigRequest;
+import com.amazonaws.services.lambda.model.PutProvisionedConcurrencyConfigResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaProvisionedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.PutLambdaReservedConcurrencyDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class PutConcurrencyAtomicOperationTest implements LambdaTestingDefaults {
+
+ @Test
+ void testProvisionedConcurrency() {
+ PutLambdaProvisionedConcurrencyDescription provisionedConcurrencyDescription =
+ new PutLambdaProvisionedConcurrencyDescription();
+ provisionedConcurrencyDescription
+ .setFunctionName(fName)
+ .setQualifier(version)
+ .setProvisionedConcurrentExecutions(2)
+ .setRegion(region)
+ .setAccount(account);
+ ;
+
+ PutLambdaProvisionedConcurrencyAtomicOperation putConcurrencyOperation =
+ spy(new PutLambdaProvisionedConcurrencyAtomicOperation(provisionedConcurrencyDescription));
+ doNothing().when(putConcurrencyOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+
+ ReflectionTestUtils.setField(
+ putConcurrencyOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+ doReturn(lambdaClient).when(putConcurrencyOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ PutProvisionedConcurrencyConfigRequest testRequest =
+ new PutProvisionedConcurrencyConfigRequest();
+ testRequest.setFunctionName(fName);
+ testRequest.setQualifier(version);
+ testRequest.setProvisionedConcurrentExecutions(2);
+
+ PutProvisionedConcurrencyConfigResult mockProvisionResult =
+ new PutProvisionedConcurrencyConfigResult();
+ mockProvisionResult.setAllocatedProvisionedConcurrentExecutions(2);
+ mockProvisionResult.setAvailableProvisionedConcurrentExecutions(4);
+ mockProvisionResult.setStatus("provisioned");
+ doReturn(mockProvisionResult).when(lambdaClient).putProvisionedConcurrencyConfig(testRequest);
+
+ PutProvisionedConcurrencyConfigResult output = putConcurrencyOperation.operate(null);
+ verify(putConcurrencyOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockProvisionResult);
+ }
+
+ @Test
+ void testReservedConcurrency() {
+ PutLambdaReservedConcurrencyDescription provisionedConcurrencyDescription =
+ new PutLambdaReservedConcurrencyDescription();
+ provisionedConcurrencyDescription
+ .setFunctionName(fName)
+ .setReservedConcurrentExecutions(2)
+ .setRegion(region)
+ .setAccount(account);
+ ;
+
+ PutLambdaReservedConcurrencyAtomicOperation putConcurrencyOperation =
+ spy(new PutLambdaReservedConcurrencyAtomicOperation(provisionedConcurrencyDescription));
+ doNothing().when(putConcurrencyOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+
+ ReflectionTestUtils.setField(
+ putConcurrencyOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+ doReturn(lambdaClient).when(putConcurrencyOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ PutFunctionConcurrencyRequest testRequest = new PutFunctionConcurrencyRequest();
+ testRequest.setReservedConcurrentExecutions(2);
+ testRequest.setFunctionName(fName);
+
+ PutFunctionConcurrencyResult mockProvisionResult = new PutFunctionConcurrencyResult();
+ doReturn(mockProvisionResult).when(lambdaClient).putFunctionConcurrency(testRequest);
+
+ PutFunctionConcurrencyResult output = putConcurrencyOperation.operate(null);
+ verify(putConcurrencyOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockProvisionResult);
+ }
+}

diff:
+/*
+ * Copyright 2020 Netflix, 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.lambda.deploy.ops;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.*;
+
+import com.amazonaws.services.lambda.AWSLambda;
+import com.amazonaws.services.lambda.model.UpdateFunctionCodeRequest;
+import com.amazonaws.services.lambda.model.UpdateFunctionCodeResult;
+import com.netflix.spinnaker.clouddriver.lambda.cache.model.LambdaFunction;
+import com.netflix.spinnaker.clouddriver.lambda.deploy.description.UpdateLambdaFunctionCodeDescription;
+import com.netflix.spinnaker.clouddriver.lambda.provider.view.LambdaFunctionProvider;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class UpdateLambdaAtomicOperationTest implements LambdaTestingDefaults {
+
+ @Test
+ void testUpdateLambdaCode() {
+ UpdateLambdaFunctionCodeDescription updateCodeDesc = new UpdateLambdaFunctionCodeDescription();
+ updateCodeDesc.setFunctionName(fName).setRegion(region).setAccount(account);
+
+ UpdateLambdaCodeAtomicOperation updateCodeOperation =
+ spy(new UpdateLambdaCodeAtomicOperation(updateCodeDesc));
+ doNothing().when(updateCodeOperation).updateTaskStatus(anyString());
+
+ AWSLambda lambdaClient = mock(AWSLambda.class);
+ LambdaFunction cachedFunction = getMockedFunctionDefintion();
+
+ LambdaFunctionProvider lambdaFunctionProvider = mock(LambdaFunctionProvider.class);
+ ReflectionTestUtils.setField(
+ updateCodeOperation, "lambdaFunctionProvider", lambdaFunctionProvider);
+
+ doReturn(lambdaClient).when(updateCodeOperation).getLambdaClient();
+ doReturn(cachedFunction)
+ .when(lambdaFunctionProvider)
+ .getFunction(anyString(), anyString(), anyString());
+
+ UpdateFunctionCodeRequest updateCodeRequest = new UpdateFunctionCodeRequest();
+ updateCodeRequest.withFunctionName(functionArn);
+ UpdateFunctionCodeResult mockCodeResult = new UpdateFunctionCodeResult();
+ doReturn(mockCodeResult).when(lambdaClient).updateFunctionCode(updateCodeRequest);
+
+ UpdateFunctionCodeResult output = updateCodeOperation.operate(null);
+ verify(updateCodeOperation, atLeastOnce()).updateTaskStatus(anyString());
+ assertThat(output).isEqualTo(mockCodeResult);
+ }
+
+ @Test
+ void testUpdateLambdaConfig() {
+ // TODO
+ }
+}

original_message: chore(test/lambda): Add tests for lambda operations (#5084)


diff:
package com.netflix.spinnaker.clouddriver.ecs.deploy.ops;
import com.amazonaws.services.applicationautoscaling.AWSApplicationAutoScaling;
-import com.amazonaws.services.applicationautoscaling.model.RegisterScalableTargetRequest;
-import com.amazonaws.services.applicationautoscaling.model.ScalableDimension;
-import com.amazonaws.services.applicationautoscaling.model.ServiceNamespace;
-import com.amazonaws.services.applicationautoscaling.model.SuspendedState;
+import com.amazonaws.services.applicationautoscaling.model.*;
import com.amazonaws.services.ecs.AmazonECS;
import com.amazonaws.services.ecs.model.UpdateServiceRequest;
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ModifyServiceDescription;
@@ -48,6 +45,19 @@ public class DisableServiceAtomicOperation
String account = description.getAccount();
String cluster = getCluster(service, account);
+ DescribeScalableTargetsRequest describeRequest =
+ new DescribeScalableTargetsRequest()
+ .withServiceNamespace(ServiceNamespace.Ecs)
+ .withResourceIds(String.format("service/%s/%s", cluster, service))
+ .withScalableDimension(ScalableDimension.EcsServiceDesiredCount);
+ DescribeScalableTargetsResult describeResult =
+ autoScalingClient.describeScalableTargets(describeRequest);
+
+ if (isSuspended(describeResult)) {
+ updateTaskStatus(
+ String.format(
+ "Autoscaling already suspended on server group %s for %s.", service, account));
+ } else {
updateTaskStatus(
String.format("Suspending autoscaling on %s server group for %s.", service, account));
RegisterScalableTargetRequest suspendRequest =
@@ -63,6 +73,7 @@ public class DisableServiceAtomicOperation
autoScalingClient.registerScalableTarget(suspendRequest);
updateTaskStatus(
String.format("Autoscaling on server group %s suspended for %s.", service, account));
+ }
updateTaskStatus(String.format("Disabling %s server group for %s.", service, account));
UpdateServiceRequest request =
@@ -70,4 +81,26 @@ public class DisableServiceAtomicOperation
ecs.updateService(request);
updateTaskStatus(String.format("Server group %s disabled for %s.", service, account));
}
+
+ private boolean isSuspended(DescribeScalableTargetsResult describeResult) {
+ if (describeResult != null
+ && describeResult.getScalableTargets() != null
+ && describeResult.getScalableTargets().size() > 0) {
+ ScalableTarget target =
+ describeResult.getScalableTargets().stream()
+ .filter(
+ e ->
+ (e.getScalableDimension()
+ .equals(ScalableDimension.EcsServiceDesiredCount.toString())))
+ .findFirst()
+ .orElse(null);
+
+ return (target != null)
+ && target.getSuspendedState().getScheduledScalingSuspended()
+ && target.getSuspendedState().getDynamicScalingInSuspended()
+ && target.getSuspendedState().getDynamicScalingOutSuspended();
+ }
+
+ return false;
+ }
}

diff:
package com.netflix.spinnaker.clouddriver.ecs.deploy.ops
+import com.amazonaws.services.applicationautoscaling.model.DescribeScalableTargetsResult
+import com.amazonaws.services.applicationautoscaling.model.ScalableDimension
+import com.amazonaws.services.applicationautoscaling.model.ScalableTarget
+import com.amazonaws.services.applicationautoscaling.model.SuspendedState
import com.netflix.spinnaker.clouddriver.ecs.TestCredential
import com.netflix.spinnaker.clouddriver.ecs.deploy.description.ModifyServiceDescription
@@ -40,7 +44,45 @@ class DisableServiceAtomicOperationSpec extends CommonAtomicOperation {
operation.operate([])
then:
+ 1 * autoscaling.describeScalableTargets(_) >> new DescribeScalableTargetsResult()
+ .withScalableTargets(new ScalableTarget()
+ .withScalableDimension(ScalableDimension.EcsServiceDesiredCount)
+ .withSuspendedState(new SuspendedState()
+ .withScheduledScalingSuspended(false)
+ .withDynamicScalingInSuspended(false)
+ .withDynamicScalingOutSuspended(false)))
1 * autoscaling.registerScalableTarget(_)
1 * ecs.updateService(_)
}
+
+ void 'should not suspend autoscaling if it is already suspended'() {
+ given:
+ def operation = new DisableServiceAtomicOperation(new ModifyServiceDescription(
+ serverGroupName: "test-server-group",
+ credentials: TestCredential.named('Test', [:])
+ ))
+
+ operation.amazonClientProvider = amazonClientProvider
+ operation.credentialsRepository = credentialsRepository
+ operation.containerInformationService = containerInformationService
+
+ amazonClientProvider.getAmazonEcs(_, _, _) >> ecs
+ amazonClientProvider.getAmazonApplicationAutoScaling(_, _, _) >> autoscaling
+ containerInformationService.getClusterName(_, _, _) >> 'cluster-name'
+ credentialsRepository.getOne(_) >> TestCredential.named("test")
+
+ when:
+ operation.operate([])
+
+ then:
+ 1 * autoscaling.describeScalableTargets(_) >> new DescribeScalableTargetsResult()
+ .withScalableTargets(new ScalableTarget()
+ .withScalableDimension(ScalableDimension.EcsServiceDesiredCount)
+ .withSuspendedState(new SuspendedState()
+ .withScheduledScalingSuspended(true)
+ .withDynamicScalingInSuspended(true)
+ .withDynamicScalingOutSuspended(true)))
+ 0 * autoscaling.registerScalableTarget(_)
+ 1 * ecs.updateService(_)
+ }
}

original_message: fix(ecs): check for already suspended autoscaling on disable service op (#5218)


diff:
@@ -98,6 +98,7 @@ public class CreateServerGroupDescription extends AbstractECSDescription {
Map<Object, Object> spelProcessedTaskDefinitionArtifact;
String taskDefinitionArtifactAccount;
Map<String, String> containerToImageMap;
+ boolean enableExecuteCommand;
/**
* @deprecated this field only allows for one container to be specified. ECS supports the ability

diff:
@@ -545,7 +545,8 @@ public class CreateServerGroupAtomicOperation
.withPlacementConstraints(description.getPlacementConstraints())
.withPlacementStrategy(description.getPlacementStrategySequence())
.withServiceRegistries(serviceRegistries)
- .withDeploymentConfiguration(deploymentConfiguration);
+ .withDeploymentConfiguration(deploymentConfiguration)
+ .withEnableExecuteCommand(description.isEnableExecuteCommand());
List<Tag> taskDefTags = new LinkedList<>();
if (description.getTags() != null && !description.getTags().isEmpty()) {

diff:
@@ -179,6 +179,7 @@ class CreateServerGroupAtomicOperationSpec extends CommonAtomicOperation {
request.tags.get(1).value == 'tomato'
request.launchType == null
request.platformVersion == null
+ request.enableExecuteCommand == false
}) >> new CreateServiceResult().withService(service)
result.getServerGroupNames().size() == 1
@@ -244,7 +245,8 @@ class CreateServerGroupAtomicOperationSpec extends CommonAtomicOperation {
subnetType: 'public',
securityGroupNames: ['helloworld'],
associatePublicIpAddress: true,
- serviceDiscoveryAssociations: [serviceRegistry]
+ serviceDiscoveryAssociations: [serviceRegistry],
+ enableExecuteCommand: true
)
def operation = new CreateServerGroupAtomicOperation(description)
@@ -308,6 +310,7 @@ class CreateServerGroupAtomicOperationSpec extends CommonAtomicOperation {
request.tags == []
request.launchType == 'FARGATE'
request.platformVersion == '1.0.0'
+ request.enableExecuteCommand == true
} as CreateServiceRequest) >> new CreateServiceResult().withService(service)
result.getServerGroupNames().size() == 1

original_message: feat(ecs): Add support for enableExecuteCommand (#5378)


old_path: CODEOWNERS

new_path: CODEOWNERS

diff:
-clouddriver-kubernetes/ @maggieneterval @ethanfrogers @german-muzquiz
-clouddriver-google/ @maggieneterval @plumpy
+clouddriver-kubernetes/ @ethanfrogers @german-muzquiz
+clouddriver-google/ @plumpy
clouddriver-cloudfoundry/ @zachsmith1
clouddriver-appengine/ @zachsmith1
clouddriver-lambda/ @zachsmith1

original_message: chore(codeowners): Remove maggieneterval from CODEOWNERS (#5385)


message:
chore(codeowners): Update the CODEOWNERS for the new googlecloud SIG.
Also update the kubernetes directory to the current kubernetes SIG
owners.

diff:
-clouddriver-kubernetes/ @ethanfrogers @german-muzquiz
-clouddriver-google/ @plumpy
+clouddriver-kubernetes/ @clanesf @german-muzquiz
+clouddriver-google/ @Nirmalyasen @plumpy @rebala @skandragon
clouddriver-cloudfoundry/ @zachsmith1
clouddriver-appengine/ @zachsmith1
clouddriver-lambda/ @zachsmith1

original_message:
chore(codeowners): Update the CODEOWNERS for the new googlecloud SIG. (#5411)

Also update the kubernetes directory to the current kubernetes SIG
owners.


message: Added infoButton to DataVC with text. Changed HeaderTitle text in DataVC

diff:
46F21CA92422444600C01DFA /* ScanListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CA82422444600C01DFA /* ScanListVC.swift */; };
46F21CAF2422597F00C01DFA /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CAE2422597F00C01DFA /* Scan.swift */; };
46F21CB4242270F700C01DFA /* ScannerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CB3242270F700C01DFA /* ScannerStore.swift */; };
+ 5EE9D815242F74F5002F833C /* DataHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE9D814242F74F5002F833C /* DataHeaderCell.swift */; };
800DD2D62428F49800E6CAEA /* Debug.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8054C0B6241D492F008907B8 /* Debug.storyboard */; };
803C5B23242932BF00E49414 /* DataListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803C5B22242932BF00E49414 /* DataListVC.swift */; };
803C5B252429346500E49414 /* DataListVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803C5B242429346500E49414 /* DataListVM.swift */; };
46F21CA82422444600C01DFA /* ScanListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanListVC.swift; sourceTree = "<group>"; };
46F21CAE2422597F00C01DFA /* Scan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = "<group>"; };
46F21CB3242270F700C01DFA /* ScannerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerStore.swift; sourceTree = "<group>"; };
+ 5EE9D814242F74F5002F833C /* DataHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataHeaderCell.swift; sourceTree = "<group>"; };
7235650B7A53BA0BF25B7647 /* Pods-BT-Tracking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BT-Tracking.debug.xcconfig"; path = "Target Support Files/Pods-BT-Tracking/Pods-BT-Tracking.debug.xcconfig"; sourceTree = "<group>"; };
803C5B22242932BF00E49414 /* DataListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataListVC.swift; sourceTree = "<group>"; };
803C5B242429346500E49414 /* DataListVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataListVM.swift; sourceTree = "<group>"; };
isa = PBXGroup;
children = (
80AD970C2429318B00AEA661 /* DataCell.swift */,
+ 5EE9D814242F74F5002F833C /* DataHeaderCell.swift */,
);
path = Cells;
sourceTree = "<group>";
8054C0D824200E7C008907B8 /* FileController.swift in Sources */,
80ECB96924291E2F00E57601 /* CSVWriter.swift in Sources */,
80B94555242B7B460052CD9F /* ActiveAppViewModel.swift in Sources */,
+ 5EE9D815242F74F5002F833C /* DataHeaderCell.swift in Sources */,
80D5F7E52423D8740010EF51 /* CompleteActivationController.swift in Sources */,
8054C0B1241D492F008907B8 /* AppDelegate.swift in Sources */,
8054C0D0241FE706008907B8 /* BTScanner.swift in Sources */,

diff:
@@ -51,9 +51,10 @@ class DataListVM {
extension DataListVM {
private func section(from scans: [Scan]) -> [SectionModel] {
+ let header = DataListVM.Section.Item.header(scans.count)
let items: [DataListVM.Section.Item] = scans.map { .data($0) }
return [
- SectionModel(model: .list, items: [.header] + items)
+ SectionModel(model: .list, items: [header] + items)
]
}
@@ -80,7 +81,7 @@ extension DataListVM {
}
enum Item: IdentifiableType, Equatable {
- case header
+ case header(Int)
case data(Scan)
var identity: String {

license: MIT License


message: Help screen now is tableView with VM

diff:
46F21CA92422444600C01DFA /* ScanListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CA82422444600C01DFA /* ScanListVC.swift */; };
46F21CAF2422597F00C01DFA /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CAE2422597F00C01DFA /* Scan.swift */; };
46F21CB4242270F700C01DFA /* ScannerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CB3242270F700C01DFA /* ScannerStore.swift */; };
+ 5ED9B2322432517300A24703 /* HelpVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ED9B2312432517300A24703 /* HelpVM.swift */; };
+ 5ED9B237243252DC00A24703 /* HelpCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ED9B236243252DC00A24703 /* HelpCell.swift */; };
5EE9D815242F74F5002F833C /* DataHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE9D814242F74F5002F833C /* DataHeaderCell.swift */; };
800DD2D62428F49800E6CAEA /* Debug.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8054C0B6241D492F008907B8 /* Debug.storyboard */; };
803C5B23242932BF00E49414 /* DataListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803C5B22242932BF00E49414 /* DataListVC.swift */; };
8054C0E22420EFE0008907B8 /* FileLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4649848424201E4600A858A9 /* FileLogger.swift */; };
805BE9772424DE0E001A93B3 /* BTDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 805BE9762424DE0E001A93B3 /* BTDevice.swift */; };
805BE97924252AE6001A93B3 /* MulticastDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 805BE97824252AE6001A93B3 /* MulticastDelegate.swift */; };
- 80631A96242CA27800EB0B6C /* HelpController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80631A95242CA27800EB0B6C /* HelpController.swift */; };
+ 80631A96242CA27800EB0B6C /* HelpVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80631A95242CA27800EB0B6C /* HelpVC.swift */; };
80631A98242CAB5000EB0B6C /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80631A97242CAB5000EB0B6C /* Image.swift */; };
807053532427BA2500DC1034 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 807053522427BA2500DC1034 /* Data.swift */; };
807053582427C5AA00DC1034 /* InfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 807053572427C5AA00DC1034 /* InfoCell.swift */; };
46F21CA82422444600C01DFA /* ScanListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanListVC.swift; sourceTree = "<group>"; };
46F21CAE2422597F00C01DFA /* Scan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = "<group>"; };
46F21CB3242270F700C01DFA /* ScannerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerStore.swift; sourceTree = "<group>"; };
+ 5ED9B2312432517300A24703 /* HelpVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpVM.swift; sourceTree = "<group>"; };
+ 5ED9B236243252DC00A24703 /* HelpCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCell.swift; sourceTree = "<group>"; };
5EE9D814242F74F5002F833C /* DataHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataHeaderCell.swift; sourceTree = "<group>"; };
7235650B7A53BA0BF25B7647 /* Pods-BT-Tracking.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BT-Tracking.debug.xcconfig"; path = "Target Support Files/Pods-BT-Tracking/Pods-BT-Tracking.debug.xcconfig"; sourceTree = "<group>"; };
803C5B22242932BF00E49414 /* DataListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataListVC.swift; sourceTree = "<group>"; };
8054C0E02420EEFF008907B8 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
805BE9762424DE0E001A93B3 /* BTDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTDevice.swift; sourceTree = "<group>"; };
805BE97824252AE6001A93B3 /* MulticastDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MulticastDelegate.swift; sourceTree = "<group>"; };
- 80631A95242CA27800EB0B6C /* HelpController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpController.swift; sourceTree = "<group>"; };
+ 80631A95242CA27800EB0B6C /* HelpVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpVC.swift; sourceTree = "<group>"; };
80631A97242CAB5000EB0B6C /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
807053522427BA2500DC1034 /* Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Data.swift; sourceTree = "<group>"; };
807053572427C5AA00DC1034 /* InfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCell.swift; sourceTree = "<group>"; };
name = Frameworks;
sourceTree = "<group>";
};
+ 5ED9B235243252CB00A24703 /* Cells */ = {
+ isa = PBXGroup;
+ children = (
+ 5ED9B236243252DC00A24703 /* HelpCell.swift */,
+ );
+ path = Cells;
+ sourceTree = "<group>";
+ };
8054C0A4241D492F008907B8 = {
isa = PBXGroup;
children = (
BDB07FBE24254A7B00834E79 /* Help */ = {
isa = PBXGroup;
children = (
+ 5ED9B235243252CB00A24703 /* Cells */,
BDB07FBF24254A8F00834E79 /* Help.storyboard */,
- 80631A95242CA27800EB0B6C /* HelpController.swift */,
+ 80631A95242CA27800EB0B6C /* HelpVC.swift */,
+ 5ED9B2312432517300A24703 /* HelpVM.swift */,
);
path = Help;
sourceTree = "<group>";
803C5B252429346500E49414 /* DataListVM.swift in Sources */,
BD979AE924255BD1004001ED /* FirstActiovationController.swift in Sources */,
8054C0D624200BEC008907B8 /* LogSegmentController.swift in Sources */,
- 80631A96242CA27800EB0B6C /* HelpController.swift in Sources */,
+ 80631A96242CA27800EB0B6C /* HelpVC.swift in Sources */,
80BB476824238CBB00F552FC /* AccountActivationController.swift in Sources */,
803C5B23242932BF00E49414 /* DataListVC.swift in Sources */,
46A0D52F242CEB8A00FAE9EA /* DeleteDataVC.swift in Sources */,
46F21CA92422444600C01DFA /* ScanListVC.swift in Sources */,
8075EDC0242A613F001D9DCD /* AppSettings.swift in Sources */,
8054C0DA24200E91008907B8 /* LogController.swift in Sources */,
+ 5ED9B2322432517300A24703 /* HelpVM.swift in Sources */,
46F21CB4242270F700C01DFA /* ScannerStore.swift in Sources */,
80B94557242B96560052CD9F /* NavigationController.swift in Sources */,
8054C0D824200E7C008907B8 /* FileLogController.swift in Sources */,
80D5F7E52423D8740010EF51 /* CompleteActivationController.swift in Sources */,
8054C0B1241D492F008907B8 /* AppDelegate.swift in Sources */,
8054C0D0241FE706008907B8 /* BTScanner.swift in Sources */,
+ 5ED9B237243252DC00A24703 /* HelpCell.swift in Sources */,
80ECB96324290C1000E57601 /* ScanCell.swift in Sources */,
80BB476624236ED100F552FC /* BluetoothActivationController.swift in Sources */,
80BF9C262424D55800150108 /* SendReportController.swift in Sources */,

original_message: Help screen now is tableView with VM


message: Added segmented control to DataList with binding, but without handling

diff:
@@ -16,6 +16,8 @@ class DataListVM {
// MARK: - Properties
+ let onSegmentedControl = PublishSubject<Int>()
+
private let scans: Observable<[Scan]>
private let scanObjects: Results<ScanRealm>
private let bag = DisposeBag()
@@ -29,6 +31,12 @@ class DataListVM {
.map { scanned in
return scanned.map { $0.toScan() }
}
+
+ onSegmentedControl
+ .subscribe(onNext: { [weak self] index in
+ // TODO: Change data in tableView
+ print("onSegmentedControl selected index: \(index)")
+ }).disposed(by: bag)
}
// MARK: - Sections


message: Added handling segmentedControl

diff:
@@ -36,6 +36,7 @@ final class DataListVC: UIViewController, UITableViewDelegate {
}
setupTableView()
+ viewModel.selectedSegmentIndex.accept(0)
}
// MARK: - TableView
@@ -72,7 +73,7 @@ final class DataListVC: UIViewController, UITableViewDelegate {
// MARK: - Actions
@IBAction private func segmentedControlValueChanged(_ sender: UISegmentedControl) {
- viewModel.onSegmentedControl.onNext(sender.selectedSegmentIndex)
+ viewModel.selectedSegmentIndex.accept(sender.selectedSegmentIndex)
}
@IBAction private func sendReportAction() {

diff:
@@ -15,8 +15,7 @@ import RealmSwift
class DataListVM {
// MARK: - Properties
-
- let onSegmentedControl = PublishSubject<Int>()
+ let selectedSegmentIndex = PublishRelay<Int>()
private let scans: Observable<[Scan]>
private let scanObjects: Results<ScanRealm>
@@ -31,18 +30,19 @@ class DataListVM {
.map { scanned in
return scanned.map { $0.toScan() }
}
-
- onSegmentedControl
- .subscribe(onNext: { [weak self] index in
- // TODO: Change data in tableView
- print("onSegmentedControl selected index: \(index)")
- }).disposed(by: bag)
}
// MARK: - Sections
var sections: Driver<[SectionModel]> {
- return scans
+ return Observable.combineLatest(scans, selectedSegmentIndex)
+ .map { unfilteredScans, selectedSegmentIndex -> [Scan] in
+ return unfilteredScans.filter { scan in
+ guard let medianRssi = scan.medianRssi else { return false }
+ let medianRssiPoint = AppSettings.medianRssiPoint
+ return selectedSegmentIndex == 0 ? (medianRssi < medianRssiPoint) : (medianRssi > medianRssiPoint)
+ }
+ }
.map { unsortedScans in
return unsortedScans.sorted(by: { scan0, scan1 in scan0.date > scan1.date })
}

diff:
@@ -11,6 +11,7 @@ import Foundation
struct AppSettings {
static let firebaseRegion = "europe-west1"
+ static let medianRssiPoint = 30
static var BUID: String? {
get {

original_message: Added handling segmentedControl


message: Fixed issue with filtering

diff:
@@ -40,7 +40,7 @@ class DataListVM {
return unfilteredScans.filter { scan in
guard let medianRssi = scan.medianRssi else { return false }
let medianRssiPoint = AppSettings.medianRssiPoint
- return selectedSegmentIndex == 0 ? (medianRssi < medianRssiPoint) : (medianRssi > medianRssiPoint)
+ return selectedSegmentIndex == 0 ? (medianRssi < medianRssiPoint) : true
}
}
.map { unsortedScans in

diff:
@@ -11,7 +11,7 @@ import Foundation
struct AppSettings {
static let firebaseRegion = "europe-west1"
- static let medianRssiPoint = 30
+ static let medianRssiPoint = -30
static var BUID: String? {
get {

original_message: Fixed issue with filtering


message: Added unregister feature. Added finish screen

diff:
46F21CA92422444600C01DFA /* ScanListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CA82422444600C01DFA /* ScanListVC.swift */; };
46F21CAF2422597F00C01DFA /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CAE2422597F00C01DFA /* Scan.swift */; };
46F21CB4242270F700C01DFA /* ScannerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46F21CB3242270F700C01DFA /* ScannerStore.swift */; };
+ 5E110F9C2433C4AD0059712A /* UnregisterFinishVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E110F9B2433C4AD0059712A /* UnregisterFinishVC.swift */; };
5ED9B2322432517300A24703 /* HelpVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ED9B2312432517300A24703 /* HelpVM.swift */; };
5ED9B237243252DC00A24703 /* HelpCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5ED9B236243252DC00A24703 /* HelpCell.swift */; };
5EE9D815242F74F5002F833C /* DataHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EE9D814242F74F5002F833C /* DataHeaderCell.swift */; };
46F21CA82422444600C01DFA /* ScanListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanListVC.swift; sourceTree = "<group>"; };
46F21CAE2422597F00C01DFA /* Scan.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = "<group>"; };
46F21CB3242270F700C01DFA /* ScannerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScannerStore.swift; sourceTree = "<group>"; };
+ 5E110F9B2433C4AD0059712A /* UnregisterFinishVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnregisterFinishVC.swift; sourceTree = "<group>"; };
5ED9B2312432517300A24703 /* HelpVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpVM.swift; sourceTree = "<group>"; };
5ED9B236243252DC00A24703 /* HelpCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCell.swift; sourceTree = "<group>"; };
5EE9D814242F74F5002F833C /* DataHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataHeaderCell.swift; sourceTree = "<group>"; };
children = (
46A0D529242CC38900FAE9EA /* UnregisterUser.storyboard */,
80C9B102243267EF00CFCDA7 /* UnregisterUserVC.swift */,
+ 5E110F9B2433C4AD0059712A /* UnregisterFinishVC.swift */,
);
path = "Unregister User";
sourceTree = "<group>";
8054C0DD2420AF63008907B8 /* App.swift in Sources */,
805BE9772424DE0E001A93B3 /* BTDevice.swift in Sources */,
46F21CAF2422597F00C01DFA /* Scan.swift in Sources */,
+ 5E110F9C2433C4AD0059712A /* UnregisterFinishVC.swift in Sources */,
8054C0D2241FE720008907B8 /* BT.swift in Sources */,
80AD970D2429318B00AEA661 /* DataCell.swift in Sources */,
80ECB95E24290B6700E57601 /* ScanRealm.swift in Sources */,

diff:
@@ -41,4 +41,10 @@ struct AppSettings {
}
}
+ static func deleteAllData() {
+ AppSettings.BUID = nil
+ AppSettings.state = nil
+ AppSettings.lastUploadDate = nil
+ }
+
}