-
Notifications
You must be signed in to change notification settings - Fork 0
compiler: claude can we have a kubernetes reporter #3
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
base: main
Are you sure you want to change the base?
Changes from all commits
eb495c6
8266675
ce83c43
176143b
c8022d3
1690810
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,10 @@ use amber_compiler::{ | |
| CompileOptions, CompileOutput, Compiler, ResolverRegistry, | ||
| bundle::{BundleBuilder, BundleLoader}, | ||
| reporter::{ | ||
| Reporter as _, docker_compose::DockerComposeReporter, dot::DotReporter, | ||
| Reporter as _, | ||
| docker_compose::DockerComposeReporter, | ||
| dot::DotReporter, | ||
| kubernetes::{KubernetesReporter, KubernetesReporterConfig}, | ||
| scenario_ir::ScenarioIrReporter, | ||
| }, | ||
| }; | ||
|
|
@@ -69,6 +72,14 @@ struct CompileArgs { | |
| #[arg(long = "bundle", value_name = "DIR")] | ||
| bundle: Option<PathBuf>, | ||
|
|
||
| /// Write Kubernetes manifests to this directory. | ||
| #[arg(long = "kubernetes", visible_alias = "k8s", value_name = "DIR")] | ||
| kubernetes: Option<PathBuf>, | ||
|
|
||
| /// Disable generation of NetworkPolicy enforcement check resources. | ||
| #[arg(long = "disable-networkpolicy-check", requires = "kubernetes")] | ||
| disable_networkpolicy_check: bool, | ||
|
|
||
| /// Root manifest or bundle to compile (URL or local path). | ||
| #[arg(value_name = "MANIFEST")] | ||
| manifest: String, | ||
|
|
@@ -179,6 +190,16 @@ async fn compile(args: CompileArgs) -> Result<()> { | |
| } | ||
| } | ||
|
|
||
| if let Some(kubernetes_dest) = outputs.kubernetes { | ||
| let reporter = KubernetesReporter { | ||
| config: KubernetesReporterConfig { | ||
| disable_networkpolicy_check: args.disable_networkpolicy_check, | ||
| }, | ||
| }; | ||
| let artifact = reporter.emit(&output).map_err(miette::Report::new)?; | ||
| write_kubernetes_output(&kubernetes_dest, &artifact)?; | ||
| } | ||
|
|
||
| if let Some(bundle_root) = resolve_bundle_root(&args)? { | ||
| let tree = bundle_tree.expect("bundle requested"); | ||
| prepare_bundle_dir(&bundle_root)?; | ||
|
|
@@ -448,20 +469,22 @@ struct OutputPaths { | |
| primary: Option<PathBuf>, | ||
| dot: Option<ArtifactOutput>, | ||
| docker_compose: Option<ArtifactOutput>, | ||
| kubernetes: Option<PathBuf>, | ||
| } | ||
|
|
||
| fn ensure_outputs_requested(args: &CompileArgs) -> Result<()> { | ||
| if args.output.is_some() | ||
| || args.dot.is_some() | ||
| || args.docker_compose.is_some() | ||
| || args.bundle.is_some() | ||
| || args.kubernetes.is_some() | ||
| { | ||
| return Ok(()); | ||
| } | ||
|
|
||
| Err(miette::miette!( | ||
| help = "Request at least one output with `--output`, `--dot`, `--docker-compose`, or \ | ||
| `--bundle`.", | ||
| help = "Request at least one output with `--output`, `--dot`, `--docker-compose`, \ | ||
| `--kubernetes`, or `--bundle`.", | ||
| "no outputs requested for `amber compile`" | ||
| )) | ||
| } | ||
|
|
@@ -470,6 +493,7 @@ fn resolve_output_paths(args: &CompileArgs) -> Result<OutputPaths> { | |
| let primary = args.output.clone(); | ||
| let dot = resolve_optional_output(&args.dot); | ||
| let docker_compose = resolve_optional_output(&args.docker_compose); | ||
| let kubernetes = args.kubernetes.clone(); | ||
|
|
||
| if let (Some(primary_path), Some(ArtifactOutput::File(dot_path))) = | ||
| (primary.as_ref(), dot.as_ref()) | ||
|
|
@@ -505,6 +529,7 @@ fn resolve_output_paths(args: &CompileArgs) -> Result<OutputPaths> { | |
| primary, | ||
| dot, | ||
| docker_compose, | ||
| kubernetes, | ||
| }) | ||
| } | ||
|
|
||
|
|
@@ -524,18 +549,10 @@ fn resolve_bundle_root(args: &CompileArgs) -> Result<Option<PathBuf>> { | |
|
|
||
| fn prepare_bundle_dir(path: &Path) -> Result<()> { | ||
| if path.exists() { | ||
| if path.is_dir() { | ||
| std::fs::remove_dir_all(path) | ||
| .into_diagnostic() | ||
| .wrap_err_with(|| { | ||
| format!("failed to remove bundle directory `{}`", path.display()) | ||
| })?; | ||
| } else { | ||
| return Err(miette::miette!( | ||
| "bundle output path `{}` is not a directory", | ||
| path.display() | ||
| )); | ||
| } | ||
| return Err(miette::miette!( | ||
| "bundle output directory `{}` already exists; please delete it first", | ||
| path.display() | ||
| )); | ||
| } | ||
|
|
||
| std::fs::create_dir_all(path) | ||
|
|
@@ -565,3 +582,51 @@ fn write_artifact(path: &Path, contents: &[u8]) -> Result<()> { | |
| .into_diagnostic() | ||
| .wrap_err_with(|| format!("failed to write `{}`", path.display())) | ||
| } | ||
|
|
||
| fn write_kubernetes_output( | ||
| root: &Path, | ||
| artifact: &amber_compiler::reporter::kubernetes::KubernetesArtifact, | ||
pro-wh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) -> Result<()> { | ||
| // Clean and recreate the output directory. | ||
| if root.exists() { | ||
| if root.is_dir() { | ||
| std::fs::remove_dir_all(root) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure if want
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. like it's not too bad in theory, but the .env files kind of invite you to edit them so
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, maybe let's make people
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok ya |
||
| .into_diagnostic() | ||
| .wrap_err_with(|| { | ||
| format!( | ||
| "failed to remove kubernetes output directory `{}`", | ||
pro-wh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| root.display() | ||
| ) | ||
| })?; | ||
| } else { | ||
| return Err(miette::miette!( | ||
| "kubernetes output path `{}` is not a directory", | ||
| root.display() | ||
| )); | ||
| } | ||
| } | ||
|
|
||
| std::fs::create_dir_all(root) | ||
| .into_diagnostic() | ||
| .wrap_err_with(|| { | ||
| format!( | ||
| "failed to create kubernetes output directory `{}`", | ||
| root.display() | ||
| ) | ||
| })?; | ||
|
|
||
| // Write each file. | ||
| for (rel_path, content) in &artifact.files { | ||
| let full_path = root.join(rel_path); | ||
| if let Some(parent) = full_path.parent() { | ||
| std::fs::create_dir_all(parent) | ||
| .into_diagnostic() | ||
| .wrap_err_with(|| format!("failed to create directory `{}`", parent.display()))?; | ||
| } | ||
| std::fs::write(&full_path, content) | ||
| .into_diagnostic() | ||
| .wrap_err_with(|| format!("failed to write `{}`", full_path.display()))?; | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| Error: × no outputs requested for `amber compile` | ||
| help: Request at least one output with `--output`, `--dot`, `--docker- | ||
| compose`, or `--bundle`. | ||
| compose`, `--kubernetes`, or `--bundle`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ jsonschema = { workspace = true } | |
| miette = { workspace = true, features = ["derive"] } | ||
| serde = { workspace = true, features = ["derive"] } | ||
| serde_json = { workspace = true } | ||
| serde_yaml = { workspace = true } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. controversial opinion: yaml is a superset of json. write out json instead of bringing in yaml
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok on json |
||
| thiserror = { workspace = true } | ||
| tokio = { workspace = true, features = ["fs", "rt", "sync"] } | ||
| url = { workspace = true, features = ["serde"] } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,5 +20,5 @@ Compiles a root component manifest into a linked `Scenario` plus provenance and | |
| - `frontend`: async resolver with caching, cycle detection, and environment handling. | ||
| - `linker`: schema validation, binding resolution, and export verification. | ||
| - `passes`: graph rewrites that must preserve scenario invariants. | ||
| - `reporter`: transforms `CompileOutput` into artifacts (e.g., scenario IR JSON, DOT, Docker Compose YAML). | ||
| - `reporter`: transforms `CompileOutput` into artifacts (e.g., scenario IR JSON, DOT, Docker Compose YAML, Kubernetes YAML). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and then leave it described as kubernetes YAML to mess with people
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nah on labeling it as yaml 😆 |
||
| - `bundle`: bundle index parsing, manifest packing, and bundle-only resolver wiring. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. So far I haven't had a good answer for how to add reporter-specific args. Thanks for making a movement on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks claude