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

WIP: Improve all public APIs by dropping (using Context) #538

Merged
merged 40 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1ee09ec
wip, a lot more to do, compiles
lbialy Sep 3, 2024
70d2538
it works! or at least looks like it works!
lbialy Sep 6, 2024
e5175f0
drop the overloaded apply in internals, fix integration tests failing…
lbialy Sep 8, 2024
b165c16
fix besom-cfg-k8s
lbialy Sep 8, 2024
c3ae303
fix besom-cfg-k8s tests
lbialy Sep 14, 2024
3a4a130
progress
lbialy Sep 17, 2024
7906c21
tests for context propagation (parenthood propagation) working correctly
lbialy Sep 17, 2024
290eeed
more public apis cleaned, codegen yet to be done
lbialy Sep 17, 2024
a4e7a42
codegen done, tests of packages now
lbialy Sep 18, 2024
baccd28
fixed overlays
lbialy Sep 19, 2024
e0eacb2
fixed besom-cfg usage of Context
lbialy Sep 20, 2024
31b2b1f
more clean-up
lbialy Sep 24, 2024
586c1f4
split rpc from core
lbialy Sep 25, 2024
18f0dac
add dependency on rpc in core and fix formatting everywhere
lbialy Sep 25, 2024
e5fedfa
fix justfile
lbialy Sep 25, 2024
d4cac68
bump pulumi version in CI so that fix to IT works on CI too
lbialy Sep 25, 2024
3b9c020
what the hell, gha?
lbialy Sep 25, 2024
64064a4
gha vscode plugin is stupid and describing stuff in yaml is stupid
lbialy Sep 25, 2024
ab8ffa3
Try to speed up builds by @prolativ
prolativ Sep 25, 2024
f48fe45
Verbose logging of pulumi cli in integration tests to diagnose CI
lbialy Sep 26, 2024
88af014
fix justfile - besom-rpc module did not have no-bloop var renamed
lbialy Sep 26, 2024
ebb4427
uh, list expand into vararg doesn't work when it's not the last arg, …
lbialy Sep 26, 2024
3a22a8f
fix TF_LOG
lbialy Sep 26, 2024
b2a77c1
uncomment previously non-compiling methods
lbialy Sep 27, 2024
b1cea8b
uncomment previously non-compiling tests!
lbialy Sep 27, 2024
3516514
debugging deadlock on CI
lbialy Sep 28, 2024
4cc81ae
fix fmt
lbialy Sep 30, 2024
c65b449
fix gradle build in IT
lbialy Sep 30, 2024
3d1707b
fix gradle build in IT
lbialy Sep 30, 2024
44f96cf
fix gradle & maven build in IT
lbialy Sep 30, 2024
3020a22
fix gradle & maven build in IT again
lbialy Sep 30, 2024
0f2e80f
drop all sonatype:snapshots and remove all autogenerated project.scal…
lbialy Sep 30, 2024
400b29a
always compile examples without bloop server
lbialy Oct 1, 2024
1fdee2b
always compile templates without a bloop server
lbialy Oct 1, 2024
c78eece
fix compiler plugin test
lbialy Oct 1, 2024
5ebf7e2
drop debugging code in Promise
lbialy Oct 1, 2024
a80075b
add missing code comments
lbialy Oct 2, 2024
5856f63
restore sonatype:snapshots in examples
lbialy Oct 2, 2024
d67b68c
drop comments
lbialy Oct 2, 2024
278c2fb
add repository sonatype:snapshots in templates too
lbialy Oct 2, 2024
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
2 changes: 1 addition & 1 deletion besom-cfg/k8s/src/main/scala/ConfiguredContainerArgs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ object ConfiguredContainerArgs:

