Skip to content

Commit

Permalink
Aliases support
Browse files Browse the repository at this point in the history
  • Loading branch information
PawelGizka1 committed Jul 9, 2024
1 parent 7429ff0 commit 648ec22
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 40 deletions.
48 changes: 48 additions & 0 deletions core/src/main/scala/besom/internal/ResourceAlias.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package besom.internal

/** Allows to specify details of parent of resource for alias.
*/
sealed trait ResourceAliasParent

/** Allows to specify urn of parent.
* @param urn
* of parent
*/
final case class ResourceAliasParentUrn(urn: String) extends ResourceAliasParent

/** Allows to indicate that resource previously had no parent. This property is ignored when set to false.
* @param noParent
* set to true when no parent
*/
final case class ResourceAliasNoParent(noParent: Boolean) extends ResourceAliasParent

/** The alias for a resource or component resource. It can be any combination of the old name, type, parent, stack, and/or project values.
* Alternatively, you can just specify the URN directly.
*/
sealed trait ResourceAlias

/** Allows to specify urn of resource.
* @param urn
* of resource
*/
final case class UrnResourceAlias(urn: String) extends ResourceAlias

/** Allows to specify any combination of old name, type, parent, stack, and/or project values.
* @param name
* of the old resource
* @param `type`
* of the old resource
* @param stack
* of the old resource
* @param project
* of the old resource
* @param parent
* of the old resource
*/
final case class SpecResourceAlias(
name: Option[String] = None,
`type`: Option[String] = None,
stack: Option[String] = None,
project: Option[String] = None,
parent: Option[ResourceAliasParent] = None
) extends ResourceAlias
37 changes: 28 additions & 9 deletions core/src/main/scala/besom/internal/ResourceOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ class ResourceOps(using ctx: Context, mdc: BesomMDC[Label]):
providerId: Option[String],
providerRefs: Map[String, String],
depUrns: AggregatedDependencyUrns,
aliases: List[String],
aliases: List[ResourceAlias],
options: ResolvedResourceOptions
)

Expand All @@ -349,9 +349,6 @@ class ResourceOps(using ctx: Context, mdc: BesomMDC[Label]):
private[internal] def resolveDeletedWithUrn(options: ResolvedResourceOptions): Result[Option[URN]] =
options.deletedWith.map(_.urn.getValue).getOrElse(Result.pure(None))

private[internal] def resolveAliases(@unused resource: Resource): Result[List[String]] =
Result.pure(List.empty) // TODO aliases

private[internal] def resolveProviderRegistrationId(state: ResourceState): Result[Option[String]] =
state match
case prs: ProviderResourceState =>
Expand Down Expand Up @@ -388,10 +385,17 @@ class ResourceOps(using ctx: Context, mdc: BesomMDC[Label]):
providerRefs <- resolveProviderReferences(state)
_ <- log.trace(s"Preparing inputs: resolved provider refs, aggregating dep URNs")
depUrns <- aggregateDependencyUrns(directDeps, serResult.propertyToDependentResources, ctx.resources)
_ <- log.trace(s"Preparing inputs: aggregated dep URNs, resolving aliases")
aliases <- resolveAliases(resource)
_ <- log.trace(s"Preparing inputs: resolved aliases, done")
yield PreparedInputs(serResult.serialized, parentUrnOpt, deletedWithUrnOpt, provIdOpt, providerRefs, depUrns, aliases, options)
yield PreparedInputs(
serResult.serialized,
parentUrnOpt,
deletedWithUrnOpt,
provIdOpt,
providerRefs,
depUrns,
options.aliases.toList,
options
)

