pulumi_wasm_build/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
//! `pulumi_wasm_build` generates glue code for given Pulumi provider
//! ## Example
//! Select Pulumi provider you want to use. For demonstration purposes I'll choose [Random](https://www.pulumi.com/registry/packages/random/)
//!
//! Here we will have the provider glue and our code in single library. Due to compilation times
//! it is recommended to separate glue code and custom code.
//! ```bash
//! $ cargo new --lib random && cd random
//! ```
//!
//! First, add `pulumi_wasm_build`, `bon`, `serde`, `anyhow` and `wit-bindgen` to `Cargo.toml`:
//!
//! ```bash
//! $ cargo add --build pulumi_wasm_build
//! $ cargo add bon
//! $ cargo add serde --features derive
//! $ cargo add anyhow
//! $ cargo add wit-bindgen
//! ```
//!
//! To generate glue code, use `pulumi_wasm_build` in `build.rs`
//! ```rust,no_run
//! use std::error::Error;
//! fn main() -> Result<(), Box<dyn Error>> {
//! pulumi_wasm_build::generate("random", "4.15.0")?;
//! Ok(())
//! }
//! ```
//!
//! Then add generated code to `lib.rs` and use it in `#[pulumi_main]`
//! ```rust,ignore
//! mod random {
//! include_provider!("random");
//! }
//!
//! use random::random_string::RandomStringArgs;
//! use random::random_string;
//! use pulumi_wasm_rust::pulumi_main;
//! use anyhow::Result;
//!
//! #[pulumi_main]
//! fn main() -> Result<()> {
//! let random_string = random_string::create(
//! "test",
//! RandomStringArgs::builder().length(32).build_struct()
//! );
//! Ok(())
//! }
//! ```
use anyhow::{Context, Result};
use pulumi_wasm_generator::{extract_micro_package, generate_combined};
use std::path::Path;
use std::{env, fs};
/// Generates glue code for given provider, version and modules. Can be included using [`pulumi_wasm_rust::include_provider!(provider_name)`]
/// Modules for provider can be found in Pulumi registry on left side with (M) icon:
/// - [AWS](https://www.pulumi.com/registry/packages/aws/)
/// - [Azure](https://www.pulumi.com/registry/packages/azure/)
/// - [GCP](https://www.pulumi.com/registry/packages/gcp/)
pub fn generate_with_filter(
provider_name: &str,
provider_version: &str,
modules: &[&str],
) -> Result<()> {
generate_with_optional_filter(provider_name, provider_version, Some(modules))
}
/// Generates glue code for given provider and version. Can be included using [`pulumi_wasm_rust::include_provider!(provider_name)`]
pub fn generate(provider_name: &str, provider_version: &str) -> Result<()> {
generate_with_optional_filter(provider_name, provider_version, None)
}
/// Generates glue code for given schema json/yaml. Can be included using [`pulumi_wasm_rust::include_provider!(provider_name)`]
pub fn generate_from_schema(schema_file: &Path) -> Result<()> {
generate_from_schema_with_optional_filter(schema_file, None)
}
/// Generates glue code for given schema json/yaml and modules. Can be included using [`pulumi_wasm_rust::include_provider!(provider_name)`]
/// Modules for provider can be found in Pulumi registry on left side with (M) icon:
/// - [AWS](https://www.pulumi.com/registry/packages/aws/)
/// - [Azure](https://www.pulumi.com/registry/packages/azure/)
/// - [GCP](https://www.pulumi.com/registry/packages/gcp/)
pub fn generate_from_schema_with_filter(schema_file: &Path, modules: &[&str]) -> Result<()> {
generate_from_schema_with_optional_filter(schema_file, Some(modules))
}
fn generate_from_schema_with_optional_filter(
schema_file: &Path,
modules: Option<&[&str]>,
) -> Result<()> {
let package = extract_micro_package(schema_file).context("Failed to deserialize package")?;
let provider_name = package.name;
let out_dir = env::var_os("OUT_DIR").context("Failed to get OUT_DIR environment variable")?;
let out_dir = out_dir
.to_str()
.context(format!("Failed to convert [{:?}] to string", out_dir))?;
let location = Path::new(out_dir).join("pulumi").join(provider_name);
generate_combined(schema_file, &location, modules).context("Failed to generate glue files")?;
println!("cargo::rerun-if-changed=build.rs");
println!("cargo::rerun-if-changed={}", schema_file.display());
Ok(())
}
fn generate_with_optional_filter(
provider_name: &str,
provider_version: &str,
modules: Option<&[&str]>,
) -> Result<()> {
let schema_output = std::process::Command::new("pulumi")
.arg("package")
.arg("get-schema")
.arg(format!("{}@{}", provider_name, provider_version))
.env("PULUMI_AWS_MINIMAL_SCHEMA", "true") // https://github.com/pulumi/pulumi-aws/issues/2565
.output()
.context("Failed to execute pulumi command")?;
let schema = String::from_utf8(schema_output.stdout).expect("Invalid UTF-8 in pulumi output");
let out_dir = env::var_os("OUT_DIR").context("Failed to get OUT_DIR environment variable")?;
let out_dir = out_dir
.to_str()
.context(format!("Failed to convert [{:?}] to string", out_dir))?;
let location = Path::new(out_dir).join("pulumi").join(provider_name);
let temp_dir = tempfile::tempdir().context("Failed to create temporary directory")?;
let file = temp_dir.path().join("schema.json");
fs::write(&file, &schema).context("Failed to write schema")?;
generate_combined(file.as_path(), &location, modules)
.context("Failed to generate glue files")?;
println!("cargo::rerun-if-changed=build.rs");
Ok(())
}