case Right(()) =>
val envExpr = '{
val envOutput = ${ env }.asOptionOutput()(using ${ context })
val envOutput = ${ env }.asOptionOutput()
val conf = ${ configuration }
val configurationAsEnvVarArgs = conf.foldedToEnvVarArgs(using $context)
envOutput.zip(configurationAsEnvVarArgs).map {
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/scala/besom/internal/BesomModule.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package besom.internal

import besom.internal.logging.{LocalBesomLogger => logger, BesomLogger}
import besom.internal.logging.{BesomMDC, LocalBesomLogger => logger, BesomLogger}
import besom.util.printer

/** An abstract effect Besom module, which can be implemented for different effect types.
Expand Down Expand Up @@ -40,6 +40,8 @@ trait EffectBesomModule extends BesomSyntax:
* the program to run
*/
def run(program: Context ?=> Stack): Unit =
given emptyMDC: BesomMDC[_] = BesomMDC.empty

val everything: Result[Unit] = Result.scoped {
for
_ <- BesomLogger.setupLogger()
Expand Down
14 changes: 7 additions & 7 deletions core/src/main/scala/besom/internal/BesomSyntax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ trait BesomSyntax:

val componentContext = ComponentContext(ctx, urnRes, componentBase)
val componentOutput =
try Output(Result.pure(f(using componentContext)(using componentBase)))
catch case e: Exception => Output(Result.fail(e))
try Output.pure(f(using componentContext)(using componentBase))
catch case e: Exception => Output.fail(e)

val componentResult = componentOutput.getValueOrFail {
s"Component resource $name of type $typ did not return a value. This should not happen."
Expand All @@ -120,22 +120,22 @@ trait BesomSyntax:
end component

extension [A <: ProviderResource](pr: A)
def provider(using Context): Output[Option[ProviderResource]] = Output {
def provider(using Context): Output[Option[ProviderResource]] = Output.ofResult {
Context().resources.getStateFor(pr).map(_.custom.provider)
}

extension [A <: CustomResource](cr: A)
def provider(using Context): Output[Option[ProviderResource]] = Output {
def provider(using Context): Output[Option[ProviderResource]] = Output.ofResult {
Context().resources.getStateFor(cr).map(_.provider)
}

extension [A <: ComponentResource](cmpr: A)
def providers(using Context): Output[Map[String, ProviderResource]] = Output {
def providers(using Context): Output[Map[String, ProviderResource]] = Output.ofResult {
Context().resources.getStateFor(cmpr).map(_.providers)
}

extension [A <: RemoteComponentResource](cb: A)
def providers(using Context): Output[Map[String, ProviderResource]] = Output {
def providers(using Context): Output[Map[String, ProviderResource]] = Output.ofResult {
Context().resources.getStateFor(cb).map(_.providers)
}

Expand All @@ -160,7 +160,7 @@ trait BesomSyntax:
* an [[IllegalArgumentException]].
*/
def toNonEmptyOutput(using Context): Output[NonEmptyString] =
NonEmptyString(s).fold(Output.fail(IllegalArgumentException(s"String $s was empty!")))(Output.apply(_))
NonEmptyString(s).fold(Output.fail(IllegalArgumentException(s"String $s was empty!")))(Output.pure(_))

extension (os: Output[String])
/** Converts an [[Output]] of [[String]] to an [[Output]] of [[NonEmptyString]] which will be failed if the string is empty.
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/scala/besom/internal/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ class Config private (
* @return
* the configuration value of the requested type
*/
private def getRawValue(key: NonEmptyString)(using ctx: Context): Output[Option[String]] =
private def getRawValue(key: NonEmptyString): Output[Option[String]] =
if configSecretKeys.contains(key)
then Output.secret(tryGet(key))
else Output(tryGet(key))
else Output.pure(tryGet(key))

private def readConfigValue[A: ConfigValueReader](
key: NonEmptyString,
Expand Down Expand Up @@ -99,7 +99,7 @@ class Config private (
.orElse(environment.collectFirst {
case env if sys.env.contains(env) => sys.env(env)
})
val value = if isSecret then Output.secret(rawValue) else Output(rawValue)
val value = if isSecret then Output.secret(rawValue) else Output.pure(rawValue)
readConfigValue(key, value).map(_.orElse(default))

/** Loads an optional configuration or secret value by its key, or returns [[None]] if it doesn't exist. If the configuration value is a
Expand Down Expand Up @@ -132,7 +132,7 @@ class Config private (
def secretOption = if configSecretKeys.contains(key) then "[--secret]" else ""
get[A](key).flatMap { valueOpt =>
valueOpt match
case Some(value) => Output(value)
case Some(value) => Output.pure(value)
case None =>
Output.fail {
ConfigError(
Expand Down Expand Up @@ -555,4 +555,4 @@ trait ConfigFactory:
*/
def apply(namespace: NonEmptyString)(using Context): Output[Config] =
val projectConfig = Context().config
Output(Config.forNamespace(namespace, projectConfig.configMap, projectConfig.configSecretKeys))
Output.ofResult(Config.forNamespace(namespace, projectConfig.configMap, projectConfig.configSecretKeys))
2 changes: 1 addition & 1 deletion core/src/main/scala/besom/internal/Context.scala
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class ContextImpl(
override private[besom] def pulumiStack: NonEmptyString = runInfo.stack

override private[besom] def getParentURN: Result[URN] =
stackPromise.get.flatMap(_.urn.getData).map(_.getValue).flatMap {
stackPromise.get.flatMap(_.urn.getData(using this)).map(_.getValue).flatMap {
case Some(urn) => Result.pure(urn)
case None => Result.fail(Exception("Stack urn is not available. This should not happen."))
}
Expand Down
34 changes: 16 additions & 18 deletions core/src/main/scala/besom/internal/Input.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,63 +15,61 @@ object Input:

given simpleInputOps: {} with
extension [A](input: Input[A])
private[Input] def wrappedAsOutput(isSecret: Boolean = false)(using ctx: Context): Output[A] =
private[Input] def wrappedAsOutput(isSecret: Boolean = false): Output[A] =
input match
case output: Output[_] => output.asInstanceOf[Output[A]]
case a: A @unchecked => if isSecret then Output.secret(a) else Output(a)
case a: A @unchecked => if isSecret then Output.secret(a) else Output.pure(a)

extension [A](input: Input[A])
def asOutput(isSecret: Boolean = false)(using ctx: Context): Output[A] =
def asOutput(isSecret: Boolean = false): Output[A] =
input.wrappedAsOutput(isSecret)

extension [A](input: Input.Optional[A])
private[Input] def wrappedAsOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[A]] =
private[Input] def wrappedAsOptionOutput(isSecret: Boolean = false): Output[Option[A]] =
val output = input match
case output: Output[_] => output.asInstanceOf[Output[A | Option[A]]]
case maybeA: (A | Option[A]) @unchecked => if isSecret then Output.secret(maybeA) else Output(maybeA)
case maybeA: (A | Option[A]) @unchecked => if isSecret then Output.secret(maybeA) else Output.pure(maybeA)
output.map(_.asOption)

def asOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[A]] =
def asOptionOutput(isSecret: Boolean = false): Output[Option[A]] =
input.wrappedAsOptionOutput(isSecret)

given mapInputOps: {} with
private def inputMapToMapOutput[A](inputMap: Map[String, Input[A]], isSecret: Boolean)(using ctx: Context): Output[Map[String, A]] =
private def inputMapToMapOutput[A](inputMap: Map[String, Input[A]], isSecret: Boolean): Output[Map[String, A]] =
val outputMap = inputMap.view.mapValues(_.asOutput(isSecret)).toMap
Output.traverseMap(outputMap)

extension [A](input: Input[Map[String, Input[A]]])
def asOutput(isSecret: Boolean = false)(using ctx: Context): Output[Map[String, A]] =
def asOutput(isSecret: Boolean = false): Output[Map[String, A]] =
input.wrappedAsOutput(isSecret).flatMap(inputMapToMapOutput(_, isSecret = isSecret))

extension [A](input: Input.Optional[Map[String, Input[A]]])
def asOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[Map[String, A]]] =
def asOptionOutput(isSecret: Boolean = false): Output[Option[Map[String, A]]] =
input.wrappedAsOptionOutput(isSecret).flatMap {
case Some(map) => inputMapToMapOutput(map, isSecret = isSecret).map(Option(_))
case None => Output(None)
case None => Output.pure(None)
}

given iterableInputOps: {} with
private def inputIterableToIterableOutput[A](inputIterable: Iterable[Input[A]], isSecret: Boolean)(using
ctx: Context
): Output[Iterable[A]] =
private def inputIterableToIterableOutput[A](inputIterable: Iterable[Input[A]], isSecret: Boolean): Output[Iterable[A]] =
val outputIterable = inputIterable.map(simpleInputOps.asOutput(_)(isSecret = isSecret))
Output.sequence(outputIterable)

extension [A](input: Input.OneOrIterable[A])
def asManyOutput(isSecret: Boolean = false)(using ctx: Context): Output[Iterable[A]] =
def asManyOutput(isSecret: Boolean = false): Output[Iterable[A]] =
input.wrappedAsOutput(isSecret).flatMap {
case iterable: Iterable[Input[A]] @unchecked => inputIterableToIterableOutput(iterable, isSecret = isSecret)
case a: A @unchecked => Output(Iterable(a))
case a: A @unchecked => Output.pure(Iterable(a))
}

extension [A](input: Input[Iterable[Input[A]]])
def asOutput(isSecret: Boolean = false)(using ctx: Context): Output[Iterable[A]] =
def asOutput(isSecret: Boolean = false): Output[Iterable[A]] =
input.wrappedAsOutput(isSecret).flatMap(inputIterableToIterableOutput(_, isSecret = isSecret))

extension [A](input: Input.Optional[Iterable[Input[A]]])
def asOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[Iterable[A]]] =
def asOptionOutput(isSecret: Boolean = false): Output[Option[Iterable[A]]] =
input.wrappedAsOptionOutput(isSecret).flatMap {
case Some(map) => inputIterableToIterableOutput(map, isSecret = isSecret).map(Option(_))
case None => Output(None)
case None => Output.pure(None)
}
end Input
Loading
Loading