From 0a97e65bee58d793f605d50b0da895acc58989dc Mon Sep 17 00:00:00 2001 From: Steve Jensen Date: Thu, 23 Nov 2023 09:40:37 -0600 Subject: [PATCH] Twilio Trunk Provision --- .../cleo/chimesma/cdk/InfrastructureApp.java | 22 ++-- .../chimesma/cdk/InfrastructureStack.java | 8 +- .../cloud/cleo/chimesma/cdk/TwilioStack.java | 20 ++-- .../customresources/ChimeVoiceConnector.java | 11 +- .../cleo/chimesma/cdk/twilio/TwilioBase.java | 21 ++-- .../cdk/twilio/TwilioOriginationUrl.java | 45 ++++++++ .../cleo/chimesma/cdk/twilio/TwilioRule.java | 35 ------ .../chimesma/cdk/twilio/TwilioSipTrunk.java | 13 ++- .../cdk/twilio/TwilioOriginationUrl.java | 102 ++++++++++++++++++ .../cleo/chimesma/cdk/twilio/TwilioRule.java | 52 --------- .../chimesma/cdk/twilio/TwilioSipTrunk.java | 76 ++++--------- 11 files changed, 228 insertions(+), 177 deletions(-) create mode 100644 src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java delete mode 100644 src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java create mode 100644 twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java delete mode 100644 twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java diff --git a/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureApp.java b/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureApp.java index b3564b4..d192bdd 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureApp.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureApp.java @@ -18,10 +18,6 @@ public enum ENV_VARS { * If set in the environment, setup Origination to point to Voice Connector and allow from termination as well */ PBX_HOSTNAME, - /** - * Provision Twilio SIP Trunk (experimental) - */ - TWILIO, /** * Attempt to provision a phone number in this area code (US only and experimental) */ @@ -37,7 +33,13 @@ public enum ENV_VARS { /** * Single IP address to allow to call the Voice Connector (Cannot be private range or will fail) */ - VOICE_CONNECTOR_ALLOW_IP + VOICE_CONNECTOR_ALLOW_IP, + + /** + * Twilio Keys, provisions SIP Trunk if both present + */ + TWILIO_ACCOUNT_SID, + TWILIO_AUTH_TOKEN } public static void main(final String[] args) { @@ -64,13 +66,13 @@ public static void main(final String[] args) { .env(makeStackEnv(accountId, regionWest)) .build()); - if (hasEnv(TWILIO)) { + if (hasTwilio()) { new TwilioStack(app, "twilio", StackProps.builder() - .description("Provision Twilio Resources") + .description("Provision Twilio Sip Trunk") .stackName(stackName + "-twilio") .env(makeStackEnv(accountId, regionEast)) .crossRegionReferences(Boolean.TRUE) - .build(), east.getVCHostName(), west.getVCHostName()); + .build(), east.getVoiceConnector(), west.getVoiceConnector()); } // Provision Chime Phone Number if area code provided @@ -88,6 +90,10 @@ public static void main(final String[] args) { } + public static boolean hasTwilio() { + return hasEnv(TWILIO_ACCOUNT_SID) && hasEnv(TWILIO_AUTH_TOKEN); + } + /** * Get the value for one of the ENV variables * @param envVar diff --git a/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureStack.java b/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureStack.java index 3b7e00b..7dbeb1b 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureStack.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/InfrastructureStack.java @@ -59,7 +59,7 @@ public InfrastructureStack(final App app, final String id, final StackProps prop String vc_arn = "PSTN"; - if ( hasEnv(VOICE_CONNECTOR,PBX_HOSTNAME) ) { + if ( hasEnv(VOICE_CONNECTOR,PBX_HOSTNAME,TWILIO_ACCOUNT_SID) ) { // Voice Connector vc = new ChimeVoiceConnector(this); @@ -98,12 +98,12 @@ public InfrastructureStack(final App app, final String id, final StackProps prop } /** - * Voice Connector Host Name + * Voice Connector or null if it was never created * * @return */ - public String getVCHostName() { - return vc == null ? "N/A" : vc.getOutboundName(); + public ChimeVoiceConnector getVoiceConnector() { + return vc; } /** diff --git a/src/main/java/cloud/cleo/chimesma/cdk/TwilioStack.java b/src/main/java/cloud/cleo/chimesma/cdk/TwilioStack.java index c11f9a2..8f3eb35 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/TwilioStack.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/TwilioStack.java @@ -1,5 +1,6 @@ package cloud.cleo.chimesma.cdk; +import cloud.cleo.chimesma.cdk.customresources.ChimeVoiceConnector; import cloud.cleo.chimesma.cdk.twilio.*; import software.amazon.awscdk.App; import software.constructs.Construct; @@ -7,22 +8,25 @@ import software.amazon.awscdk.StackProps; /** - * CDK Stack + * CDK Stack * * @author sjensen */ public class TwilioStack extends Stack { - - public TwilioStack(final App parent, final String id, String vc1, String vc2) { - this(parent, id, null,vc1,vc2); + public TwilioStack(final App parent, final String id, ChimeVoiceConnector vc1, ChimeVoiceConnector vc2) { + this(parent, id, null, vc1, vc2); } - public TwilioStack(final Construct parent, final String id, final StackProps props, String vc1, String vc2) { + public TwilioStack(final Construct parent, final String id, final StackProps props, ChimeVoiceConnector vc1, ChimeVoiceConnector vc2) { super(parent, id, props); - - new TwilioSipTrunk(this,vc1, vc2); - new TwilioRule(this); + + // Create the Trunk + final var sipTrunk = new TwilioSipTrunk(this); + + // Set the Orig entries to the VC's + new TwilioOriginationUrl(this, sipTrunk.getSid(), vc1); + new TwilioOriginationUrl(this, sipTrunk.getSid(), vc2); } } diff --git a/src/main/java/cloud/cleo/chimesma/cdk/customresources/ChimeVoiceConnector.java b/src/main/java/cloud/cleo/chimesma/cdk/customresources/ChimeVoiceConnector.java index 82d9bdd..3924680 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/customresources/ChimeVoiceConnector.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/customresources/ChimeVoiceConnector.java @@ -22,6 +22,7 @@ import static cloud.cleo.chimesma.cdk.InfrastructureApp.ENV_VARS.*; import static cloud.cleo.chimesma.cdk.InfrastructureApp.getEnv; import static cloud.cleo.chimesma.cdk.InfrastructureApp.hasEnv; +import static cloud.cleo.chimesma.cdk.InfrastructureApp.hasTwilio; import java.util.ArrayList; /** @@ -32,6 +33,8 @@ public class ChimeVoiceConnector extends AwsCustomResource { private final static String ID = "VC-CR"; + private final String region; + /** * The Voice Connector ID in the API response */ @@ -57,6 +60,8 @@ public ChimeVoiceConnector(Stack scope) { .logRetention(RetentionDays.ONE_MONTH) .build()); + region = scope.getRegion(); + /** * // Don't enable SIP logging on VC, This can be done manually SIP Logs final var logging = new * AwsCustomResource(scope, ID + "-LOG", AwsCustomResourceProps.builder() @@ -73,7 +78,7 @@ public ChimeVoiceConnector(Stack scope) { var termAllow = new ArrayList(); // Add Twilio - if (hasEnv(PBX_HOSTNAME, TWILIO)) { + if (hasEnv(PBX_HOSTNAME) || hasTwilio() ) { // Start with list of Twilio NA ranges for SIP Trunking termAllow.add(AclCidr.ipv4("54.172.60.0/30")); termAllow.add(AclCidr.ipv4("54.244.51.0/30")); @@ -145,6 +150,10 @@ public String getArn() { public String getOutboundName() { return getResponseField("VoiceConnector.OutboundHostName"); } + + public String getRegion() { + return region; + } /** * Required parameters for the CreateVoiceConnectorCommand API call diff --git a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioBase.java b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioBase.java index bbba3ff..bb0b409 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioBase.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioBase.java @@ -7,6 +7,7 @@ import java.util.Arrays; import static java.util.Collections.singletonList; import java.util.List; +import java.util.Map; import software.amazon.awscdk.BundlingOptions; import software.amazon.awscdk.BundlingOutput; import software.amazon.awscdk.DockerVolume; @@ -18,6 +19,9 @@ import static software.amazon.awscdk.services.lambda.Runtime.*; import software.amazon.awscdk.services.logs.RetentionDays; import software.amazon.awscdk.services.s3.assets.AssetOptions; +import static cloud.cleo.chimesma.cdk.InfrastructureApp.ENV_VARS.*; +import cloud.cleo.chimesma.cdk.InfrastructureApp; +import java.util.concurrent.atomic.AtomicInteger; /** * Base class for all Twilio Custom Resource Lambda's @@ -26,16 +30,16 @@ */ public abstract class TwilioBase extends Function { - + private static final AtomicInteger ID_COUNTER = new AtomicInteger(0); private static final BundlingOptions builderOptions; static { List functionOnePackagingInstructions = Arrays.asList( "/bin/sh", "-c", - "mvn clean install && cp /asset-input/target/twilio.jar /asset-output/"); + "mvn clean install && cp /asset-input/target/twilio.jar /asset-output/"); - builderOptions = BundlingOptions.builder() + builderOptions = BundlingOptions.builder() .command(functionOnePackagingInstructions) .image(JAVA_17.getBundlingImage()) .user("root") @@ -48,25 +52,28 @@ public abstract class TwilioBase extends Function { * @param scope */ protected TwilioBase(Stack scope, Class c) { - super(scope, c.getSimpleName(), FunctionProps.builder() + super(scope, c.getSimpleName() + ID_COUNTER.incrementAndGet(), FunctionProps.builder() .handler(c.getName()) .runtime(JAVA_17) .description(c.getSimpleName() + " Provisioning Lambda") .timeout(Duration.seconds(30)) .logRetention(RetentionDays.ONE_MONTH) .maxEventAge(Duration.seconds(60)) - .timeout(Duration.seconds(30)) + .timeout(Duration.minutes(5)) .retryAttempts(0) .memorySize(512) .code(getCode()) + .environment(Map.of(TWILIO_ACCOUNT_SID.toString(), InfrastructureApp.getEnv(TWILIO_ACCOUNT_SID), + TWILIO_AUTH_TOKEN.toString(), InfrastructureApp.getEnv(TWILIO_AUTH_TOKEN))) .build()); - } - + protected static Code getCode() { return Code.fromAsset("./twilio", AssetOptions.builder() .bundling(builderOptions).build()); } + + public abstract String getSid(); } diff --git a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java new file mode 100644 index 0000000..7dd6a5a --- /dev/null +++ b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java @@ -0,0 +1,45 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package cloud.cleo.chimesma.cdk.twilio; + +import cloud.cleo.chimesma.cdk.customresources.ChimeVoiceConnector; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import software.amazon.awscdk.CustomResource; +import software.amazon.awscdk.CustomResourceProps; +import software.amazon.awscdk.Stack; + +/** + * Twilio SIP Trunk Function that will provision + * + * @author sjensen + */ +public class TwilioOriginationUrl extends TwilioBase { + + private static final AtomicInteger ID_COUNTER = new AtomicInteger(0); + final CustomResource cr; + + /** + * @param scope + * @param trunkSid + * @param vc + */ + public TwilioOriginationUrl(Stack scope, String trunkSid, ChimeVoiceConnector vc) { + super(scope, TwilioOriginationUrl.class); + + // Add associated Custom Resource linked to this Lambda + cr = new CustomResource(this, "SipOrigUrlResource"+ ID_COUNTER.incrementAndGet(), CustomResourceProps.builder() + .resourceType("Custom::" + TwilioOriginationUrl.class.getSimpleName()) + .properties(Map.of("trunkSid", trunkSid, "voiceConnector", vc.getOutboundName(),"region",vc.getRegion())) + .serviceToken(getFunctionArn()) + .build()); + + } + + @Override + public String getSid() { + return cr.getRef(); + } +} diff --git a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java deleted file mode 100644 index de1e8b0..0000000 --- a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license - * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template - */ -package cloud.cleo.chimesma.cdk.twilio; - -import java.util.Map; -import software.amazon.awscdk.CustomResource; -import software.amazon.awscdk.CustomResourceProps; -import software.amazon.awscdk.Stack; - -/** - * Twilio SIP Trunk Function that will provision - * - * @author sjensen - */ -public class TwilioRule extends TwilioBase { - - - /** - * @param scope - */ - public TwilioRule(Stack scope) { - super(scope, TwilioRule.class); - - // Add associated Custom Resource linked to this Lambda - new CustomResource(this, "SipRuleResource", CustomResourceProps.builder() - .resourceType("Custom::" + TwilioRule.class.getSimpleName()) - .serviceToken(getFunctionArn()) - .build()); - - } - - -} diff --git a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java index 10025c0..25ed56d 100644 --- a/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java +++ b/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java @@ -4,7 +4,6 @@ */ package cloud.cleo.chimesma.cdk.twilio; -import java.util.Map; import software.amazon.awscdk.CustomResource; import software.amazon.awscdk.CustomResourceProps; import software.amazon.awscdk.Stack; @@ -16,21 +15,25 @@ */ public class TwilioSipTrunk extends TwilioBase { + final CustomResource cr; /** * @param scope */ - public TwilioSipTrunk(Stack scope, String vc1, String vc2) { + public TwilioSipTrunk(Stack scope) { super(scope, TwilioSipTrunk.class); // Add associated Custom Resource linked to this Lambda - new CustomResource(this, "SipTrunkResource", CustomResourceProps.builder() + cr = new CustomResource(this, "SipTrunkResource", CustomResourceProps.builder() .resourceType("Custom::" + TwilioSipTrunk.class.getSimpleName()) - .properties(Map.of("vcEast",vc1,"vcWest",vc2,"vcEastRegion","us-east-1","vcWestRegion","us-east-2")) .serviceToken(getFunctionArn()) .build()); } - + + @Override + public String getSid() { + return cr.getRef(); + } } diff --git a/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java b/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java new file mode 100644 index 0000000..ff7ad69 --- /dev/null +++ b/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioOriginationUrl.java @@ -0,0 +1,102 @@ +package cloud.cleo.chimesma.cdk.twilio; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; +import com.twilio.Twilio; +import com.twilio.rest.trunking.v1.trunk.OriginationUrl; +import java.net.URI; +import java.util.UUID; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; +import software.amazon.lambda.powertools.cloudformation.Response; + +/** + * + * @author sjensen + */ +public class TwilioOriginationUrl extends AbstractCustomResourceHandler { + + // Initialize the Log4j logger. + static final Logger log = LogManager.getLogger(TwilioOriginationUrl.class); + + static { + Twilio.init(System.getenv("TWILIO_ACCOUNT_SID"), System.getenv("TWILIO_AUTH_TOKEN")); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent cfcre, Context cntxt) { + log.debug("Received CREATE Event from Cloudformation", cfcre); + + var sid = UUID.randomUUID().toString(); + + try { + var props = cfcre.getResourceProperties(); + + final var trunkSid = props.get("trunkSid").toString(); + final var voiceConnector = props.get("voiceConnector").toString(); + final var region = props.get("region").toString(); + + final var edge = switch(region) { + case "us-east-1" -> ";edge=ashburn"; + case "us-west-2" -> ";edge=umatilla"; + default -> ""; + }; + + final Integer priority = switch(region) { + case "us-east-1" -> 1; + case "us-west-2" -> 2; + default -> 10; + }; + + sid = OriginationUrl.creator( + trunkSid, + 10, + priority, + true, + "Chime Voice " + region, + URI.create("sip:" + voiceConnector + edge)) + .create().getSid(); + + log.debug("Orig URL created with SID " + sid); + + } catch (Exception e) { + log.error("Create Error", e); + return Response.failed(sid); + } + return Response.success(sid); + } + + @Override + protected Response update(CloudFormationCustomResourceEvent cfcre, Context cntxt) { + log.debug("Received UPDATE Event from Cloudformation", cfcre); + + + // No Update support, we can return null + return null; + } + + @Override + protected Response delete(CloudFormationCustomResourceEvent cfcre, Context cntxt) { + log.debug("Received DELETE Event from Cloudformation", cfcre); + + final var sid = cfcre.getPhysicalResourceId(); + final var trunkSid = cfcre.getResourceProperties().get("trunkSid").toString(); + log.debug("Deleting Orig URL SID " + sid); + try { + + if (!OriginationUrl.deleter(trunkSid,sid).delete()) { + throw new RuntimeException("Could Not Delete Orig Url"); + } + + log.debug("Orig URL deleted with SID " + sid); + + } catch (Exception e) { + log.error("Delete Error", e); + return Response.failed(sid); + } + + return Response.success(sid); + } + +} diff --git a/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java b/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java deleted file mode 100644 index b6482e0..0000000 --- a/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java +++ /dev/null @@ -1,52 +0,0 @@ -package cloud.cleo.chimesma.cdk.twilio; - - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; -import java.util.Map; -import java.util.UUID; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; -import software.amazon.lambda.powertools.cloudformation.Response; - -/** - * - * @author sjensen - */ -public class TwilioRule extends AbstractCustomResourceHandler { - - // Initialize the Log4j logger. - static final Logger log = LogManager.getLogger(TwilioRule.class); - - @Override - protected Response create(CloudFormationCustomResourceEvent cfcre, Context cntxt) { - log.debug("Received CREATE Event from Cloudformation", cfcre); - - final var sid = UUID.randomUUID().toString(); - log.debug("SIP Rule created with SID " + sid); - - return Response.builder() - .value(Map.of("operation", "success")) - .physicalResourceId(sid) - .build(); - } - - @Override - protected Response update(CloudFormationCustomResourceEvent cfcre, Context cntxt) { - log.debug("Received UPDATE Event from Cloudformation", cfcre); - // No Update support, we can return null - return null; - } - - @Override - protected Response delete(CloudFormationCustomResourceEvent cfcre, Context cntxt) { - log.debug("Received DELETE Event from Cloudformation", cfcre); - log.debug("Deleting SID " + cfcre.getPhysicalResourceId()); - - return Response.builder() - .value(Map.of("operation", "success")) - .build(); - } - -} diff --git a/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java b/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java index 267ef99..6b42960 100644 --- a/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java +++ b/twilio/src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java @@ -4,9 +4,7 @@ import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; import com.twilio.Twilio; import com.twilio.rest.trunking.v1.Trunk; -import com.twilio.rest.trunking.v1.trunk.OriginationUrl; -import java.net.URI; -import java.util.Map; +import java.util.UUID; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; @@ -21,91 +19,55 @@ public class TwilioSipTrunk extends AbstractCustomResourceHandler { // Initialize the Log4j logger. static final Logger log = LogManager.getLogger(TwilioSipTrunk.class); + static { + Twilio.init(System.getenv("TWILIO_ACCOUNT_SID"), System.getenv("TWILIO_AUTH_TOKEN")); + } + @Override protected Response create(CloudFormationCustomResourceEvent cfcre, Context cntxt) { log.debug("Received CREATE Event from Cloudformation", cfcre); - String sid = null; - + var sid = UUID.randomUUID().toString(); try { - Trunk trunk = Trunk.creator() - .setFriendlyName(cfcre.getStackId()) + final var trunk = Trunk.creator() + .setFriendlyName("Chime VoiceConnector") .create(); sid = trunk.getSid(); - - var props = cfcre.getResourceProperties(); - - OriginationUrl.creator( - sid, - 10, - 10, - true, - "Chime Voice " + props.get("vcEastRegion"), - URI.create("sip:" + props.get("vcEast") + ";edge=ashburn")) - .create(); - - - OriginationUrl.creator( - sid, - 10, - 10, - true, - "Chime Voice " + props.get("vcWestRegion"), - URI.create("sip:" + props.get("vcWest") + ";edge=umatilla")) - .create(); - - - log.debug("SIP Trunk created with SID " + sid); - } catch (Exception e) { - log.error("Create Error",e); - return Response.builder() - .status(Response.Status.FAILED) - .value(e.getMessage()) - .build(); + log.error("Create Error", e); + return Response.failed(sid); } - return Response.builder() - .value(Map.of("operation", "success")) - .physicalResourceId(sid) - .build(); + return Response.success(sid); } @Override protected Response update(CloudFormationCustomResourceEvent cfcre, Context cntxt) { log.debug("Received UPDATE Event from Cloudformation", cfcre); - // No Update support, we can return null - return null; + return Response.success(cfcre.getPhysicalResourceId()); } @Override protected Response delete(CloudFormationCustomResourceEvent cfcre, Context cntxt) { log.debug("Received DELETE Event from Cloudformation", cfcre); - log.debug("Deleting SID " + cfcre.getPhysicalResourceId()); + final var sid = cfcre.getPhysicalResourceId(); + log.debug("Deleting SID " + sid); try { - - - if (!Trunk.deleter(cfcre.getPhysicalResourceId()).delete()) { + if (!Trunk.deleter(sid).delete()) { throw new RuntimeException("Could Not Delete SIP Trunk"); } - - log.debug("SIP Trunk deleted with SID " + cfcre.getPhysicalResourceId()); + log.debug("SIP Trunk deleted with SID " + sid); } catch (Exception e) { - log.error("Delete Error",e); - return Response.builder() - .status(Response.Status.FAILED) - .value(e.getMessage()) - .build(); + log.error("Delete Error", e); + return Response.failed(sid); } - return Response.builder() - .value(Map.of("operation", "success")) - .build(); + return Response.success(sid); } }