Skip to content

Commit 6c01505

Browse files
authored
SAM Lambda ARM support (#2997)
1 parent a5a4c38 commit 6c01505

34 files changed

+477
-77
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "feature",
3+
"description" : "Add SAM Lambda ARM support"
4+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.core.lambda
5+
6+
import software.amazon.awssdk.services.lambda.model.Architecture
7+
8+
enum class LambdaArchitecture(
9+
private val architecture: Architecture,
10+
val minSam: String? = null,
11+
) {
12+
X86_64(Architecture.X86_64),
13+
ARM64(Architecture.ARM64, minSam = "1.33.0");
14+
15+
override fun toString() = architecture.toString()
16+
17+
fun toSdkArchitecture() = architecture.validOrNull
18+
19+
companion object {
20+
fun fromValue(value: String?): LambdaArchitecture? = if (value == null) {
21+
null
22+
} else {
23+
values().find { it.toString() == value }
24+
}
25+
26+
fun fromValue(value: Architecture): LambdaArchitecture? = values().find { it.architecture == value }
27+
28+
val DEFAULT = X86_64
29+
val ARM_COMPATIBLE = listOf(X86_64, ARM64)
30+
}
31+
}

core/src/software/aws/toolkits/core/lambda/LambdaRuntime.kt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
package software.aws.toolkits.core.lambda
55

66
import software.amazon.awssdk.services.lambda.model.Runtime
7+
import software.aws.toolkits.core.lambda.LambdaArchitecture.Companion.ARM_COMPATIBLE
78

89
enum class LambdaRuntime(
910
private val runtime: Runtime?,
1011
val minSamInit: String? = null,
1112
val minSamDebugging: String? = null,
13+
val architectures: List<LambdaArchitecture>? = listOf(LambdaArchitecture.DEFAULT),
1214
private val runtimeOverride: String? = null
1315
) {
1416
GO1_X(
@@ -17,15 +19,15 @@ enum class LambdaRuntime(
1719
// and 1.17.0 broke the arguments
1820
minSamDebugging = "1.18.1"
1921
),
20-
NODEJS12_X(Runtime.NODEJS12_X),
21-
NODEJS14_X(Runtime.NODEJS14_X, minSamDebugging = "1.17.0", minSamInit = "1.17.0"),
22+
NODEJS12_X(Runtime.NODEJS12_X, architectures = ARM_COMPATIBLE),
23+
NODEJS14_X(Runtime.NODEJS14_X, minSamDebugging = "1.17.0", minSamInit = "1.17.0", architectures = ARM_COMPATIBLE),
2224
JAVA8(Runtime.JAVA8),
23-
JAVA8_AL2(Runtime.JAVA8_AL2, minSamDebugging = "1.2.0"),
24-
JAVA11(Runtime.JAVA11),
25+
JAVA8_AL2(Runtime.JAVA8_AL2, minSamDebugging = "1.2.0", architectures = ARM_COMPATIBLE),
26+
JAVA11(Runtime.JAVA11, architectures = ARM_COMPATIBLE),
2527
PYTHON3_6(Runtime.PYTHON3_6),
2628
PYTHON3_7(Runtime.PYTHON3_7),
27-
PYTHON3_8(Runtime.PYTHON3_8),
28-
PYTHON3_9(Runtime.PYTHON3_9, minSamDebugging = "1.28.0", minSamInit = "1.28.0"),
29+
PYTHON3_8(Runtime.PYTHON3_8, architectures = ARM_COMPATIBLE),
30+
PYTHON3_9(Runtime.PYTHON3_9, minSamDebugging = "1.28.0", minSamInit = "1.28.0", architectures = ARM_COMPATIBLE),
2931
DOTNETCORE3_1(Runtime.DOTNETCORE3_1),
3032
DOTNET5_0(null, minSamInit = "1.16.0", runtimeOverride = "dotnet5.0");
3133

core/src/software/aws/toolkits/core/lambda/LambdaUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
package software.aws.toolkits.core.lambda
55

6+
import software.amazon.awssdk.services.lambda.model.Architecture
67
import software.amazon.awssdk.services.lambda.model.Runtime
78

89
val Runtime?.validOrNull: Runtime? get() = this?.takeUnless { it == Runtime.UNKNOWN_TO_SDK_VERSION }
10+
val Architecture?.validOrNull: Architecture? get() = this?.takeUnless { it == Architecture.UNKNOWN_TO_SDK_VERSION }

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/CloudFormationTemplate.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.VirtualFile
99
import com.intellij.psi.PsiElement
1010
import org.jetbrains.yaml.YAMLFileType
1111
import org.jetbrains.yaml.YAMLLanguage
12+
import org.jetbrains.yaml.psi.YAMLSequence
1213
import software.aws.toolkits.jetbrains.services.cloudformation.yaml.YamlCloudFormationTemplate
1314
import software.aws.toolkits.resources.message
1415
import java.io.File
@@ -51,6 +52,8 @@ interface NamedMap {
5152
fun getScalarProperty(key: String): String
5253
fun getOptionalScalarProperty(key: String): String?
5354
fun setScalarProperty(key: String, value: String)
55+
fun getSequenceProperty(key: String): YAMLSequence
56+
fun getOptionalSequenceProperty(key: String): YAMLSequence?
5457
}
5558

5659
interface Resource : NamedMap {
@@ -96,6 +99,14 @@ class MutableParameter(private val copyFrom: Parameter) : Parameter {
9699
throw NotImplementedError()
97100
}
98101

102+
override fun getSequenceProperty(key: String): YAMLSequence {
103+
throw NotImplementedError()
104+
}
105+
106+
override fun getOptionalSequenceProperty(key: String): YAMLSequence? {
107+
throw NotImplementedError()
108+
}
109+
99110
override fun defaultValue(): String? = defaultValue
100111

101112
override fun description(): String? = description

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/Resources.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package software.aws.toolkits.jetbrains.services.cloudformation
55

66
import software.amazon.awssdk.services.lambda.model.PackageType
7+
import software.aws.toolkits.jetbrains.services.cloudformation.yaml.YamlCloudFormationTemplate.Companion.getTextValues
78
import software.aws.toolkits.resources.message
89

910
interface Function : Resource {
@@ -17,6 +18,7 @@ interface Function : Resource {
1718

1819
fun runtime(): String = getScalarProperty("Runtime")
1920
fun handler(): String = getScalarProperty("Handler")
21+
fun architectures(): List<String>? = getOptionalSequenceProperty("Architectures")?.getTextValues()
2022
fun timeout(): Int? = getOptionalScalarProperty("Timeout")?.toInt()
2123
fun memorySize(): Int? = getOptionalScalarProperty("MemorySize")?.toInt()
2224
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/cloudformation/yaml/YamlCloudFormationTemplate.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import org.jetbrains.yaml.YAMLLanguage
1515
import org.jetbrains.yaml.psi.YAMLFile
1616
import org.jetbrains.yaml.psi.YAMLKeyValue
1717
import org.jetbrains.yaml.psi.YAMLMapping
18+
import org.jetbrains.yaml.psi.YAMLScalar
19+
import org.jetbrains.yaml.psi.YAMLSequence
1820
import software.aws.toolkits.core.utils.debug
1921
import software.aws.toolkits.core.utils.getLogger
2022
import software.aws.toolkits.jetbrains.services.cloudformation.CloudFormationParameter
@@ -77,6 +79,12 @@ class YamlCloudFormationTemplate(template: YAMLFile) : CloudFormationTemplate {
7779
override fun setScalarProperty(key: String, value: String) {
7880
throw NotImplementedError()
7981
}
82+
83+
override fun getSequenceProperty(key: String): YAMLSequence = getOptionalSequenceProperty(key)
84+
?: throw IllegalStateException(message("cloudformation.missing_property", key, logicalName))
85+
86+
override fun getOptionalSequenceProperty(key: String): YAMLSequence? = delegate.getKeyValueByKey(key)
87+
?.children?.filterIsInstance<YAMLSequence>()?.firstOrNull()
8088
}
8189

8290
private class YamlResource(
@@ -102,6 +110,12 @@ class YamlCloudFormationTemplate(template: YAMLFile) : CloudFormationTemplate {
102110
properties().putKeyValue(newKeyValue)
103111
}
104112

113+
override fun getSequenceProperty(key: String): YAMLSequence = getOptionalSequenceProperty(key)
114+
?: throw IllegalStateException(message("cloudformation.missing_property", key, logicalName))
115+
116+
override fun getOptionalSequenceProperty(key: String): YAMLSequence? =
117+
properties().getKeyValueByKey(key)?.children?.filterIsInstance<YAMLSequence>()?.firstOrNull()
118+
105119
override fun getScalarMetadata(key: String): String = getOptionalScalarMetadata(key)
106120
?: throw IllegalStateException(message("cloudformation.missing_property", key, logicalName))
107121

@@ -124,6 +138,11 @@ class YamlCloudFormationTemplate(template: YAMLFile) : CloudFormationTemplate {
124138
override fun setScalarProperty(key: String, value: String) {
125139
throw NotImplementedError()
126140
}
141+
142+
override fun getSequenceProperty(key: String): YAMLSequence = getOptionalSequenceProperty(key)
143+
?: throw IllegalStateException(message("cloudformation.missing_property", key, logicalName))
144+
override fun getOptionalSequenceProperty(key: String): YAMLSequence? = delegate.getKeyValueByKey(key)
145+
?.children?.filterIsInstance<YAMLSequence>()?.firstOrNull()
127146
}
128147

129148
companion object {
@@ -144,6 +163,8 @@ class YamlCloudFormationTemplate(template: YAMLFile) : CloudFormationTemplate {
144163
return yamlKeyValue.asResource(YamlCloudFormationTemplate(yamlKeyValue.containingFile as YAMLFile))
145164
}
146165

166+
fun YAMLSequence.getTextValues(): List<String> = this.items.map { it.value }.filterIsInstance<YAMLScalar>().map { it.textValue }
167+
147168
private fun YAMLKeyValue.asResource(cloudFormationTemplate: CloudFormationTemplate): Resource? {
148169
if (PsiTreeUtil.getParentOfType(this, YAMLKeyValue::class.java)?.keyText == "Resources") {
149170
val yamlValue = this.value as? YAMLMapping ?: return null

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/Lambda.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import software.amazon.awssdk.services.lambda.model.FunctionConfiguration
1616
import software.amazon.awssdk.services.lambda.model.PackageType
1717
import software.amazon.awssdk.services.lambda.model.Runtime
1818
import software.amazon.awssdk.services.lambda.model.TracingMode
19+
import software.aws.toolkits.core.lambda.LambdaRuntime
1920
import software.aws.toolkits.core.utils.debug
2021
import software.aws.toolkits.core.utils.getLogger
2122
import software.aws.toolkits.jetbrains.services.iam.IamRole
@@ -32,6 +33,10 @@ import software.aws.toolkits.jetbrains.ui.SliderPanel
3233
object Lambda {
3334
private val LOG = getLogger<Lambda>()
3435

36+
fun findPsiElementsForHandler(project: Project, runtime: LambdaRuntime, handler: String): Array<NavigatablePsiElement> {
37+
runtime.toSdkRuntime()?.let { return findPsiElementsForHandler(project, it, handler) } ?: return emptyArray()
38+
}
39+
3540
fun findPsiElementsForHandler(project: Project, runtime: Runtime, handler: String): Array<NavigatablePsiElement> {
3641
val resolver = runtime.runtimeGroup?.let { LambdaHandlerResolver.getInstanceOrNull(it) } ?: return emptyArray()
3742

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/LambdaBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ abstract class LambdaBuilder {
4747
SamTemplateUtils.writeDummySamTemplate(
4848
tempFile = dummyTemplate,
4949
logicalId = dummyLogicalId,
50-
runtime = runtime,
50+
runtime = runtime.toSdkRuntime() ?: throw IllegalStateException("Cannot map runtime $runtime to SDK runtime."),
51+
architecture = settings.architecture.toSdkArchitecture(),
5152
handler = handlerForDummyTemplate(settings, element),
5253
timeout = settings.timeout,
5354
memorySize = settings.memorySize,

jetbrains-core/src/software/aws/toolkits/jetbrains/services/lambda/LambdaUtils.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package software.aws.toolkits.jetbrains.services.lambda
55

66
import com.intellij.util.text.SemVer
7+
import software.aws.toolkits.core.lambda.LambdaArchitecture
78
import software.aws.toolkits.core.lambda.LambdaRuntime
89
import software.aws.toolkits.jetbrains.services.lambda.sam.SamExecutable
910

@@ -14,3 +15,7 @@ fun LambdaRuntime.minSamDebuggingVersion(): SemVer =
1415
fun LambdaRuntime.minSamInitVersion(): SemVer =
1516
minSamInit?.let { SemVer.parseFromText(it) ?: throw IllegalStateException("$this has bad minSamInitVersion! It should be a semver string!") }
1617
?: SamExecutable.minVersion
18+
19+
fun LambdaArchitecture.minSamVersion(): SemVer =
20+
minSam?.let { SemVer.parseFromText(it) ?: throw IllegalStateException("$this has bad minSamInitVersion! It should be a semver string!") }
21+
?: SamExecutable.minVersion

0 commit comments

Comments
 (0)