Changelog
0.5.0 (01-10-2025)
Besom is no longer in beta. 0.5.0 is considered stable-candidate and will be the last version before 1.0.0.
Core API
withArgs(copy) method added to args companion objects for all Args classes. This allows for Args reuse between similar resources.- StackReferences can now be typed statically by just providing the target type to which exports are to be loaded.
- The
(using Context)clause has been dropped from many APIs due to the introduction of built-in reader monad into theOutputmonad's internals that passesContextinternally. It is now only required whereContextis used to establish resource parenthood relationships or where free functions require access to the data related to the current stack. - Fixed codegen issue where
"plain"input parameters were generated asInputs instead of raw arguments. This fixes a whole category of smaller issues with providers. - Code-generated output classes now use
Outputtypes for all fields. This ensures that deserialization errors are isolated to individual fields and that field secrecy is handled with finer granularity. - All public APIs now take
Iterable[A]instead ofList[A]. This allows greater flexibility of the user API - no more.toList! - Resource aliases are now implemented!
- Codegen now supports hotfixes allowing usage of many previously blocked packages.
- Various fixes and optimizations to codegen in preparation for full automation of release pipeline. Examples are now used as complete end to end tests before releases.
Kubernetes provider
- Added Custom Resource and Custom Resource Patch support in Kubernetes provider via overlays mechanism.
- We now support generation of resource classes from Kubernetes Custom Resource Definitions via command line tool crd2besom (experimental).
New examples:
- GCP Functions
- GCP Instance + Nginx
- Google Firestore
- Google Cloud BigQuery
- Azure ACI
- Kubernetes + Keycloak
- Azure CosmosDB + LogicApp
- ETL pipeline with Amazon Redshift + AWS Glue
- Azure Synapse Workspace and Pools
- Azure web app with Private Endpoint and VNet injection
Full Changelog: https://github.com/VirtusLab/besom/compare/v0.3.2...v0.5.0
About Besom 0.4.0
Besom 0.4.0 was released in March of 2025 but, unfortunately, it did incorporate a significant correctness bug that impacted any user code that depended on the Component API. This issue was present in both Core SDK and all packages generated by codegen of the 0.4.0 release. As the bug was found in the late smoke testing procedure of the release, most of the provider packages were already published to Maven Central. The release on Github was not published at the time and therefore the decision was made to scrap the whole release, not announce it, treat is as dead-on-arrival and to patch both Core SDK and Codegen and re-release everything once more.
tl;dr: Do not use Besom 0.4.0. Skip to 0.5.0 directly from 0.3.2.
0.3.2 (11-06-2024)
- Added missing
provider/providersfield on resources to fix #397 (@lbialy in 505) - Exposed
CustomTimeoutsresource option configuration value (@lbialy in 502) - Fixed issue 489 where ANSI control chars crashed internal logging (@lbialy in 492)
- First working draft of Automation API (sync, Either-monad based) (@pawelprazak in 336)
- Fixed issues with eviction of dependencies of core besom library (@lbialy in 500)
- Fixed bug that crashed besom when resource options were provided for component resource (@lbialy in 502)
- First working draft of Besom Configure (besom-cfg) (Kubernetes only) (@lbialy in 494)
- Allow passing options to scala-cli via language plugin executor (@lbialy in 503)
New examples:
- Add AWS API Gateway V2 with EventBridge example by @polkx in https://github.com/VirtusLab/besom/pull/479
Full Changelog: https://github.com/VirtusLab/besom/compare/v0.3.1...v0.3.2
0.3.1 (19-04-2024)
-
Support for
ConfigGroup,ConfigFileresources in Kubernetes provider 4.11.0+ is now available in Besom! -
Added new combinators on
Output:recoverallows to map an error inside of a failedOutputto a new valuerecoverWithallows the same but using an effectful function returning either anOutputor any other supported effect, e.g.:Future,IOorTasktapallows to access the value of anOutputand apply an effectful function to it while discarding said function's resultstapErrorallows the same but for an error of a failedOutputtapBothtakes two effectful function and allows to access either error or value of anOutputby applying one of them to the contents of theOutputvoiddiscards the value of anOutput, comes with a static constructor function -Output.unitunzipcan be called on anOutputof a tuple to receive a tuple ofOutputs, all of which are descendents of the originalOutput
Full Changelog: GitHub (v0.3.0...v0.3.1)
0.3.0 (16-04-2024)
API Changes and New Features
- Added new
besom.jsoninterpolation API. Now this snippet from our tutorial:
s3.BucketPolicyArgs(
bucket = feedBucket.id,
policy = JsObject(
"Version" -> JsString("2012-10-17"),
"Statement" -> JsArray(
JsObject(
"Sid" -> JsString("PublicReadGetObject"),
"Effect" -> JsString("Allow"),
"Principal" -> JsObject(
"AWS" -> JsString("*")
),
"Action" -> JsArray(JsString("s3:GetObject")),
"Resource" -> JsArray(JsString(s"arn:aws:s3:::${name}/*"))
)
)
).prettyPrint
)
can be rewritten as:
s3.BucketPolicyArgs(
bucket = feedBucket.id,
policy = json"""{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3::${name}/*"]
}]
}""".map(_.prettyPrint)
)
The json interpolator returns an Output[JsValue] and is fully compile-time type safe and verifies JSON string for correctness.
The only types that can be interpolated are String, Int, Short, Long, Float, Double, JsValue and Option and Output
of the former (in whatever amount of nesting). If you need to interpolate a more complex type it's advised to derive a JsonFormat
for it and convert it to JsValue.
-
Package
besom.jsonwas modified to ease the use ofJsonFormatderivation. This change is breaking compatibility by exporting default instances fromDefaultJsonProtocoland providing a givenJsonProtocolinstance for use withderives JsonFormat. If you need to define a customJsonProcolchange the import toimport besom.json.custom.*which preserves the older semantics from spray-json and requires manual extension ofDefaultJsonProtocol. -
Derived
JsonFormatfrom packagebesom.jsonnow respects arguments with default values. In conjunction with the previous change it means one can now use it like this:
import besom.json.*
case class Color(name: String, red: Int, green: Int, blue: Int = 160) derives JsonFormat
val color = Color("CadetBlue", 95, 158)
val json = """{"name":"CadetBlue","red":95,"green":158}"""
assert(color.toJson.convertTo[Color] == color)
assert(json.parseJson.convertTo[Color] == color)
Bug Fixes
- fixed infinite loop in encoders #407 when a recursive type is encountered
- fixed cause passing in
AggregateExceptionto improve debugging of decoders #426 - fixed Pulumi side effects memoization issues in Component API #429
- fixed traverse problem caused by export bug in compiler with a temporary workaround #430
Other Changes
- custom timeouts have scaladocs now #419
- overhauled serde layer with refined outputs implemented to improve parity with upstream Pulumi engine #414
- StackReferences are now documented #428
- updated AWS EKS hello world example #399
- Component API now disallows returning component instances wrapped in Outputs to prevent users from dry run issues #441
- added
parSequenceandparTraversecombinators onOutput#440 - added
Output.whencombinator #439 - improved compilation errors around
Output.evalandOutput#flatMap#443 - all
Outputcombinators have scaladocs now #445 - added extension-based combinators for
Output[Option[A]],Output[List[A]]etc #445 - added support for overlays (package-specific extensions) in besom
codegen, this opens a way for support of Helm, magic lambdas and other advanced features #402
Full Changelog: GitHub (v0.2.2...v0.3.0)
0.2.2 (22-02-2024)
Bug Fixes
- fixed component argument serialization issue 398
Other Changes
- added Kubernetes guestbook example 395
Full Changelog: GitHub (v0.2.1...v0.2.2)
0.2.1 (15-02-2024)
Bug Fixes
- Fix URL validation to allow for kubernetes types #385
- Loosen up and fix URN parsing #389
- Fix serializer now skips fields with null value secrets #386
Full Changelog: GitHub (v0.2.0...v0.2.1)
0.2.0 (08-02-2024)
API Changes
-
Changed the type of main
Pulumi.runfunction fromContext ?=> Output[Exports](a context function providingbesom.Contextinstance implicitly in its scope and expectingOutput[Exports]as returned value) toContext ?=> Stack. This change has one core reason: it helps us solve a problem related to dry run functionality that was hindered when a external Output was interwoven in the final for-comprehension. External Outputs (Outputs that depend on real return values from Pulumi engine) no-op their flatMap/map chains in dry run similarly to Option's None (because there is no value to feed to the passed function) and therefore led to exports code not being executed in dry run at all, causing a diff showing that all exports are going to be removed in preview and then recreated in apply phase. New type ofPulumi.runfunction disallows returning of async values - Stack has to be returned unwrapped, synchronously. Stack is just a case class that takes only two arguments:exports: ExportsanddependsOn: Vector[Output[?]].exportsserve the same purpose as before anddependsOnis used to use all theOutputsthat have to be evaluated for this stack to be constructed but are not to be exported. You can return aStackthat only consists of exports (for instance when everything you depend on is composed into a thing that you export in the final step) usingStack.export(x = a, y = b)or aStackthat has only dependencies when you don't want to export anything usingStack(x, y). You can also use some resources and export others usingStack(a, b).export(x = i, y = j)syntax. Here's an example use of Stack:@main def main = Pulumi.run {
val awsPolicy = aws.iam.Policy("my-policy",...)
val s3 = aws.s3.Bucket("my-bucket")
val logMessage = log.info("Creating your bucket!") // logs are values too!
Stack(logMessage, awsPolicy).exports(
url = s3.publicEndpoint
)
} -
Improved
Configergonomy, by automatic secrets handling and usingOutput[A]as the return value, and also adding a helpful error message when a key is missing #204 -
Overhauled
ResourceOptions#355
New Features
-
added support for Gradle and Maven to the Besom Scala language host #303
-
Provider functions like
aws.ec2.getAmiwere added to Besom. They allow you to use the Pulumi SDK to fetch data from the cloud provider and use it in your program. Here's an example of how to use them:@main def main = Pulumi.run {
val ami = ec2.getAmi(
ec2.GetAmiArgs(
filters = List(
GetAmiFilterArgs(
name = "name",
values = List("amzn2-ami-hvm-*-x86_64-ebs")
)
),
owners = List("137112412989"), // Amazon
mostRecent = true
)
)
val server = ec2.Instance("web-server-www",
ec2.InstanceArgs(ami = ami.id,...)
)
Stack(server).exports(
ami = ami.id
)
} -
Stack References were added to Besom. They allow you to use outputs from another stack as inputs to the current stack. Here's an example of how to use them #348:
@main def main = Pulumi.run {
...
Stack.exports(
someOutput = "Hello world!",
)
}@main def main = Pulumi.run {
val otherStack = besom.StackReference("stackRef", StackReferenceArgs("organization/source-stack-test/my-stack-name"))
val otherStackOutput = otherStack.output[String]("someOutput")
...
} -
Added support for Get functions to Besom. You can use the static get function, which is available on all resource types, to look up an existing resource that is not managed by Pulumi. Here's an example of how to use it:
@main def main = Pulumi.run {
val group = aws.ec2.SecurityGroup.get("group", "sg-0dfd33cdac25b1ec9")
...
} -
Added support for Structured Configuration, this allows user to read structured configuration from Pulumi configuration into JSON AST (
config.getJsonorconfig.requireJson) or deserialize to an object (config.getObjectorconfig.requireObject) #207 -
Added new methods to the Besom
ContextandResource, that allow for introspection into basic Pulumi metadata:pulumiResourceNameandpulumiProject,pulumiOrganization,pulumiStack#295 -
Added support for Remote Components to Besom #355.
-
Provider SDKs Code Generator was improved on multiple fronts:
- normalized the generated code to be more idiomatic and consistent with the rest of the SDK
- added support for provider functions and methods
- added support for component providers
- added support for convenient provider configuration access #259
- allow to refer to other resources by reference instead of ID #144
-
Improved [NonEmptyString] inference via metaprogramming to find string literals by recursively traversing the AST tree. It now coveres cases where strings are defined directly as
: String, concatenated with+, multiplied with*, all kinds of interpolators (includingp/pulumiinterpolator) are covered. Additionally, some new extension methods are defined to ease work with NES:"string".toNonEmpty: Option[NonEmptyString]- safe, same asNonEmptyString("string")"string".toNonEmptyOrThrow:NonEmptyString` - an unsafe extension for situations where you just can't be bothered"string".toNonEmptyOutput: Output[NonEmptyString]- safe, if the string is empty the returned Output will be failedOutput("string").toNonEmptyOutput: Output[NonEmptyString]- safe, if the string inside of the Output is empty the returned Output will be failed
Bug Fixes
- fixed logging via Pulumi RPC and added user-level MDC, now logs are properly displayed in the Pulumi console #199
- fixed failing gRPC shutdown in our core SDK by correcting the lifecycle handling, now the SDK properly shuts down #228
- fixed failing gRPC serialisation in multiple cases, now the SDK properly serialises and deserializes messages #148 #150
- fixed failing shorthand config key names, now the SDK properly handles shorthand config key names #205
- fixed
Output.sequence/Result.sequencemultiple evaluations issue, now the SDK properly handles multiple evaluations ofOutput.sequence/Result.sequence#313 - fixed failing codecs for provider inputs, now the SDK properly handles provider inputs #312
- fixed
Output.traverseruntime exception, now the SDK properly handlesOutput.traverse#360 - fixed fatal errors hanging the SDK, now the SDK properly handles fatal errors #361
- fixed resource decoders failing at runtime when handling special resources #364
- fixed transitive dependency resolution algorithm, now the SDK properly resolves transitive dependencies #371
- fixed failing code generation for unsupported or malformed schema files, now the generator properly handles schemas #265 #270 #274 #329 #332
- fixed failing code generation when clashing names are present in the schema, now the generator properly handles clashing names #275
- fixed failing code generation schema deserialization for complex types used as underlying types of named types #282
Other Changes
- added more examples to the Besom repository
- introduce schema-driven integration tests for
codegenfed from upstream Pulumi to improve reliability of the code generator - many internal improvements and refactorings to the codebase to improve the overall quality of the SDK and its maintainability
Full Changelog: GitHub (v0.1.0...v0.2.0)