Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add provider name to provider resource #241

Merged
merged 7 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package project

import com.pulumi.core.Output
import com.pulumi.gcp.compute.kotlin.instance
import com.pulumi.gcp.kotlin.Provider
import com.pulumi.gcp.kotlin.provider
import com.pulumi.gcp.kotlin.GcpProvider
import com.pulumi.gcp.kotlin.gcpProvider
import com.pulumi.kotlin.Pulumi

private val commonTags = listOf("gcp-provider-sample-project", "foo", "bar")
Expand Down Expand Up @@ -51,15 +51,15 @@ fun main() {
}

private suspend fun createProvider(resourceName: String, projectName: String, region: String, zone: String) =
provider(resourceName) {
gcpProvider(resourceName) {
args {
project(projectName)
region(region)
zone(zone)
}
}

private suspend fun createInstanceWithProvider(resourceName: String, provider: Provider, tags: List<String>) =
private suspend fun createInstanceWithProvider(resourceName: String, provider: GcpProvider, tags: List<String>) =
instance(resourceName) {
args {
machineType("e2-micro")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ object IntermediateRepresentationGenerator {
createResource(DEFAULT_PROVIDER_TOKEN, schema.provider, context, typeMap, isProvider = true)
} else {
createResources(typeMap, context)
}.filterNotNull()
}
.filterNotNull()

return IntermediateRepresentation(
types = types,
Expand All @@ -76,12 +77,13 @@ object IntermediateRepresentationGenerator {
fun <V> createTypes(
map: Map<String, V>,
usageKind: UsageKind? = null,
isProvider: Boolean = false,
propertyExtractor: (V) -> RootTypeProperty?,
) = map
.mapValues { propertyExtractor(it.value) }
.filterNotNullValues()
.flatMap { (name, value) ->
createRootTypes(context, name, value, listOfNotNull(usageKind))
createRootTypes(context, name, value, listOfNotNull(usageKind), isProvider)
}

val syntheticTypes = listOf(
Expand All @@ -98,14 +100,16 @@ object IntermediateRepresentationGenerator {
createTypes(
mapOf(DEFAULT_PROVIDER_TOKEN to schema.provider),
UsageKind(Root, Resource, Input),
isProvider = true,
) { resource ->
ObjectProperty(
properties = resource.inputProperties,
description = resource.description,
deprecationMessage = resource.deprecationMessage,
)
}
}.orEmpty(),
}
.orEmpty(),
)

val regularTypes = listOf(
Expand All @@ -117,7 +121,7 @@ object IntermediateRepresentationGenerator {

private fun createResources(types: Map<TypeKey, RootType>, context: Context): List<ResourceType> {
return context.schema.resources.mapNotNull { (typeToken, resource) ->
createResource(typeToken, resource, context, types)
createResource(typeToken, resource, context, types, isProvider = false)
}
}

Expand All @@ -126,7 +130,7 @@ object IntermediateRepresentationGenerator {
resource: SchemaModel.Resource,
context: Context,
types: Map<TypeKey, RootType>,
isProvider: Boolean = false,
isProvider: Boolean,
): ResourceType? {
val resultFields = resource.properties
.letIf(isProvider, ::filterStringProperties)
Expand All @@ -143,7 +147,7 @@ object IntermediateRepresentationGenerator {
}

return try {
val pulumiName = PulumiName.from(typeToken, context.namingConfiguration)
val pulumiName = PulumiName.from(typeToken, context.namingConfiguration, isProvider = isProvider)
val inputUsageKind = UsageKind(Root, Resource, Input)
val argumentType =
findTypeAsReference<ReferencedComplexType>(
Expand All @@ -160,7 +164,7 @@ object IntermediateRepresentationGenerator {
private fun createFunctions(types: Map<TypeKey, RootType>, context: Context): List<FunctionType> {
return context.schema.functions.mapNotNull { (typeName, function) ->
try {
val pulumiName = PulumiName.from(typeName, context.namingConfiguration)
val pulumiName = PulumiName.from(typeName, context.namingConfiguration, isProvider = false)

val inputUsageKind = UsageKind(Root, Function, Input)
val argumentType = findTypeOrEmptyComplexType(
Expand Down Expand Up @@ -201,6 +205,7 @@ object IntermediateRepresentationGenerator {
typeName: String,
rootType: RootTypeProperty,
forcedUsageKinds: List<UsageKind> = emptyList(),
isProvider: Boolean,
): List<RootType> {
val usages = forcedUsageKinds.ifEmpty {
val allUsagesForTypeName = context.referenceFinder.getUsages(typeName)
Expand All @@ -214,7 +219,7 @@ object IntermediateRepresentationGenerator {
}

try {
val pulumiName = PulumiName.from(typeName, context.namingConfiguration)
val pulumiName = PulumiName.from(typeName, context.namingConfiguration, isProvider)
return usages.map { usage ->
when (rootType) {
is ObjectProperty -> ComplexType(
Expand Down Expand Up @@ -302,7 +307,7 @@ object IntermediateRepresentationGenerator {
} else if (context.referencedStringTypesResolver.shouldGenerateStringType(referencedTypeName)) {
StringType
} else {
val pulumiName = PulumiName.from(referencedTypeName, context.namingConfiguration)
val pulumiName = PulumiName.from(referencedTypeName, context.namingConfiguration, isProvider = false)
when (context.referenceFinder.resolve(referencedTypeName)) {
is ObjectProperty -> ReferencedComplexType(
TypeMetadata(pulumiName, usageKind, getKDoc(property)),
Expand Down Expand Up @@ -396,8 +401,11 @@ object IntermediateRepresentationGenerator {
name = with(name) {
PulumiName(
providerName.lowercase(),
namespace.map { it.lowercase() },
providerNameOverride?.lowercase(),
baseNamespace.map { it.lowercase() },
moduleName?.lowercase(),
name.lowercase(),
isProvider = isProvider,
)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,21 @@ import org.virtuslab.pulumikotlin.codegen.utils.decapitalize

data class PulumiName(
val providerName: String,
val namespace: List<String>,
val providerNameOverride: String?,
val baseNamespace: List<String>,
val moduleName: String?,
val name: String,
val isProvider: Boolean,
) {
val namespace: List<String>
get() {
val effectiveProviderName = (providerNameOverride ?: providerName)
val namespaceSections = baseNamespace + effectiveProviderName + moduleName
return namespaceSections
.filterNotNull()
.filter { it.isNotBlank() }
.map { it.replace("-", "") }
}

private data class Modifiers(
val nameSuffix: String,
Expand Down Expand Up @@ -175,19 +187,19 @@ data class PulumiName(
}

fun toFunctionGroupObjectName(namingFlags: NamingFlags): String {
return when (namingFlags.language) {
Kotlin, Java -> {
if (namespace.isEmpty()) {
providerName.capitalize() + "Functions"
} else {
namespace.last().replace(".", "_").capitalize() + "Functions"
}
}
return if (moduleName != null) {
moduleName.replace(".", "_").capitalize() + "Functions"
} else {
getProviderPrefix(namingFlags.language).replace(".", "_").capitalize() + "Functions"
}
}

fun toResourceName(namingFlags: NamingFlags): String {
return name.capitalize()
return if (namingFlags.language == Kotlin && isProvider) {
"${getProviderPrefix(namingFlags.language)}${name.capitalize()}"
} else {
name.capitalize()
}
}

fun toClassName(namingFlags: NamingFlags): String {
Expand All @@ -212,6 +224,14 @@ data class PulumiName(
}
}

private fun getProviderPrefix(languageType: LanguageType): String {
val splitProviderName = providerName.split("-")
return when (languageType) {
Kotlin -> splitProviderName.joinToString("") { it.capitalize() }
Java -> splitProviderName.joinToString("").capitalize()
}
}

private fun packageToString(packageList: List<String>): String {
return packageList.joinToString(".")
}
Expand Down Expand Up @@ -248,44 +268,57 @@ data class PulumiName(
companion object {
private const val EXPECTED_NUMBER_OF_SEGMENTS_IN_TOKEN = 3

fun from(token: String, namingConfiguration: PulumiNamingConfiguration): PulumiName {
fun from(
token: String,
namingConfiguration: PulumiNamingConfiguration,
isProvider: Boolean = false,
): PulumiName {
// token = pkg ":" module ":" member

val segments = token.split(":")

require(segments.size == EXPECTED_NUMBER_OF_SEGMENTS_IN_TOKEN) { "Malformed token $token" }

fun substituteWithOverride(name: String) = namingConfiguration.packageOverrides[name] ?: name
fun substituteWithOverride(name: String) = namingConfiguration.packageOverrides[name]

val module = when (segments[1]) {
"providers" -> ""
"providers" -> null
else -> {
val moduleMatches = namingConfiguration.moduleFormatRegex.matchEntire(segments[1])
?.groupValues
.orEmpty()

if (moduleMatches.size < 2 || moduleMatches[1].startsWith("index")) {
""
null
} else {
moduleMatches[1]
}
}
}

val providerName = substituteWithOverride(namingConfiguration.providerName)
val moduleName = substituteWithOverride(module)

val namespace = (namingConfiguration.baseNamespace + providerName + moduleName)
.filter { it.isNotBlank() }
.map { it.replace("-", "") }
val providerNameOverride = substituteWithOverride(namingConfiguration.providerName)
val moduleName = module?.let { substituteWithOverride(it) } ?: module

val name = segments[2]

if (name.contains("/")) {
val namespace = (
namingConfiguration.baseNamespace +
(providerNameOverride ?: namingConfiguration.providerName) +
moduleName
)
.filterNotNull()
throw InvalidPulumiName(name, namespace)
}

return PulumiName(providerName, namespace, name)
return PulumiName(
namingConfiguration.providerName,
providerNameOverride,
namingConfiguration.baseNamespace,
moduleName,
name,
isProvider,
)
}
}
}
Expand Down
17 changes: 9 additions & 8 deletions src/test/kotlin/org/virtuslab/pulumikotlin/TestUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ internal fun <T> extractOutputValue(output: Output<T>?): T? {
return value
}

internal fun <T> concat(iterableOfIterables: Iterable<Iterable<T>>?): List<T> =
iterableOfIterables?.flatten().orEmpty()

internal fun <T> concat(vararg iterables: Iterable<T>?): List<T> =
concat(iterables.filterNotNull().asIterable())

internal fun namingConfigurationWithSlashInModuleFormat(providerName: String) =
PulumiNamingConfiguration.create(providerName = providerName, moduleFormat = "(.*)(?:/[^/]*)")
internal fun namingConfigurationWithSlashInModuleFormat(
providerName: String,
packageOverrides: Map<String, String> = emptyMap(),
) =
PulumiNamingConfiguration.create(
providerName = providerName,
moduleFormat = "(.*)(?:/[^/]*)",
packageOverrides = packageOverrides,
)

private fun messagePrefix(message: String?) = if (message == null) "" else "$message. "

Expand Down
Loading