private[internal] def executeReadResourceRequest[R <: Resource](
state: ResourceState,
Expand Down Expand Up @@ -471,8 +475,23 @@ class ResourceOps(using ctx: Context, mdc: BesomMDC[Label]):
case CustomResolvedResourceOptions(_, _, _, _, importId) => importId.getOrElse("")
case _ => ""
,
aliases = inputs.aliases.map { alias =>
pulumirpc.alias.Alias(pulumirpc.alias.Alias.Alias.Urn(alias))
aliases = inputs.aliases.map {
case UrnResourceAlias(urn) => pulumirpc.alias.Alias(pulumirpc.alias.Alias.Alias.Urn(urn))
case SpecResourceAlias(name, resourceType, stack, project, parent) =>
pulumirpc.alias.Alias(
pulumirpc.alias.Alias.Alias.Spec(
pulumirpc.alias.Alias.Spec(
name = name.getOrElse(""),
`type` = resourceType.getOrElse(""),
stack = stack.getOrElse(""),
project = project.getOrElse(""),
parent = parent match
case Some(ResourceAliasParentUrn(urn)) => pulumirpc.alias.Alias.Spec.Parent.ParentUrn(urn)
case Some(ResourceAliasNoParent(noParent)) => pulumirpc.alias.Alias.Spec.Parent.NoParent(noParent)
case None => pulumirpc.alias.Alias.Spec.Parent.Empty
)
)
)
},
remote = remote,
customTimeouts = Some(
Expand Down
29 changes: 19 additions & 10 deletions core/src/main/scala/besom/internal/ResourceOptions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ sealed trait ResolvedResourceOptions:
def version: Option[String]
def customTimeouts: Option[CustomTimeouts]
// def resourceTransformations: Iterable[ResourceTransformation], // TODO
// def aliases: Iterable[Output[Alias]], // TODO
def aliases: Iterable[ResourceAlias]
def urn: Option[URN]
def replaceOnChanges: Iterable[String]
def retainOnDelete: Boolean
Expand All @@ -47,7 +47,7 @@ case class CommonResolvedResourceOptions(
version: Option[String],
customTimeouts: Option[CustomTimeouts],
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Iterable[ResourceAlias],
urn: Option[URN],
replaceOnChanges: Iterable[String],
retainOnDelete: Boolean,
Expand Down Expand Up @@ -84,7 +84,7 @@ trait CommonResourceOptions:
def version: Output[Option[String]]
def customTimeouts: Output[Option[CustomTimeouts]]
// def resourceTransformations: Iterable[ResourceTransformation], // TODO
// def aliases: Iterable[Output[Alias]], // TODO
def aliases: Output[Iterable[ResourceAlias]]
// TODO this is only necessary for Resource deserialization, dependency resources and multi-language remote components
def urn: Output[Option[URN]]
def replaceOnChanges: Output[Iterable[String]]
Expand All @@ -103,6 +103,7 @@ extension (cro: CommonResourceOptions)
ignoreChanges <- cro.ignoreChanges.getData
version <- cro.version.getData
customTimeouts <- cro.customTimeouts.getData
aliases <- cro.aliases.getData
urn <- cro.urn.getData
replaceOnChanges <- cro.replaceOnChanges.getData
retainOnDelete <- cro.retainOnDelete.getData
Expand All @@ -116,6 +117,7 @@ extension (cro: CommonResourceOptions)
ignoreChanges = ignoreChanges.getValueOrElse(Iterable.empty),
version = version.getValueOrElse(None),
customTimeouts = customTimeouts.getValueOrElse(None),
aliases = aliases.getValueOrElse(Iterable.empty),
urn = urn.getValueOrElse(None),
replaceOnChanges = replaceOnChanges.getValueOrElse(Iterable.empty),
retainOnDelete = retainOnDelete.getValueOrElse(false),
Expand All @@ -131,7 +133,7 @@ final case class CommonResourceOptionsImpl(
version: Output[Option[String]],
customTimeouts: Output[Option[CustomTimeouts]],
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Output[Iterable[ResourceAlias]],
urn: Output[Option[URN]],
replaceOnChanges: Output[Iterable[String]],
retainOnDelete: Output[Boolean],
Expand Down Expand Up @@ -240,7 +242,7 @@ trait CustomResourceOptionsFactory:
provider: Input.Optional[ProviderResource] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -257,6 +259,7 @@ trait CustomResourceOptionsFactory:
version = version.asOptionOutput(),
provider = provider.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand All @@ -277,7 +280,7 @@ object CustomResourceOptions:
provider: Input.Optional[ProviderResource] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -293,6 +296,7 @@ object CustomResourceOptions:
ignoreChanges = ignoreChanges.asManyOutput(),
version = version.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand All @@ -306,6 +310,7 @@ object CustomResourceOptions:
additionalSecretOutputs = additionalSecretOutputs.asManyOutput(),
importId = importId.asOptionOutput()
)
end apply
end CustomResourceOptions

trait ComponentResourceOptionsFactory:
Expand All @@ -318,7 +323,7 @@ trait ComponentResourceOptionsFactory:
version: Input.Optional[NonEmptyString] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -332,6 +337,7 @@ trait ComponentResourceOptionsFactory:
ignoreChanges = ignoreChanges.asManyOutput(),
version = version.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand All @@ -349,7 +355,7 @@ object ComponentResourceOptions:
version: Input.Optional[NonEmptyString] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -363,6 +369,7 @@ object ComponentResourceOptions:
ignoreChanges = ignoreChanges.asManyOutput(),
version = version.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand All @@ -380,7 +387,7 @@ object StackReferenceResourceOptions:
version: Input.Optional[NonEmptyString] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -395,6 +402,7 @@ object StackReferenceResourceOptions:
ignoreChanges = ignoreChanges.asManyOutput(),
version = version.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand All @@ -412,7 +420,7 @@ trait StackReferenceResourceOptionsFactory:
version: Input.Optional[NonEmptyString] = None,
customTimeouts: Input.Optional[CustomTimeouts] = None,
// resourceTransformations: Iterable[ResourceTransformation], // TODO
// aliases: Iterable[Output[Alias]], // TODO
aliases: Input.OneOrIterable[ResourceAlias] = Iterable.empty,
urn: Input.Optional[URN] = None,
replaceOnChanges: Input.OneOrIterable[String] = Iterable.empty,
retainOnDelete: Input[Boolean] = false,
Expand All @@ -427,6 +435,7 @@ trait StackReferenceResourceOptionsFactory:
ignoreChanges = ignoreChanges.asManyOutput(),
version = version.asOptionOutput(),
customTimeouts = customTimeouts.asOptionOutput(),
aliases = aliases.asManyOutput(),
urn = urn.asOptionOutput(),
replaceOnChanges = replaceOnChanges.asManyOutput(),
retainOnDelete = retainOnDelete.asOutput(),
Expand Down
23 changes: 4 additions & 19 deletions integration-tests/CoreTests.test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,29 +86,14 @@ class CoreTests extends munit.FunSuite {
)
},
teardown = pulumi.fixture.teardown
).test("random provider and memoization should work") { ctx =>
).test("random provider, memoization and aliases should work") { ctx =>
val result = pulumi.up(ctx.stackName).call(cwd = ctx.programDir, env = ctx.env)
val output = result.out.text()
assert(output.contains("randomString:"), s"Output:\n$output\n")
}

FunFixture[pulumi.FixtureContext](
setup = {
val schemaName = "tls"
val latestVersion = Version.latestPackageVersion(schemaName)
val result = codegen.generatePackage(PackageMetadata(schemaName, latestVersion))
scalaCli.publishLocal(result.outputDir).call()
pulumi.fixture.setup(
wd / "resources" / "tls-example",
projectFiles = Map(
"project.scala" ->
(defaultProjectFile + CodeGen.packageDependency(schemaName, latestVersion))
)
)
},
teardown = pulumi.fixture.teardown
).test("tls provider should work with function") { ctx =>
pulumi.up(ctx.stackName).call(cwd = ctx.programDir, env = ctx.env)
val previewResult = pulumi.preview(ctx.stackName).call(cwd = ctx.programDir, env = ctx.env + ("TEST_ALIAS" -> "true"))
val previewOutput = previewResult.out.text()
assert(previewOutput.contains("2 unchanged"), s"Output:\n$previewOutput\n")
}

FunFixture[pulumi.FixtureMultiContext](
Expand Down
10 changes: 8 additions & 2 deletions integration-tests/resources/random-example/Main.scala
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import besom.*
import besom.api.random.*
import besom.internal.SpecResourceAlias

@main
def main(): Unit = Pulumi.run {
val oldName = "random-string"
val newName = "random-string-2"

val testAlias = sys.env.getOrElse("TEST_ALIAS", "false").toBoolean

def strOutput = RandomString(
name = "random-string",
name = if (testAlias) newName else oldName,
args = RandomStringArgs(
length = 10
)
),
opts = opts(aliases = if (testAlias) List(SpecResourceAlias(name = Some(oldName))) else List.empty)
)

val str = strOutput
Expand Down

0 comments on commit 648ec22

Please sign in to comment.