use std::collections::HashMap;
use std::fmt;
use crate::clang::*;
use crate::x86::*;
pub const X86_CLOUD_DEFAULT_REGION: &str = "us-east-1";
pub const X86_CLOUD_DEFAULT_AZ: &str = "us-east-1a";
pub const X86_CLOUD_MAX_CONTAINER_LAYERS: usize = 127;
pub const X86_CLOUD_DEFAULT_MEMORY_MB: usize = 128;
pub const X86_CLOUD_DEFAULT_TIMEOUT_SECS: u64 = 30;
pub const X86_CLOUD_DEFAULT_CPU_COUNT: usize = 1;
pub const X86_DOCKERFILE_SYNTAX: &str = "docker/dockerfile:1";
pub const X86_BUILDKIT_VERSION: &str = "0.12";
pub const X86_OCI_MEDIA_TYPE_MANIFEST: &str = "application/vnd.oci.image.manifest.v1+json";
pub const X86_OCI_MEDIA_TYPE_CONFIG: &str = "application/vnd.oci.image.config.v1+json";
pub const X86_OCI_MEDIA_TYPE_LAYER: &str = "application/vnd.oci.image.layer.v1.tar+gzip";
pub const X86_OCI_MEDIA_TYPE_LAYER_ZSTD: &str = "application/vnd.oci.image.layer.v1.tar+zstd";
pub const X86_K8S_API_VERSION: &str = "apps/v1";
pub const X86_K8S_CORE_API_VERSION: &str = "v1";
pub const X86_HELM_CHART_API_VERSION: &str = "v2";
pub const X86_GHA_RUNNER_UBUNTU: &str = "ubuntu-22.04";
pub const X86_GHA_RUNNER_WINDOWS: &str = "windows-2022";
pub const X86_GHA_RUNNER_MACOS: &str = "macos-13";
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86CloudProvider {
AWS,
Azure,
GCP,
Oracle,
IBM,
DigitalOcean,
Alibaba,
Cloudflare,
SelfHosted,
Custom(String),
}
impl X86CloudProvider {
pub fn as_str(&self) -> &str {
match self {
Self::AWS => "aws",
Self::Azure => "azure",
Self::GCP => "gcp",
Self::Oracle => "oracle",
Self::IBM => "ibm",
Self::DigitalOcean => "digitalocean",
Self::Alibaba => "alibaba",
Self::Cloudflare => "cloudflare",
Self::SelfHosted => "self-hosted",
Self::Custom(_) => "custom",
}
}
pub fn default_region(&self) -> &str {
match self {
Self::AWS => "us-east-1",
Self::Azure => "eastus",
Self::GCP => "us-central1",
Self::Oracle => "us-ashburn-1",
Self::IBM => "us-south",
Self::DigitalOcean => "nyc3",
Self::Alibaba => "us-east-1",
Self::Cloudflare => "auto",
Self::SelfHosted => "local",
Self::Custom(_) => "default",
}
}
pub fn container_registry_url(&self) -> &str {
match self {
Self::AWS => "public.ecr.aws",
Self::Azure => "mcr.microsoft.com",
Self::GCP => "gcr.io",
Self::Oracle => "container-registry.oracle.com",
Self::IBM => "icr.io",
Self::DigitalOcean => "registry.digitalocean.com",
Self::Alibaba => "registry.cn-hangzhou.aliyuncs.com",
Self::Cloudflare => "docker.io",
Self::SelfHosted => "localhost:5000",
Self::Custom(_) => "registry.example.com",
}
}
}
impl fmt::Display for X86CloudProvider {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86CloudTarget {
Container,
Serverless,
Kubernetes,
VM,
BareMetal,
Edge,
Hybrid,
}
impl X86CloudTarget {
pub fn as_str(&self) -> &str {
match self {
Self::Container => "container",
Self::Serverless => "serverless",
Self::Kubernetes => "kubernetes",
Self::VM => "vm",
Self::BareMetal => "bare-metal",
Self::Edge => "edge",
Self::Hybrid => "hybrid",
}
}
}
impl fmt::Display for X86CloudTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone)]
pub struct X86Cloud {
pub provider: X86CloudProvider,
pub region: String,
pub availability_zone: String,
pub target: X86CloudTarget,
pub container_support: X86ContainerSupport,
pub serverless_support: X86ServerlessSupport,
pub kubernetes_support: X86KubernetesSupport,
pub ci_cd_support: X86CI_CD_Support,
pub infra_as_code: X86InfraAsCode,
pub observability: X86Observability,
pub security: X86CloudSecurity,
pub enabled: bool,
pub verbose: bool,
pub profile: String,
pub project_name: String,
pub environment: String,
pub tags: HashMap<String, String>,
}
impl X86Cloud {
pub fn new(provider: X86CloudProvider, region: &str) -> Self {
let region_str = if region.is_empty() {
provider.default_region().to_string()
} else {
region.to_string()
};
Self {
provider,
region: region_str.clone(),
availability_zone: format!("{}{}", region_str, "a"),
target: X86CloudTarget::Container,
container_support: X86ContainerSupport::default(),
serverless_support: X86ServerlessSupport::default(),
kubernetes_support: X86KubernetesSupport::default(),
ci_cd_support: X86CI_CD_Support::default(),
infra_as_code: X86InfraAsCode::default(),
observability: X86Observability::default(),
security: X86CloudSecurity::default(),
enabled: true,
verbose: false,
profile: "default".to_string(),
project_name: "x86-cloud-app".to_string(),
environment: "development".to_string(),
tags: HashMap::new(),
}
}
pub fn aws_default() -> Self {
Self::new(X86CloudProvider::AWS, "us-east-1")
}
pub fn azure_default() -> Self {
Self::new(X86CloudProvider::Azure, "eastus")
}
pub fn gcp_default() -> Self {
Self::new(X86CloudProvider::GCP, "us-central1")
}
pub fn for_serverless() -> Self {
let mut cloud = Self::default();
cloud.target = X86CloudTarget::Serverless;
cloud.serverless_support = X86ServerlessSupport::full();
cloud
}
pub fn for_kubernetes() -> Self {
let mut cloud = Self::default();
cloud.target = X86CloudTarget::Kubernetes;
cloud.kubernetes_support = X86KubernetesSupport::full();
cloud
}
pub fn for_hybrid() -> Self {
let mut cloud = Self::default();
cloud.target = X86CloudTarget::Hybrid;
cloud.container_support = X86ContainerSupport::full();
cloud.serverless_support = X86ServerlessSupport::full();
cloud.kubernetes_support = X86KubernetesSupport::full();
cloud
}
pub fn with_tag(&mut self, key: &str, value: &str) -> &mut Self {
self.tags.insert(key.to_string(), value.to_string());
self
}
pub fn with_environment(&mut self, env: &str) -> &mut Self {
self.environment = env.to_string();
self
}
pub fn with_project(&mut self, name: &str) -> &mut Self {
self.project_name = name.to_string();
self
}
pub fn describe(&self) -> String {
let mut desc = format!(
"X86Cloud [{}] region={} az={} target={}\n",
self.provider, self.region, self.availability_zone, self.target
);
desc.push_str(&format!(" Project: {} / Environment: {}\n", self.project_name, self.environment));
desc.push_str(&format!(" Container: {}\n", if self.container_support.enabled { "enabled" } else { "disabled" }));
desc.push_str(&format!(" Serverless: {}\n", if self.serverless_support.enabled { "enabled" } else { "disabled" }));
desc.push_str(&format!(" Kubernetes: {}\n", if self.kubernetes_support.enabled { "enabled" } else { "disabled" }));
desc.push_str(&format!(" CI/CD: {}\n", if self.ci_cd_support.enabled { "enabled" } else { "disabled" }));
desc.push_str(&format!(" Observability: {}\n", if self.observability.enabled { "enabled" } else { "disabled" }));
desc.push_str(&format!(" Security: {}\n", if self.security.enabled { "enabled" } else { "disabled" }));
desc
}
pub fn to_json(&self) -> String {
format!(
r#"{{"provider":"{}","region":"{}","az":"{}","target":"{}","project":"{}","environment":"{}","enabled":{}}}"#,
self.provider, self.region, self.availability_zone, self.target,
self.project_name, self.environment, self.enabled
)
}
pub fn generate_all_artifacts(&self) -> X86CloudArtifactBundle {
let mut bundle = X86CloudArtifactBundle::new();
if self.container_support.enabled {
bundle.dockerfile = Some(self.container_support.generate_dockerfile());
bundle.oci_manifest = Some(self.container_support.generate_oci_manifest());
bundle.oci_config = Some(self.container_support.generate_oci_config());
}
if self.kubernetes_support.enabled {
bundle.k8s_deployment = Some(self.kubernetes_support.generate_deployment("x86-app", "myapp:latest"));
bundle.k8s_service = Some(self.kubernetes_support.generate_service("x86-app"));
bundle.k8s_configmap = Some(self.kubernetes_support.generate_configmap("x86-config"));
}
if self.ci_cd_support.enabled {
bundle.github_workflow = Some(self.ci_cd_support.generate_github_workflow());
bundle.gitlab_ci = Some(self.ci_cd_support.generate_gitlab_ci());
}
bundle
}
}
impl Default for X86Cloud {
fn default() -> Self {
Self::new(X86CloudProvider::AWS, "us-east-1")
}
}
#[derive(Debug, Clone, Default)]
pub struct X86CloudArtifactBundle {
pub dockerfile: Option<String>,
pub oci_manifest: Option<String>,
pub oci_config: Option<String>,
pub k8s_deployment: Option<String>,
pub k8s_service: Option<String>,
pub k8s_configmap: Option<String>,
pub github_workflow: Option<String>,
pub gitlab_ci: Option<String>,
pub helm_chart: Option<String>,
pub terraform_config: Option<String>,
pub serverless_config: Option<String>,
}
impl X86CloudArtifactBundle {
pub fn new() -> Self {
Self::default()
}
pub fn count(&self) -> usize {
let mut c = 0;
if self.dockerfile.is_some() { c += 1; }
if self.oci_manifest.is_some() { c += 1; }
if self.oci_config.is_some() { c += 1; }
if self.k8s_deployment.is_some() { c += 1; }
if self.k8s_service.is_some() { c += 1; }
if self.k8s_configmap.is_some() { c += 1; }
if self.github_workflow.is_some() { c += 1; }
if self.gitlab_ci.is_some() { c += 1; }
if self.helm_chart.is_some() { c += 1; }
if self.terraform_config.is_some() { c += 1; }
if self.serverless_config.is_some() { c += 1; }
c
}
pub fn artifacts(&self) -> Vec<String> {
let mut v = Vec::new();
if self.dockerfile.is_some() { v.push("Dockerfile".into()); }
if self.oci_manifest.is_some() { v.push("oci_manifest.json".into()); }
if self.oci_config.is_some() { v.push("oci_config.json".into()); }
if self.k8s_deployment.is_some() { v.push("k8s_deployment.yaml".into()); }
if self.k8s_service.is_some() { v.push("k8s_service.yaml".into()); }
if self.k8s_configmap.is_some() { v.push("k8s_configmap.yaml".into()); }
if self.github_workflow.is_some() { v.push(".github/workflows/ci.yml".into()); }
if self.gitlab_ci.is_some() { v.push(".gitlab-ci.yml".into()); }
if self.helm_chart.is_some() { v.push("helm/Chart.yaml".into()); }
if self.terraform_config.is_some() { v.push("terraform/main.tf".into()); }
if self.serverless_config.is_some() { v.push("serverless.yml".into()); }
v
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86ContainerBaseImage {
Alpine,
Ubuntu,
Debian,
CentOS,
RHEL,
Fedora,
AmazonLinux,
Distroless,
Scratch,
Custom(String),
}
impl X86ContainerBaseImage {
pub fn image_name(&self, tag: &str) -> String {
match self {
Self::Alpine => format!("alpine:{}", tag),
Self::Ubuntu => format!("ubuntu:{}", tag),
Self::Debian => format!("debian:{}", tag),
Self::CentOS => format!("centos:{}", tag),
Self::RHEL => format!("registry.access.redhat.com/ubi8/ubi:{}", tag),
Self::Fedora => format!("fedora:{}", tag),
Self::AmazonLinux => format!("amazonlinux:{}", tag),
Self::Distroless => format!("gcr.io/distroless/cc-debian12:{}", tag),
Self::Scratch => "scratch".to_string(),
Self::Custom(img) => img.clone(),
}
}
pub fn default_tag(&self) -> &str {
match self {
Self::Alpine => "3.19",
Self::Ubuntu => "22.04",
Self::Debian => "bookworm-slim",
Self::CentOS => "9",
Self::RHEL => "9.3",
Self::Fedora => "39",
Self::AmazonLinux => "2023",
Self::Distroless => "latest",
Self::Scratch => "",
Self::Custom(_) => "latest",
}
}
pub fn package_manager(&self) -> &str {
match self {
Self::Alpine => "apk",
Self::Ubuntu | Self::Debian => "apt-get",
Self::CentOS | Self::RHEL | Self::Fedora | Self::AmazonLinux => "yum",
Self::Distroless | Self::Scratch | Self::Custom(_) => "none",
}
}
}
impl fmt::Display for X86ContainerBaseImage {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Custom(s) => write!(f, "{}", s),
_ => write!(f, "{:?}", self),
}
}
}
#[derive(Debug, Clone)]
pub struct X86BuildStage {
pub name: String,
pub base_image: X86ContainerBaseImage,
pub base_tag: String,
pub run_commands: Vec<String>,
pub copy_instructions: Vec<(String, String)>,
pub env_vars: HashMap<String, String>,
pub args: HashMap<String, String>,
pub workdir: Option<String>,
pub user: Option<String>,
pub expose_ports: Vec<u16>,
pub volumes: Vec<String>,
pub healthcheck: Option<X86ContainerHealthcheck>,
pub is_final: bool,
pub entrypoint: Option<Vec<String>>,
pub cmd: Option<Vec<String>>,
pub labels: HashMap<String, String>,
pub build_args: HashMap<String, String>,
pub secrets: Vec<String>,
pub mounts: Vec<X86BuildMount>,
}
impl X86BuildStage {
pub fn new(name: &str, base: X86ContainerBaseImage) -> Self {
let tag = base.default_tag().to_string();
Self {
name: name.to_string(),
base_image: base,
base_tag: tag,
run_commands: Vec::new(),
copy_instructions: Vec::new(),
env_vars: HashMap::new(),
args: HashMap::new(),
workdir: None,
user: None,
expose_ports: Vec::new(),
volumes: Vec::new(),
healthcheck: None,
is_final: false,
entrypoint: None,
cmd: None,
labels: HashMap::new(),
build_args: HashMap::new(),
secrets: Vec::new(),
mounts: Vec::new(),
}
}
pub fn builder(name: &str) -> Self {
let mut stage = Self::new(name, X86ContainerBaseImage::Ubuntu);
stage.run_commands.push("apt-get update".into());
stage.run_commands.push("apt-get install -y build-essential clang cmake".into());
stage.workdir = Some("/build".into());
stage
}
pub fn runner(name: &str, base: X86ContainerBaseImage) -> Self {
let mut stage = Self::new(name, base);
stage.is_final = true;
stage
}
pub fn add_run(&mut self, cmd: &str) -> &mut Self {
self.run_commands.push(cmd.to_string());
self
}
pub fn add_copy(&mut self, from: &str, to: &str) -> &mut Self {
self.copy_instructions.push((from.to_string(), to.to_string()));
self
}
pub fn add_copy_from(&mut self, stage: &str, from: &str, to: &str) -> &mut Self {
self.copy_instructions.push((format!("--from={} {}", stage, from), to.to_string()));
self
}
pub fn add_env(&mut self, key: &str, value: &str) -> &mut Self {
self.env_vars.insert(key.to_string(), value.to_string());
self
}
pub fn add_arg(&mut self, key: &str, default: Option<&str>) -> &mut Self {
if let Some(val) = default {
self.args.insert(key.to_string(), val.to_string());
} else {
self.args.insert(key.to_string(), String::new());
}
self
}
pub fn with_workdir(&mut self, dir: &str) -> &mut Self {
self.workdir = Some(dir.to_string());
self
}
pub fn with_user(&mut self, user: &str) -> &mut Self {
self.user = Some(user.to_string());
self
}
pub fn with_entrypoint(&mut self, cmd: Vec<&str>) -> &mut Self {
self.entrypoint = Some(cmd.iter().map(|s| s.to_string()).collect());
self
}
pub fn with_cmd(&mut self, cmd: Vec<&str>) -> &mut Self {
self.cmd = Some(cmd.iter().map(|s| s.to_string()).collect());
self
}
pub fn generate(&self) -> String {
let mut out = String::new();
let image_tag = if self.base_tag.is_empty() {
self.base_image.image_name("")
} else {
self.base_image.image_name(&self.base_tag)
};
out.push_str(&format!("# Stage: {}\n", self.name));
out.push_str(&format!("FROM {} AS {}\n", image_tag, self.name));
for (k, v) in &self.args {
if v.is_empty() {
out.push_str(&format!("ARG {}\n", k));
} else {
out.push_str(&format!("ARG {}={}\n", k, v));
}
}
for k in self.build_args.keys() {
out.push_str(&format!("ARG {}\n", k));
out.push_str(&format!("RUN --mount=type=secret,id={} echo using {}\n", k, k));
}
for (k, v) in &self.labels {
out.push_str(&format!("LABEL {}=\"{}\"\n", k, v));
}
if let Some(ref wd) = self.workdir {
out.push_str(&format!("WORKDIR {}\n", wd));
}
if let Some(ref user) = self.user {
out.push_str(&format!("USER {}\n", user));
}
for (k, v) in &self.env_vars {
out.push_str(&format!("ENV {}=\"{}\"\n", k, v));
}
for cmd in &self.run_commands {
if cmd.contains('\n') {
out.push_str(&format!("RUN <<EOF\n{}\nEOF\n", cmd));
} else {
out.push_str(&format!("RUN {}\n", cmd));
}
}
for (from_src, dest) in &self.copy_instructions {
if from_src.starts_with("--from=") {
out.push_str(&format!("COPY {} {}\n", from_src, dest));
} else {
out.push_str(&format!("COPY {} {}\n", from_src, dest));
}
}
for port in &self.expose_ports {
out.push_str(&format!("EXPOSE {}\n", port));
}
for vol in &self.volumes {
out.push_str(&format!("VOLUME [\"{}\"]\n", vol));
}
if let Some(ref hc) = self.healthcheck {
out.push_str(&hc.generate());
}
if let Some(ref ep) = self.entrypoint {
let args: Vec<String> = ep.iter().map(|s| format!("\"{}\"", s)).collect();
out.push_str(&format!("ENTRYPOINT [{}]\n", args.join(", ")));
}
if let Some(ref cmd) = self.cmd {
let args: Vec<String> = cmd.iter().map(|s| format!("\"{}\"", s)).collect();
out.push_str(&format!("CMD [{}]\n", args.join(", ")));
}
out.push('\n');
out
}
}
#[derive(Debug, Clone)]
pub struct X86ContainerHealthcheck {
pub test: Vec<String>,
pub interval_secs: u64,
pub timeout_secs: u64,
pub retries: u64,
pub start_period_secs: u64,
pub start_interval_secs: u64,
}
impl X86ContainerHealthcheck {
pub fn new(test: Vec<&str>) -> Self {
Self {
test: test.iter().map(|s| s.to_string()).collect(),
interval_secs: 30,
timeout_secs: 5,
retries: 3,
start_period_secs: 5,
start_interval_secs: 5,
}
}
pub fn http_get(path: &str, port: u16) -> Self {
Self::new(vec!["CMD-SHELL", &format!("wget -qO- http://localhost:{}{} || exit 1", port, path)])
}
pub fn tcp_check(port: u16) -> Self {
Self::new(vec!["CMD-SHELL", &format!("nc -z localhost {} || exit 1", port)])
}
pub fn generate(&self) -> String {
let test_str: Vec<String> = self.test.iter().map(|s| format!("\"{}\"", s)).collect();
let mut out = format!("HEALTHCHECK --interval={}s --timeout={}s --retries={}",
self.interval_secs, self.timeout_secs, self.retries);
if self.start_period_secs > 0 {
out.push_str(&format!(" --start-period={}s", self.start_period_secs));
}
if self.start_interval_secs > 0 {
out.push_str(&format!(" --start-interval={}s", self.start_interval_secs));
}
out.push_str(&format!(" CMD [{}]\n", test_str.join(", ")));
out
}
}
#[derive(Debug, Clone)]
pub struct X86BuildMount {
pub mount_type: X86MountType,
pub source: Option<String>,
pub target: String,
pub read_only: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86MountType {
Bind,
Cache,
Tmpfs,
Secret,
SSH,
}
impl X86MountType {
pub fn as_str(&self) -> &str {
match self {
Self::Bind => "bind",
Self::Cache => "cache",
Self::Tmpfs => "tmpfs",
Self::Secret => "secret",
Self::SSH => "ssh",
}
}
}
impl X86BuildMount {
pub fn cache(target: &str) -> Self {
Self {
mount_type: X86MountType::Cache,
source: None,
target: target.to_string(),
read_only: false,
}
}
pub fn secret(id: &str, target: &str) -> Self {
Self {
mount_type: X86MountType::Secret,
source: Some(id.to_string()),
target: target.to_string(),
read_only: true,
}
}
pub fn bind(source: &str, target: &str) -> Self {
Self {
mount_type: X86MountType::Bind,
source: Some(source.to_string()),
target: target.to_string(),
read_only: false,
}
}
pub fn generate(&self) -> String {
let mut s = format!("--mount=type={}", self.mount_type.as_str());
if let Some(ref src) = self.source {
s.push_str(&format!(",source={}", src));
}
s.push_str(&format!(",target={}", self.target));
if self.read_only {
s.push_str(",readonly");
}
s
}
}
#[derive(Debug, Clone)]
pub struct X86OciLayer {
pub media_type: String,
pub digest: String,
pub size: u64,
pub annotations: HashMap<String, String>,
pub compressed: bool,
}
impl X86OciLayer {
pub fn new(digest: &str, size: u64) -> Self {
Self {
media_type: X86_OCI_MEDIA_TYPE_LAYER.to_string(),
digest: digest.to_string(),
size,
annotations: HashMap::new(),
compressed: true,
}
}
pub fn with_annotation(&mut self, key: &str, value: &str) -> &mut Self {
self.annotations.insert(key.to_string(), value.to_string());
self
}
pub fn to_json(&self) -> String {
let ann: Vec<String> = self.annotations.iter()
.map(|(k, v)| format!("\"{}\":\"{}\"", k, v))
.collect();
format!(
r#"{{"mediaType":"{}","digest":"{}","size":{},"annotations":{{{}}}}},"#,
self.media_type, self.digest, self.size, ann.join(",")
)
}
}
#[derive(Debug, Clone)]
pub struct X86OciManifest {
pub schema_version: u32,
pub media_type: String,
pub config: X86OciManifestConfig,
pub layers: Vec<X86OciLayer>,
pub annotations: HashMap<String, String>,
pub subject: Option<X86OciManifestSubject>,
}
#[derive(Debug, Clone)]
pub struct X86OciManifestConfig {
pub media_type: String,
pub digest: String,
pub size: u64,
}
impl X86OciManifestConfig {
pub fn new(digest: &str, size: u64) -> Self {
Self {
media_type: X86_OCI_MEDIA_TYPE_CONFIG.to_string(),
digest: digest.to_string(),
size,
}
}
}
#[derive(Debug, Clone)]
pub struct X86OciManifestSubject {
pub media_type: String,
pub digest: String,
pub size: u64,
}
impl X86OciManifest {
pub fn new(config_digest: &str, config_size: u64) -> Self {
Self {
schema_version: 2,
media_type: X86_OCI_MEDIA_TYPE_MANIFEST.to_string(),
config: X86OciManifestConfig::new(config_digest, config_size),
layers: Vec::new(),
annotations: HashMap::new(),
subject: None,
}
}
pub fn add_layer(&mut self, layer: X86OciLayer) -> &mut Self {
self.layers.push(layer);
self
}
pub fn to_json(&self) -> String {
let mut out = format!(
r#"{{"schemaVersion":{},"mediaType":"{}","config":{{"mediaType":"{}","digest":"{}","size":{}}},"#,
self.schema_version,
self.media_type,
self.config.media_type,
self.config.digest,
self.config.size,
);
out.push_str("\"layers\":[");
for (i, layer) in self.layers.iter().enumerate() {
if i > 0 { out.push(','); }
let lj = layer.to_json();
out.push_str(&lj[..lj.len()-1]); }
out.push_str("]");
if let Some(ref subject) = self.subject {
out.push_str(&format!(
r#","subject":{{"mediaType":"{}","digest":"{}","size":{}}}"#,
subject.media_type, subject.digest, subject.size
));
}
out.push('}');
out
}
}
#[derive(Debug, Clone)]
pub struct X86OciImageConfig {
pub created: String,
pub author: String,
pub architecture: String,
pub os: String,
pub os_version: Option<String>,
pub os_features: Vec<String>,
pub variant: Option<String>,
pub config: X86OciRuntimeConfig,
pub rootfs: X86OciRootfs,
pub history: Vec<X86OciHistory>,
}
#[derive(Debug, Clone)]
pub struct X86OciRuntimeConfig {
pub user: Option<String>,
pub exposed_ports: HashMap<String, serde_json::Value>,
pub env: Vec<String>,
pub entrypoint: Vec<String>,
pub cmd: Vec<String>,
pub volumes: HashMap<String, serde_json::Value>,
pub working_dir: Option<String>,
pub labels: HashMap<String, String>,
pub stop_signal: Option<String>,
pub healthcheck: Option<X86OciHealthcheck>,
}
mod serde_json {
#[derive(Debug, Clone)]
pub enum Value {
Object,
}
}
#[derive(Debug, Clone)]
pub struct X86OciHealthcheck {
pub test: Vec<String>,
pub interval_ns: u64,
pub timeout_ns: u64,
pub retries: u64,
}
#[derive(Debug, Clone)]
pub struct X86OciRootfs {
pub r#type: String,
pub diff_ids: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86OciHistory {
pub created: String,
pub created_by: String,
pub empty_layer: bool,
pub comment: Option<String>,
}
impl X86OciImageConfig {
pub fn new_x86_64() -> Self {
Self {
created: "2024-01-01T00:00:00Z".to_string(),
author: "clang-cloud-x86".to_string(),
architecture: "amd64".to_string(),
os: "linux".to_string(),
os_version: None,
os_features: vec!["x86_64-v3".to_string()],
variant: None,
config: X86OciRuntimeConfig {
user: None,
exposed_ports: HashMap::new(),
env: Vec::new(),
entrypoint: Vec::new(),
cmd: Vec::new(),
volumes: HashMap::new(),
working_dir: None,
labels: HashMap::new(),
stop_signal: None,
healthcheck: None,
},
rootfs: X86OciRootfs {
r#type: "layers".to_string(),
diff_ids: Vec::new(),
},
history: Vec::new(),
}
}
pub fn to_json(&self) -> String {
let env_str: Vec<String> = self.config.env.iter().map(|e| format!("\"{}\"", e)).collect();
let ep_str: Vec<String> = self.config.entrypoint.iter().map(|e| format!("\"{}\"", e)).collect();
let cmd_str: Vec<String> = self.config.cmd.iter().map(|e| format!("\"{}\"", e)).collect();
let labels: Vec<String> = self.config.labels.iter().map(|(k,v)| format!("\"{}\":\"{}\"", k, v)).collect();
let diff_ids: Vec<String> = self.rootfs.diff_ids.iter().map(|d| format!("\"{}\"", d)).collect();
format!(
concat!(
r#"{{"created":"{}","author":"{}","architecture":"{}","os":"{}","#,
r#""config":{{"Env":[{}],"Entrypoint":[{}],"Cmd":[{}],"Labels":{{{}}}}},"#,
r#""rootfs":{{"type":"{}","diff_ids":[{}]}},"#,
r#""history":[]}}"#
),
self.created, self.author, self.architecture, self.os,
env_str.join(","), ep_str.join(","), cmd_str.join(","), labels.join(","),
self.rootfs.r#type, diff_ids.join(","),
)
}
}
#[derive(Debug, Clone)]
pub struct X86ContainerRegistry {
pub registry_url: String,
pub auth_type: X86RegistryAuthType,
pub repository: String,
pub tag: String,
pub namespace: Option<String>,
pub region: Option<String>,
pub credentials: Option<X86RegistryCredentials>,
}
#[derive(Debug, Clone)]
pub enum X86RegistryAuthType {
None,
Basic,
BearerToken(String),
AWSECR,
GCPAccessToken,
AzureServicePrincipal,
OAuth,
CustomHeader(String, String),
}
impl X86RegistryAuthType {
pub fn auth_header(&self) -> Option<String> {
match self {
Self::None => None,
Self::Basic => Some("Basic <base64-creds>".into()),
Self::BearerToken(token) => Some(format!("Bearer {}", token)),
Self::AWSECR => Some("AWS4-HMAC-SHA256 <credentials>".into()),
Self::GCPAccessToken => Some("Bearer <gcp-access-token>".into()),
Self::AzureServicePrincipal => Some("Basic <sp-credentials>".into()),
Self::OAuth => Some("Bearer <oauth-token>".into()),
Self::CustomHeader(k, v) => Some(format!("{} {}", k, v)),
}
}
}
#[derive(Debug, Clone)]
pub struct X86RegistryCredentials {
pub username: String,
pub password: String,
pub access_key_id: Option<String>,
pub secret_access_key: Option<String>,
pub session_token: Option<String>,
}
impl X86RegistryCredentials {
pub fn basic(username: &str, password: &str) -> Self {
Self {
username: username.to_string(),
password: password.to_string(),
access_key_id: None,
secret_access_key: None,
session_token: None,
}
}
pub fn aws_ecr(key_id: &str, secret: &str, token: Option<&str>) -> Self {
Self {
username: "AWS".to_string(),
password: "".to_string(),
access_key_id: Some(key_id.to_string()),
secret_access_key: Some(secret.to_string()),
session_token: token.map(|s| s.to_string()),
}
}
}
impl X86ContainerRegistry {
pub fn dockerhub(username: &str, repo: &str, tag: &str) -> Self {
Self {
registry_url: "registry-1.docker.io".to_string(),
auth_type: X86RegistryAuthType::Basic,
repository: format!("{}/{}", username, repo),
tag: tag.to_string(),
namespace: Some(username.to_string()),
region: None,
credentials: None,
}
}
pub fn ecr(account_id: &str, repo: &str, region: &str) -> Self {
Self {
registry_url: format!("{}.dkr.ecr.{}.amazonaws.com", account_id, region),
auth_type: X86RegistryAuthType::AWSECR,
repository: repo.to_string(),
tag: "latest".to_string(),
namespace: None,
region: Some(region.to_string()),
credentials: None,
}
}
pub fn gcr(project: &str, repo: &str, region: &str) -> Self {
Self {
registry_url: format!("{}-docker.pkg.dev/{}/{}", region, project, repo),
auth_type: X86RegistryAuthType::GCPAccessToken,
repository: repo.to_string(),
tag: "latest".to_string(),
namespace: Some(project.to_string()),
region: Some(region.to_string()),
credentials: None,
}
}
pub fn acr(registry_name: &str, repo: &str) -> Self {
Self {
registry_url: format!("{}.azurecr.io", registry_name),
auth_type: X86RegistryAuthType::AzureServicePrincipal,
repository: repo.to_string(),
tag: "latest".to_string(),
namespace: None,
region: None,
credentials: None,
}
}
pub fn full_image_path(&self) -> String {
format!("{}/{}:{}", self.registry_url, self.repository, self.tag)
}
pub fn push_command(&self) -> String {
format!("docker push {}", self.full_image_path())
}
pub fn pull_command(&self) -> String {
format!("docker pull {}", self.full_image_path())
}
pub fn login_command(&self) -> String {
match self.auth_type {
X86RegistryAuthType::AWSECR => {
let region = self.region.as_deref().unwrap_or("us-east-1");
let url_parts: Vec<&str> = self.registry_url.split('/').collect();
let registry = url_parts.first().unwrap_or(&"");
format!("aws ecr get-login-password --region {} | docker login --username AWS --password-stdin {}", region, registry)
}
X86RegistryAuthType::GCPAccessToken => {
format!("gcloud auth configure-docker {}", self.registry_url)
}
X86RegistryAuthType::AzureServicePrincipal => {
format!("az acr login --name {}", self.registry_url.trim_end_matches(".azurecr.io"))
}
_ => format!("docker login {} -u <username> -p <password>", self.registry_url),
}
}
}
#[derive(Debug, Clone)]
pub struct X86ContainerSupport {
pub enabled: bool,
pub buildkit_enabled: bool,
pub base_image: X86ContainerBaseImage,
pub base_tag: String,
pub multi_stage: bool,
pub stages: Vec<X86BuildStage>,
pub registry: Option<X86ContainerRegistry>,
pub cache_from: Vec<String>,
pub cache_to: Option<String>,
pub platforms: Vec<String>,
pub output_type: X86BuildOutputType,
pub build_args: HashMap<String, String>,
pub secrets: Vec<String>,
pub ssh_agents: Vec<String>,
pub layer_compression: X86LayerCompression,
pub provenance_enabled: bool,
pub sbom_enabled: bool,
pub image_name: String,
pub image_tag: String,
pub extra_labels: HashMap<String, String>,
pub target_stage: Option<String>,
pub no_cache: bool,
pub pull_base: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86BuildOutputType {
Docker,
OCI,
Tar,
LocalDirectory,
Registry,
MultiPlatform,
}
impl X86BuildOutputType {
pub fn buildx_type(&self) -> &str {
match self {
Self::Docker => "type=docker",
Self::OCI => "type=oci,dest=image.tar",
Self::Tar => "type=tar,dest=image.tar",
Self::LocalDirectory => "type=local,dest=./output",
Self::Registry => "type=image,push=true",
Self::MultiPlatform => "type=image,push=true",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86LayerCompression {
Gzip,
Zstd,
Uncompressed,
EStargz,
}
impl X86LayerCompression {
pub fn media_type(&self) -> &str {
match self {
Self::Gzip => X86_OCI_MEDIA_TYPE_LAYER,
Self::Zstd => X86_OCI_MEDIA_TYPE_LAYER_ZSTD,
Self::Uncompressed => "application/vnd.oci.image.layer.v1.tar",
Self::EStargz => "application/vnd.oci.image.layer.v1.tar+gzip",
}
}
pub fn compression_flag(&self) -> &str {
match self {
Self::Gzip => "gzip",
Self::Zstd => "zstd",
Self::Uncompressed => "uncompressed",
Self::EStargz => "estargz",
}
}
}
impl X86ContainerSupport {
pub fn new() -> Self {
Self {
enabled: true,
buildkit_enabled: true,
base_image: X86ContainerBaseImage::Ubuntu,
base_tag: "22.04".to_string(),
multi_stage: true,
stages: Vec::new(),
registry: None,
cache_from: Vec::new(),
cache_to: None,
platforms: vec!["linux/amd64".to_string()],
output_type: X86BuildOutputType::Docker,
build_args: HashMap::new(),
secrets: Vec::new(),
ssh_agents: Vec::new(),
layer_compression: X86LayerCompression::Gzip,
provenance_enabled: true,
sbom_enabled: true,
image_name: "x86-app".to_string(),
image_tag: "latest".to_string(),
extra_labels: HashMap::new(),
target_stage: None,
no_cache: false,
pull_base: true,
}
}
pub fn full() -> Self {
let mut cs = Self::new();
cs.multi_stage = true;
cs.buildkit_enabled = true;
cs.provenance_enabled = true;
cs.sbom_enabled = true;
cs.platforms = vec!["linux/amd64".to_string(), "linux/arm64".to_string()];
cs
}
pub fn minimal() -> Self {
let mut cs = Self::new();
cs.multi_stage = false;
cs.buildkit_enabled = false;
cs.provenance_enabled = false;
cs.sbom_enabled = false;
cs
}
pub fn add_stage(&mut self, stage: X86BuildStage) -> &mut Self {
self.stages.push(stage);
self
}
pub fn with_registry(&mut self, registry: X86ContainerRegistry) -> &mut Self {
self.registry = Some(registry);
self
}
pub fn generate_dockerfile(&self) -> String {
let mut out = String::new();
out.push_str(&format!("# syntax={}\n", X86_DOCKERFILE_SYNTAX));
out.push_str("# Auto-generated by clang-cloud-x86\n\n");
out.push_str("ARG BUILDKIT_SYNTAX=1\n");
for (k, v) in &self.build_args {
out.push_str(&format!("ARG {}={}\n", k, v));
}
out.push('\n');
for stage in &self.stages {
out.push_str(&stage.generate());
}
if self.stages.is_empty() {
let mut default_stage = X86BuildStage::builder("build");
default_stage.add_run("cmake -B build -DCMAKE_BUILD_TYPE=Release");
default_stage.add_run("cmake --build build --parallel $(nproc)");
let build_output = default_stage.generate();
out.push_str(&build_output);
let mut runner = X86BuildStage::runner("runtime", self.base_image.clone());
runner.add_copy_from("build", "/build/output", "/app");
runner.with_workdir("/app");
runner.with_entrypoint(vec!["/app/x86-app"]);
runner.with_cmd(vec!["--help"]);
let runner_output = runner.generate();
out.push_str(&runner_output);
}
out
}
pub fn generate_oci_manifest(&self) -> String {
let manifest = X86OciManifest::new(
"sha256:0000000000000000000000000000000000000000000000000000000000000000",
1024,
);
manifest.to_json()
}
pub fn generate_oci_config(&self) -> String {
let mut config = X86OciImageConfig::new_x86_64();
if !self.platforms.is_empty() {
config.os_features = self.platforms.clone();
}
config.to_json()
}
pub fn buildx_command(&self) -> String {
let mut cmd = String::from("docker buildx build");
if self.buildkit_enabled {
cmd.push_str(" --builder=buildkit");
}
for cache in &self.cache_from {
cmd.push_str(&format!(" --cache-from type=registry,ref={}", cache));
}
if let Some(ref cache_to) = self.cache_to {
cmd.push_str(&format!(" --cache-to type=registry,ref={},mode=max", cache_to));
}
for platform in &self.platforms {
cmd.push_str(&format!(" --platform {}", platform));
}
for (k, v) in &self.build_args {
cmd.push_str(&format!(" --build-arg {}={}", k, v));
}
for secret in &self.secrets {
cmd.push_str(&format!(" --secret id={}", secret));
}
if self.provenance_enabled {
cmd.push_str(" --provenance=true");
}
if self.sbom_enabled {
cmd.push_str(" --sbom=true");
}
if self.no_cache {
cmd.push_str(" --no-cache");
}
if self.pull_base {
cmd.push_str(" --pull");
}
cmd.push_str(&format!(" --output {}", self.output_type.buildx_type()));
cmd.push_str(&format!(" -t {}:{}", self.image_name, self.image_tag));
if let Some(ref target) = self.target_stage {
cmd.push_str(&format!(" --target {}", target));
}
cmd.push_str(" .");
cmd
}
pub fn describe(&self) -> String {
let mut d = format!(
"X86ContainerSupport image={}:{} buildkit={} multi_stage={}\n",
self.image_name, self.image_tag, self.buildkit_enabled, self.multi_stage
);
d.push_str(&format!(" Platforms: {:?}\n", self.platforms));
d.push_str(&format!(" Stages: {}\n", self.stages.len()));
d.push_str(&format!(" Output: {:?}\n", self.output_type));
d.push_str(&format!(" Compression: {:?}\n", self.layer_compression));
if let Some(ref reg) = self.registry {
d.push_str(&format!(" Registry: {}\n", reg.full_image_path()));
}
d
}
}
impl Default for X86ContainerSupport {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86ServerlessPlatform {
AWSLambda,
AzureFunctions,
GoogleCloudFunctions,
CloudflareWorkers,
NetlifyFunctions,
VercelFunctions,
Custom(String),
}
impl X86ServerlessPlatform {
pub fn as_str(&self) -> &str {
match self {
Self::AWSLambda => "aws_lambda",
Self::AzureFunctions => "azure_functions",
Self::GoogleCloudFunctions => "gcp_cloud_functions",
Self::CloudflareWorkers => "cloudflare_workers",
Self::NetlifyFunctions => "netlify_functions",
Self::VercelFunctions => "vercel_functions",
Self::Custom(_) => "custom",
}
}
pub fn runtime_identifier(&self) -> &str {
match self {
Self::AWSLambda => "provided.al2",
Self::AzureFunctions => "custom",
Self::GoogleCloudFunctions => "custom",
Self::CloudflareWorkers => "javascript",
Self::NetlifyFunctions => "custom",
Self::VercelFunctions => "custom",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86AwsLambdaEventType {
ApiGatewayV1,
ApiGatewayV2,
S3,
DynamoDB,
SQS,
SNS,
EventBridge,
Kinesis,
CloudWatchLogs,
CloudFront,
Cognito,
Config,
CodeCommit,
CodePipeline,
Lex,
Alexa,
StepFunctions,
AppSync,
Custom(String),
}
impl X86AwsLambdaEventType {
pub fn struct_name(&self) -> &str {
match self {
Self::ApiGatewayV1 => "ApiGatewayProxyRequest",
Self::ApiGatewayV2 => "ApiGatewayV2Request",
Self::S3 => "S3Event",
Self::DynamoDB => "DynamoDbEvent",
Self::SQS => "SqsEvent",
Self::SNS => "SnsEvent",
Self::EventBridge => "EventBridgeEvent",
Self::Kinesis => "KinesisEvent",
Self::CloudWatchLogs => "CloudWatchLogsEvent",
Self::CloudFront => "CloudFrontEvent",
Self::Cognito => "CognitoEvent",
Self::Config => "ConfigEvent",
Self::CodeCommit => "CodeCommitEvent",
Self::CodePipeline => "CodePipelineEvent",
Self::Lex => "LexEvent",
Self::Alexa => "AlexaEvent",
Self::StepFunctions => "StepFunctionsEvent",
Self::AppSync => "AppSyncEvent",
Self::Custom(_) => "CustomEvent",
}
}
pub fn header_file(&self) -> &str {
match self {
Self::ApiGatewayV1 | Self::ApiGatewayV2 => "aws/lambda/api_gateway.h",
Self::S3 => "aws/lambda/s3_event.h",
Self::DynamoDB => "aws/lambda/dynamodb_event.h",
Self::SQS => "aws/lambda/sqs_event.h",
Self::SNS => "aws/lambda/sns_event.h",
Self::EventBridge => "aws/lambda/eventbridge_event.h",
Self::Kinesis => "aws/lambda/kinesis_event.h",
Self::CloudWatchLogs => "aws/lambda/cloudwatch_logs.h",
_ => "aws/lambda/custom_event.h",
}
}
}
#[derive(Debug, Clone)]
pub struct X86AwsLambdaContext {
pub function_name: String,
pub function_version: String,
pub invoked_function_arn: String,
pub memory_limit_mb: usize,
pub aws_request_id: String,
pub log_group_name: String,
pub log_stream_name: String,
pub identity: Option<X86AwsCognitoIdentity>,
pub client_context: Option<X86AwsClientContext>,
pub deadline_ms: u64,
pub xray_trace_id: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86AwsCognitoIdentity {
pub cognito_identity_id: String,
pub cognito_identity_pool_id: String,
}
#[derive(Debug, Clone)]
pub struct X86AwsClientContext {
pub client: X86AwsClientContextClient,
pub env: HashMap<String, String>,
pub custom: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct X86AwsClientContextClient {
pub installation_id: String,
pub app_title: String,
pub app_version_name: String,
pub app_version_code: String,
pub app_package_name: String,
}
impl X86AwsLambdaContext {
pub fn new(function_name: &str, request_id: &str) -> Self {
Self {
function_name: function_name.to_string(),
function_version: "$LATEST".to_string(),
invoked_function_arn: format!("arn:aws:lambda:us-east-1:123456789012:function:{}", function_name),
memory_limit_mb: 128,
aws_request_id: request_id.to_string(),
log_group_name: format!("/aws/lambda/{}", function_name),
log_stream_name: "2024/01/01/[$LATEST]abc123".to_string(),
identity: None,
client_context: None,
deadline_ms: 30000,
xray_trace_id: None,
}
}
pub fn remaining_time_ms(&self) -> u64 {
self.deadline_ms.saturating_sub(0)
}
}
#[derive(Debug, Clone)]
pub struct X86AwsLambdaFunction {
pub name: String,
pub handler: String,
pub runtime: String,
pub memory_mb: usize,
pub timeout_secs: u64,
pub event_types: Vec<X86AwsLambdaEventType>,
pub environment: HashMap<String, String>,
pub vpc_config: Option<X86AwsLambdaVpcConfig>,
pub layers: Vec<String>,
pub reserved_concurrency: Option<usize>,
pub provisioned_concurrency: Option<usize>,
pub architectures: Vec<String>,
pub ephemeral_storage_mb: usize,
pub tracing_mode: X86AwsLambdaTracingMode,
pub destinations: X86AwsLambdaDestinations,
}
#[derive(Debug, Clone)]
pub struct X86AwsLambdaVpcConfig {
pub subnet_ids: Vec<String>,
pub security_group_ids: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AwsLambdaTracingMode {
Active,
PassThrough,
}
impl X86AwsLambdaTracingMode {
pub fn as_str(&self) -> &str {
match self {
Self::Active => "Active",
Self::PassThrough => "PassThrough",
}
}
}
#[derive(Debug, Clone, Default)]
pub struct X86AwsLambdaDestinations {
pub on_success: Option<String>,
pub on_failure: Option<String>,
}
impl X86AwsLambdaFunction {
pub fn new(name: &str, handler: &str) -> Self {
Self {
name: name.to_string(),
handler: handler.to_string(),
runtime: "provided.al2".to_string(),
memory_mb: 128,
timeout_secs: 30,
event_types: vec![X86AwsLambdaEventType::ApiGatewayV2],
environment: HashMap::new(),
vpc_config: None,
layers: Vec::new(),
reserved_concurrency: None,
provisioned_concurrency: None,
architectures: vec!["x86_64".to_string()],
ephemeral_storage_mb: 512,
tracing_mode: X86AwsLambdaTracingMode::PassThrough,
destinations: X86AwsLambdaDestinations::default(),
}
}
pub fn generate_cfn_resource(&self) -> String {
let mut yaml = format!(
" {}:\n Type: AWS::Lambda::Function\n Properties:\n FunctionName: {}\n Handler: {}\n Runtime: {}\n MemorySize: {}\n Timeout: {}\n Architectures:\n - {}\n EphemeralStorage:\n Size: {}\n TracingConfig:\n Mode: {}\n",
self.name, self.name, self.handler, self.runtime,
self.memory_mb, self.timeout_secs,
self.architectures.join("\n - "),
self.ephemeral_storage_mb,
self.tracing_mode.as_str()
);
if !self.environment.is_empty() {
yaml.push_str(" Environment:\n Variables:\n");
for (k, v) in &self.environment {
yaml.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
if let Some(ref vpc) = self.vpc_config {
yaml.push_str(" VpcConfig:\n");
yaml.push_str(" SubnetIds:\n");
for sn in &vpc.subnet_ids {
yaml.push_str(&format!(" - {}\n", sn));
}
yaml.push_str(" SecurityGroupIds:\n");
for sg in &vpc.security_group_ids {
yaml.push_str(&format!(" - {}\n", sg));
}
}
if !self.layers.is_empty() {
yaml.push_str(" Layers:\n");
for layer in &self.layers {
yaml.push_str(&format!(" - {}\n", layer));
}
}
if let Some(rc) = self.reserved_concurrency {
yaml.push_str(&format!(" ReservedConcurrentExecutions: {}\n", rc));
}
yaml
}
pub fn generate_cpp_handler(&self) -> String {
let event_type = self.event_types.first()
.map(|e| e.struct_name())
.unwrap_or("CustomEvent");
format!(
r#"#include <aws/lambda/runtime.h>
#include "aws/lambda/context.h"
using namespace aws::lambda_runtime;
invocation_response my_handler({} const& event, context const& ctx) {{
// X86-optimized Lambda handler for {}
auto request_id = ctx.get_request_id();
auto function_name = ctx.get_function_name();
auto remaining = ctx.get_remaining_time_in_millis();
// Process event...
(void)event;
return invocation_response::success(
R"({{"statusCode": 200, "body": "OK"}})",
"application/json"
);
}}
int main() {{
run_handler(my_handler);
return 0;
}}
"#,
event_type, self.name
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86AzureTriggerType {
Http,
Timer,
Queue,
Blob,
CosmosDB,
EventHub,
ServiceBus,
EventGrid,
SignalR,
DurableFunctions,
Kafka,
RabbitMQ,
Custom(String),
}
impl X86AzureTriggerType {
pub fn binding_type(&self) -> &str {
match self {
Self::Http => "httpTrigger",
Self::Timer => "timerTrigger",
Self::Queue => "queueTrigger",
Self::Blob => "blobTrigger",
Self::CosmosDB => "cosmosDBTrigger",
Self::EventHub => "eventHubTrigger",
Self::ServiceBus => "serviceBusTrigger",
Self::EventGrid => "eventGridTrigger",
Self::SignalR => "signalRTrigger",
Self::DurableFunctions => "orchestrationTrigger",
Self::Kafka => "kafkaTrigger",
Self::RabbitMQ => "rabbitMQTrigger",
Self::Custom(_) => "customTrigger",
}
}
pub fn direction(&self) -> &str {
match self {
Self::DurableFunctions => "inout",
_ => "in",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86AzureOutputBinding {
Http,
Queue,
Blob,
CosmosDB,
Table,
EventHub,
ServiceBus,
EventGrid,
SignalR,
SendGrid,
TwilioSms,
Custom(String),
}
impl X86AzureOutputBinding {
pub fn binding_type(&self) -> &str {
match self {
Self::Http => "http",
Self::Queue => "queue",
Self::Blob => "blob",
Self::CosmosDB => "cosmosDB",
Self::Table => "table",
Self::EventHub => "eventHub",
Self::ServiceBus => "serviceBus",
Self::EventGrid => "eventGrid",
Self::SignalR => "signalR",
Self::SendGrid => "sendGrid",
Self::TwilioSms => "twilioSms",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone)]
pub struct X86AzureFunction {
pub name: String,
pub trigger: X86AzureTriggerType,
pub output_bindings: Vec<X86AzureOutputBinding>,
pub direction: String,
pub auth_level: X86AzureAuthLevel,
pub route: Option<String>,
pub methods: Vec<String>,
pub schedule: Option<String>,
pub queue_name: Option<String>,
pub connection: Option<String>,
pub container_name: Option<String>,
pub database_name: Option<String>,
pub collection_name: Option<String>,
pub is_disabled: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86AzureAuthLevel {
Anonymous,
Function,
Admin,
System,
}
impl X86AzureAuthLevel {
pub fn as_str(&self) -> &str {
match self {
Self::Anonymous => "anonymous",
Self::Function => "function",
Self::Admin => "admin",
Self::System => "system",
}
}
}
impl X86AzureFunction {
pub fn http_trigger(name: &str, route: &str) -> Self {
Self {
name: name.to_string(),
trigger: X86AzureTriggerType::Http,
output_bindings: vec![X86AzureOutputBinding::Http],
direction: "in".to_string(),
auth_level: X86AzureAuthLevel::Function,
route: Some(route.to_string()),
methods: vec!["GET".into(), "POST".into()],
schedule: None,
queue_name: None,
connection: None,
container_name: None,
database_name: None,
collection_name: None,
is_disabled: false,
}
}
pub fn timer_trigger(name: &str, schedule: &str) -> Self {
Self {
name: name.to_string(),
trigger: X86AzureTriggerType::Timer,
output_bindings: Vec::new(),
direction: "in".to_string(),
auth_level: X86AzureAuthLevel::Anonymous,
route: None,
methods: Vec::new(),
schedule: Some(schedule.to_string()),
queue_name: None,
connection: None,
container_name: None,
database_name: None,
collection_name: None,
is_disabled: false,
}
}
pub fn queue_trigger(name: &str, queue: &str, connection: &str) -> Self {
Self {
name: name.to_string(),
trigger: X86AzureTriggerType::Queue,
output_bindings: vec![X86AzureOutputBinding::Queue],
direction: "in".to_string(),
auth_level: X86AzureAuthLevel::Anonymous,
route: None,
methods: Vec::new(),
schedule: None,
queue_name: Some(queue.to_string()),
connection: Some(connection.to_string()),
container_name: None,
database_name: None,
collection_name: None,
is_disabled: false,
}
}
pub fn generate_function_json(&self) -> String {
let mut json = format!(
r#"{{"bindings":["#,
);
json.push_str(&format!(
r#"{{"name":"{}","type":"{}","direction":"{}""#,
self.name,
self.trigger.binding_type(),
self.trigger.direction()
));
match self.trigger {
X86AzureTriggerType::Http => {
json.push_str(&format!(
r#","authLevel":"{}","methods":[{}]"#,
self.auth_level.as_str(),
self.methods.iter().map(|m| format!("\"{}\"", m)).collect::<Vec<_>>().join(",")
));
if let Some(ref route) = self.route {
json.push_str(&format!(r#","route":"{}""#, route));
}
}
X86AzureTriggerType::Timer => {
if let Some(ref sched) = self.schedule {
json.push_str(&format!(r#","schedule":"{}""#, sched));
}
}
X86AzureTriggerType::Queue => {
if let Some(ref qn) = self.queue_name {
json.push_str(&format!(r#","queueName":"{}""#, qn));
}
if let Some(ref conn) = self.connection {
json.push_str(&format!(r#","connection":"{}""#, conn));
}
}
X86AzureTriggerType::Blob => {
if let Some(ref container) = self.container_name {
json.push_str(&format!(r#","path":"{}/{{name}}""#, container));
}
if let Some(ref conn) = self.connection {
json.push_str(&format!(r#","connection":"{}""#, conn));
}
}
X86AzureTriggerType::CosmosDB => {
if let Some(ref db) = self.database_name {
json.push_str(&format!(r#","databaseName":"{}""#, db));
}
if let Some(ref coll) = self.collection_name {
json.push_str(&format!(r#","collectionName":"{}""#, coll));
}
if let Some(ref conn) = self.connection {
json.push_str(&format!(r#","connection":"{}""#, conn));
}
}
_ => {}
}
json.push_str("}");
for ob in &self.output_bindings {
json.push_str(&format!(
r#",{{"name":"{}_out","type":"{}","direction":"out"}}"#,
self.name,
ob.binding_type()
));
}
json.push_str("]}");
json
}
pub fn generate_cpp_handler(&self) -> String {
format!(
r#"// Azure Function: {}
// Trigger: {:?}
// X86-optimized custom handler
#include <cstdlib>
#include <string>
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
extern "C" int azure_function_handler(
const char* input_json,
char** output_json
) {{
rapidjson::Document doc;
doc.Parse(input_json);
rapidjson::Document response;
response.SetObject();
auto& allocator = response.GetAllocator();
response.AddMember("status", 200, allocator);
// Process input based on trigger type
if (doc.HasMember("Data")) {{
// Custom handler invocation
}}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
response.Accept(writer);
*output_json = strdup(buffer.GetString());
return 0;
}}
"#,
self.name, self.trigger
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86GcpEventType {
Storage,
PubSub,
Firestore,
HTTP,
RemoteConfig,
Analytics,
Auth,
Database,
Crashlytics,
Performance,
Custom(String),
}
impl X86GcpEventType {
pub fn event_type_str(&self) -> &str {
match self {
Self::Storage => "google.storage.object.finalize",
Self::PubSub => "google.pubsub.topic.publish",
Self::Firestore => "google.cloud.firestore.document.v1.written",
Self::HTTP => "http",
Self::RemoteConfig => "google.firebase.remoteconfig.remoteConfig.v1.updated",
Self::Analytics => "google.firebase.analytics.log.v1.written",
Self::Auth => "providers/firebase.auth/eventTypes/user.create",
Self::Database => "providers/google.firebase.database/eventTypes/ref.write",
Self::Crashlytics => "google.firebase.crashlytics.issue.v1.new",
Self::Performance => "google.firebase.performance.metric.v1.written",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone)]
pub struct X86GcpFunction {
pub name: String,
pub region: String,
pub runtime: String,
pub entry_point: String,
pub event_type: X86GcpEventType,
pub memory_mb: usize,
pub timeout_secs: u64,
pub max_instances: usize,
pub min_instances: usize,
pub environment: HashMap<String, String>,
pub vpc_connector: Option<String>,
pub service_account: Option<String>,
pub ingress_settings: X86GcpIngressSettings,
pub source_dir: String,
pub build_env_vars: HashMap<String, String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86GcpIngressSettings {
AllowAll,
AllowInternalOnly,
AllowInternalAndGclb,
}
impl X86GcpIngressSettings {
pub fn flag(&self) -> &str {
match self {
Self::AllowAll => "all",
Self::AllowInternalOnly => "internal-only",
Self::AllowInternalAndGclb => "internal-and-gclb",
}
}
}
impl X86GcpFunction {
pub fn new(name: &str, entry_point: &str) -> Self {
Self {
name: name.to_string(),
region: "us-central1".to_string(),
runtime: "custom".to_string(),
entry_point: entry_point.to_string(),
event_type: X86GcpEventType::HTTP,
memory_mb: 256,
timeout_secs: 60,
max_instances: 100,
min_instances: 0,
environment: HashMap::new(),
vpc_connector: None,
service_account: None,
ingress_settings: X86GcpIngressSettings::AllowAll,
source_dir: ".".to_string(),
build_env_vars: HashMap::new(),
}
}
pub fn gcloud_deploy_command(&self) -> String {
let mut cmd = format!(
"gcloud functions deploy {} \
--region={} \
--runtime={} \
--entry-point={} \
--memory={}MB \
--timeout={}s \
--max-instances={} \
--min-instances={} \
--ingress-settings={} \
--trigger-{}",
self.name,
self.region,
self.runtime,
self.entry_point,
self.memory_mb,
self.timeout_secs,
self.max_instances,
self.min_instances,
self.ingress_settings.flag(),
if matches!(self.event_type, X86GcpEventType::HTTP) { "http" } else { "event" },
);
if self.event_type != X86GcpEventType::HTTP {
cmd.push_str(&format!(" --trigger-event={}", self.event_type.event_type_str()));
}
if let Some(ref svc) = self.service_account {
cmd.push_str(&format!(" --service-account={}", svc));
}
if let Some(ref vpc) = self.vpc_connector {
cmd.push_str(&format!(" --vpc-connector={}", vpc));
}
for (k, v) in &self.environment {
cmd.push_str(&format!(" --set-env-vars {}={}", k, v));
}
cmd.push_str(&format!(" --source={}", self.source_dir));
cmd
}
pub fn generate_cpp_handler(&self) -> String {
format!(
r#"// Google Cloud Function: {}
// Entry point: {}
// X86-optimized handler using Functions Framework
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <nlohmann/json.hpp>
namespace beast = boost::beast;
namespace http = beast::http;
using json = nlohmann::json;
// HTTP handler (CloudEvent format)
extern "C" json gcp_function_handler(const json& event) {{
json response;
response["status"] = "ok";
if (event.contains("data")) {{
// Process CloudEvent data
auto data = event["data"];
if (data.is_object()) {{
response["processed"] = true;
}}
}}
return response;
}}
// For background functions:
extern "C" void gcp_background_handler(
const json& event,
const json& context
) {{
// eventType: {}
(void)event;
(void)context;
}}
"#,
self.name,
self.entry_point,
self.event_type.event_type_str()
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum X86CfBindingType {
KVNamespace,
DurableObject,
R2Bucket,
D1Database,
Queue,
Service,
AnalyticsEngine,
BrowserRendering,
Vectorize,
Hyperdrive,
Custom(String),
}
impl X86CfBindingType {
pub fn wrangler_type(&self) -> &str {
match self {
Self::KVNamespace => "kv_namespaces",
Self::DurableObject => "durable_objects",
Self::R2Bucket => "r2_buckets",
Self::D1Database => "d1_databases",
Self::Queue => "queues",
Self::Service => "services",
Self::AnalyticsEngine => "analytics_engine_datasets",
Self::BrowserRendering => "browser",
Self::Vectorize => "vectorize",
Self::Hyperdrive => "hyperdrive",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone)]
pub struct X86CfWorker {
pub name: String,
pub main_module: String,
pub compatibility_date: String,
pub bindings: Vec<(String, X86CfBindingType, String)>,
pub routes: Vec<String>,
pub usage_model: X86CfUsageModel,
pub wasm_modules: Vec<String>,
pub text_blobs: Vec<String>,
pub data_blobs: Vec<String>,
pub env_vars: HashMap<String, String>,
pub triggers: Vec<X86CfTrigger>,
pub tail_consumers: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CfUsageModel {
Bundled,
Unbound,
}
impl X86CfUsageModel {
pub fn as_str(&self) -> &str {
match self {
Self::Bundled => "bundled",
Self::Unbound => "unbound",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86CfTrigger {
Fetch,
Cron(String),
Queue,
Email,
Tail,
Dispatch,
Alarm,
}
impl X86CfTrigger {
pub fn wrangler_config(&self) -> String {
match self {
Self::Fetch => r#"type = "fetch""#.to_string(),
Self::Cron(cron) => format!(r#"type = "cron", cron = "{}""#, cron),
Self::Queue => r#"type = "queue""#.to_string(),
Self::Email => r#"type = "email""#.to_string(),
Self::Tail => r#"type = "tail""#.to_string(),
Self::Dispatch => r#"type = "dispatch""#.to_string(),
Self::Alarm => r#"type = "alarm""#.to_string(),
}
}
}
impl X86CfWorker {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
main_module: "src/index.ts".to_string(),
compatibility_date: "2024-01-01".to_string(),
bindings: Vec::new(),
routes: Vec::new(),
usage_model: X86CfUsageModel::Bundled,
wasm_modules: Vec::new(),
text_blobs: Vec::new(),
data_blobs: Vec::new(),
env_vars: HashMap::new(),
triggers: vec![X86CfTrigger::Fetch],
tail_consumers: Vec::new(),
}
}
pub fn add_kv_binding(&mut self, binding_name: &str, namespace_id: &str) -> &mut Self {
self.bindings.push((binding_name.to_string(), X86CfBindingType::KVNamespace, namespace_id.to_string()));
self
}
pub fn add_do_binding(&mut self, binding_name: &str, class_name: &str) -> &mut Self {
self.bindings.push((binding_name.to_string(), X86CfBindingType::DurableObject, class_name.to_string()));
self
}
pub fn add_r2_binding(&mut self, binding_name: &str, bucket_name: &str) -> &mut Self {
self.bindings.push((binding_name.to_string(), X86CfBindingType::R2Bucket, bucket_name.to_string()));
self
}
pub fn generate_wrangler_toml(&self) -> String {
let mut toml = format!(
r#"# Generated by clang-cloud-x86
name = "{}"
main = "{}"
compatibility_date = "{}"
usage_model = "{}"
"#,
self.name, self.main_module,
self.compatibility_date, self.usage_model.as_str()
);
let mut kv_bindings: Vec<&(String, X86CfBindingType, String)> = Vec::new();
let mut do_bindings: Vec<&(String, X86CfBindingType, String)> = Vec::new();
let mut r2_bindings: Vec<&(String, X86CfBindingType, String)> = Vec::new();
let mut d1_bindings: Vec<&(String, X86CfBindingType, String)> = Vec::new();
for b in &self.bindings {
match b.1 {
X86CfBindingType::KVNamespace => kv_bindings.push(b),
X86CfBindingType::DurableObject => do_bindings.push(b),
X86CfBindingType::R2Bucket => r2_bindings.push(b),
X86CfBindingType::D1Database => d1_bindings.push(b),
_ => {}
}
}
if !kv_bindings.is_empty() {
toml.push_str("kv_namespaces = [\n");
for (name, _, id) in &kv_bindings {
toml.push_str(&format!(" {{ binding = \"{}\", id = \"{}\" }},\n", name, id));
}
toml.push_str("]\n\n");
}
if !r2_bindings.is_empty() {
toml.push_str("r2_buckets = [\n");
for (name, _, bucket) in &r2_bindings {
toml.push_str(&format!(" {{ binding = \"{}\", bucket_name = \"{}\" }},\n", name, bucket));
}
toml.push_str("]\n\n");
}
if !d1_bindings.is_empty() {
toml.push_str("d1_databases = [\n");
for (name, _, db) in &d1_bindings {
toml.push_str(&format!(" {{ binding = \"{}\", database_id = \"{}\" }},\n", name, db));
}
toml.push_str("]\n\n");
}
if !do_bindings.is_empty() {
toml.push_str("durable_objects = {{\n bindings = [\n");
for (name, _, class) in &do_bindings {
toml.push_str(&format!(" {{ name = \"{}\", class_name = \"{}\" }},\n", name, class));
}
toml.push_str(" ]\n}}\n\n");
}
if !self.wasm_modules.is_empty() {
toml.push_str("wasm_modules = {\n");
for wm in &self.wasm_modules {
toml.push_str(&format!(" \"{}\" = \"./{}\",\n", wm, wm));
}
toml.push_str("}\n\n");
}
if !self.env_vars.is_empty() {
toml.push_str("[vars]\n");
for (k, v) in &self.env_vars {
toml.push_str(&format!("{} = \"{}\"\n", k, v));
}
toml.push('\n');
}
if !self.triggers.is_empty() {
toml.push_str("[[triggers]]\n");
for trigger in &self.triggers {
toml.push_str(&format!("triggers = [{{ {} }}]\n", trigger.wrangler_config()));
}
toml.push('\n');
}
if !self.routes.is_empty() {
toml.push_str("routes = [\n");
for route in &self.routes {
toml.push_str(&format!(" {{ pattern = \"{}\", zone_name = \"auto\" }},\n", route));
}
toml.push_str("]\n");
}
toml
}
pub fn generate_wasm_cpp_worker(&self) -> String {
format!(
r#"// Cloudflare Worker for {} (WASM/WASI target)
// Compiled with: clang++ --target=wasm32-wasi -O3 -flto
// X86-cross compiled for WASM
#include <cstdint>
#include <cstring>
#include <cstdlib>
// Worker request/response structures (FFI)
struct CxRequest {{
const char* url;
const char* method;
const char* body;
uint32_t body_len;
}};
struct CxResponse {{
uint16_t status;
const char* body;
uint32_t body_len;
const char* content_type;
}};
extern "C" {{
// Called by the Cloudflare Workers runtime
CxResponse* handle_request(CxRequest* req) {{
auto* resp = (CxResponse*)malloc(sizeof(CxResponse));
resp->status = 200;
resp->content_type = "text/plain; charset=utf-8";
const char* msg = "Hello from X86-compiled WASM Worker!";
resp->body = strdup(msg);
resp->body_len = strlen(msg);
return resp;
}}
void free_response(CxResponse* resp) {{
free((void*)resp->body);
free(resp);
}}
// WASI initialization
void __wasm_call_ctors() {{}}
void __wasm_call_dtors() {{}}
}}
"#,
self.name
)
}
}
#[derive(Debug, Clone)]
pub struct X86WasmEdgeFunction {
pub name: String,
pub target_triple: String,
pub optimization_level: String,
pub wasi_sdk_version: String,
pub exported_functions: Vec<String>,
pub imported_functions: Vec<String>,
pub memory_initial_pages: u32,
pub memory_max_pages: u32,
pub enable_threads: bool,
pub enable_simd: bool,
pub enable_bulk_memory: bool,
pub enable_reference_types: bool,
pub enable_tail_call: bool,
pub enable_exception_handling: bool,
pub linker_flags: Vec<String>,
pub adapters: Vec<String>,
}
impl X86WasmEdgeFunction {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
target_triple: "wasm32-wasi".to_string(),
optimization_level: "O3".to_string(),
wasi_sdk_version: "20".to_string(),
exported_functions: vec!["_start".into(), "handle_request".into()],
imported_functions: Vec::new(),
memory_initial_pages: 256,
memory_max_pages: 1024,
enable_threads: false,
enable_simd: true,
enable_bulk_memory: true,
enable_reference_types: true,
enable_tail_call: true,
enable_exception_handling: false,
linker_flags: vec![
"-Wl,--export=handle_request".into(),
"-Wl,--export=__wasm_call_ctors".into(),
"-Wl,--export=malloc".into(),
"-Wl,--export=free".into(),
"-Wl,--allow-undefined".into(),
],
adapters: Vec::new(),
}
}
pub fn compile_command(&self, source: &str) -> String {
let mut cmd = format!(
"clang --target={} \
-{} \
--sysroot=/opt/wasi-sdk-{}/share/wasi-sysroot \
-nostdlib \
-Wl,--no-entry \
-Wl,--initial-memory={} \
-Wl,--max-memory={}",
self.target_triple,
self.optimization_level,
self.wasi_sdk_version,
self.memory_initial_pages * 65536,
self.memory_max_pages * 65536,
);
if self.enable_threads {
cmd.push_str(" -pthread -Wl,--shared-memory -Wl,--import-memory");
}
if self.enable_simd {
cmd.push_str(" -msimd128");
}
if self.enable_bulk_memory {
cmd.push_str(" -mbulk-memory");
}
if self.enable_reference_types {
cmd.push_str(" -mreference-types");
}
if self.enable_tail_call {
cmd.push_str(" -mtail-call");
}
if self.enable_exception_handling {
cmd.push_str(" -fwasm-exceptions");
}
for flag in &self.linker_flags {
cmd.push_str(&format!(" {}", flag));
}
for export_fn in &self.exported_functions {
cmd.push_str(&format!(" -Wl,--export={}", export_fn));
}
cmd.push_str(&format!(" {} -o {}.wasm", source, self.name));
cmd
}
}
#[derive(Debug, Clone)]
pub struct X86ServerlessSupport {
pub enabled: bool,
pub platform: X86ServerlessPlatform,
pub lambda_functions: Vec<X86AwsLambdaFunction>,
pub azure_functions: Vec<X86AzureFunction>,
pub gcp_functions: Vec<X86GcpFunction>,
pub cf_workers: Vec<X86CfWorker>,
pub wasm_functions: Vec<X86WasmEdgeFunction>,
pub custom_runtime_image: Option<String>,
pub x86_optimizations: bool,
pub tiered_compilation: bool,
pub cold_start_optimization: bool,
pub connection_pooling: bool,
pub keep_warm: bool,
}
impl X86ServerlessSupport {
pub fn new() -> Self {
Self {
enabled: true,
platform: X86ServerlessPlatform::AWSLambda,
lambda_functions: Vec::new(),
azure_functions: Vec::new(),
gcp_functions: Vec::new(),
cf_workers: Vec::new(),
wasm_functions: Vec::new(),
custom_runtime_image: None,
x86_optimizations: true,
tiered_compilation: false,
cold_start_optimization: true,
connection_pooling: true,
keep_warm: false,
}
}
pub fn full() -> Self {
let mut ss = Self::new();
ss.cold_start_optimization = true;
ss.tiered_compilation = true;
ss.keep_warm = true;
ss
}
pub fn add_lambda(&mut self, func: X86AwsLambdaFunction) -> &mut Self {
self.lambda_functions.push(func);
self
}
pub fn add_azure(&mut self, func: X86AzureFunction) -> &mut Self {
self.azure_functions.push(func);
self
}
pub fn add_gcp(&mut self, func: X86GcpFunction) -> &mut Self {
self.gcp_functions.push(func);
self
}
pub fn add_worker(&mut self, worker: X86CfWorker) -> &mut Self {
self.cf_workers.push(worker);
self
}
pub fn add_wasm(&mut self, wasm: X86WasmEdgeFunction) -> &mut Self {
self.wasm_functions.push(wasm);
self
}
pub fn to_clang_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.x86_optimizations {
flags.push("-march=x86-64-v3".to_string());
flags.push("-mtune=generic".to_string());
}
if self.cold_start_optimization {
flags.push("-Os".to_string());
}
if self.enabled {
flags.push("-DCLOUD_X86_SERVERLESS=1".to_string());
}
flags
}
pub fn describe(&self) -> String {
let mut d = format!("X86ServerlessSupport platform={:?} enabled={}\n",
self.platform, self.enabled);
d.push_str(&format!(" Lambda functions: {}\n", self.lambda_functions.len()));
d.push_str(&format!(" Azure functions: {}\n", self.azure_functions.len()));
d.push_str(&format!(" GCP functions: {}\n", self.gcp_functions.len()));
d.push_str(&format!(" Cloudflare workers: {}\n", self.cf_workers.len()));
d.push_str(&format!(" WASM edge functions: {}\n", self.wasm_functions.len()));
d.push_str(&format!(" X86 optimizations: {}\n", self.x86_optimizations));
d.push_str(&format!(" Cold start opt: {}\n", self.cold_start_optimization));
d
}
}
impl Default for X86ServerlessSupport {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sResourceKind {
Pod,
Deployment,
StatefulSet,
DaemonSet,
Job,
CronJob,
Service,
ConfigMap,
Secret,
Ingress,
PersistentVolumeClaim,
ServiceAccount,
Role,
RoleBinding,
HorizontalPodAutoscaler,
PodDisruptionBudget,
NetworkPolicy,
CustomResourceDefinition,
}
impl X86K8sResourceKind {
pub fn api_version(&self) -> &str {
match self {
Self::Pod | Self::Service | Self::ConfigMap | Self::Secret |
Self::PersistentVolumeClaim | Self::ServiceAccount => X86_K8S_CORE_API_VERSION,
Self::NetworkPolicy => "networking.k8s.io/v1",
Self::Ingress => "networking.k8s.io/v1",
Self::HorizontalPodAutoscaler => "autoscaling/v2",
Self::PodDisruptionBudget => "policy/v1",
Self::Role | Self::RoleBinding => "rbac.authorization.k8s.io/v1",
Self::CronJob => "batch/v1",
_ => X86_K8S_API_VERSION,
}
}
pub fn kind_str(&self) -> &str {
match self {
Self::Pod => "Pod",
Self::Deployment => "Deployment",
Self::StatefulSet => "StatefulSet",
Self::DaemonSet => "DaemonSet",
Self::Job => "Job",
Self::CronJob => "CronJob",
Self::Service => "Service",
Self::ConfigMap => "ConfigMap",
Self::Secret => "Secret",
Self::Ingress => "Ingress",
Self::PersistentVolumeClaim => "PersistentVolumeClaim",
Self::ServiceAccount => "ServiceAccount",
Self::Role => "Role",
Self::RoleBinding => "RoleBinding",
Self::HorizontalPodAutoscaler => "HorizontalPodAutoscaler",
Self::PodDisruptionBudget => "PodDisruptionBudget",
Self::NetworkPolicy => "NetworkPolicy",
Self::CustomResourceDefinition => "CustomResourceDefinition",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sPodSpec {
pub name: String,
pub namespace: String,
pub labels: HashMap<String, String>,
pub annotations: HashMap<String, String>,
pub containers: Vec<X86K8sContainer>,
pub init_containers: Vec<X86K8sContainer>,
pub volumes: Vec<X86K8sVolume>,
pub restart_policy: X86K8sRestartPolicy,
pub service_account: Option<String>,
pub node_selector: HashMap<String, String>,
pub tolerations: Vec<X86K8sToleration>,
pub affinity: Option<X86K8sAffinity>,
pub security_context: Option<X86K8sPodSecurityContext>,
pub termination_grace_period_secs: u64,
pub dns_policy: X86K8sDnsPolicy,
pub host_network: bool,
pub host_pid: bool,
pub host_ipc: bool,
pub share_process_namespace: bool,
pub subdomain: Option<String>,
pub scheduler_name: Option<String>,
pub priority_class_name: Option<String>,
pub runtime_class_name: Option<String>,
pub topology_spread_constraints: Vec<X86K8sTopologySpreadConstraint>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sRestartPolicy {
Always,
OnFailure,
Never,
}
impl X86K8sRestartPolicy {
pub fn as_str(&self) -> &str {
match self {
Self::Always => "Always",
Self::OnFailure => "OnFailure",
Self::Never => "Never",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sDnsPolicy {
ClusterFirst,
Default,
ClusterFirstWithHostNet,
None,
}
impl X86K8sDnsPolicy {
pub fn as_str(&self) -> &str {
match self {
Self::ClusterFirst => "ClusterFirst",
Self::Default => "Default",
Self::ClusterFirstWithHostNet => "ClusterFirstWithHostNet",
Self::None => "None",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sContainer {
pub name: String,
pub image: String,
pub image_pull_policy: X86K8sImagePullPolicy,
pub command: Vec<String>,
pub args: Vec<String>,
pub working_dir: Option<String>,
pub ports: Vec<X86K8sContainerPort>,
pub env_from: Vec<X86K8sEnvFromSource>,
pub env: Vec<X86K8sEnvVar>,
pub resources: X86K8sResourceRequirements,
pub volume_mounts: Vec<X86K8sVolumeMount>,
pub liveness_probe: Option<X86K8sProbe>,
pub readiness_probe: Option<X86K8sProbe>,
pub startup_probe: Option<X86K8sProbe>,
pub lifecycle: Option<X86K8sLifecycle>,
pub security_context: Option<X86K8sSecurityContext>,
pub stdin: bool,
pub stdin_once: bool,
pub tty: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sImagePullPolicy {
Always,
IfNotPresent,
Never,
}
impl X86K8sImagePullPolicy {
pub fn as_str(&self) -> &str {
match self {
Self::Always => "Always",
Self::IfNotPresent => "IfNotPresent",
Self::Never => "Never",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sContainerPort {
pub name: Option<String>,
pub container_port: u16,
pub host_port: Option<u16>,
pub protocol: X86K8sProtocol,
pub host_ip: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sProtocol {
TCP,
UDP,
SCTP,
}
impl X86K8sProtocol {
pub fn as_str(&self) -> &str {
match self {
Self::TCP => "TCP",
Self::UDP => "UDP",
Self::SCTP => "SCTP",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sEnvVar {
pub name: String,
pub value: Option<String>,
pub value_from: Option<X86K8sEnvVarSource>,
}
#[derive(Debug, Clone)]
pub enum X86K8sEnvVarSource {
FieldRef(String, String),
ResourceFieldRef(String, String),
ConfigMapKeyRef(String, String, bool),
SecretKeyRef(String, String, bool),
}
impl X86K8sEnvVarSource {
pub fn to_yaml(&self) -> String {
match self {
Self::FieldRef(path, api) => format!(
"valueFrom:\n fieldRef:\n fieldPath: {}\n apiVersion: {}",
path, api
),
Self::ConfigMapKeyRef(name, key, optional) => format!(
"valueFrom:\n configMapKeyRef:\n name: {}\n key: {}\n optional: {}",
name, key, optional
),
Self::SecretKeyRef(name, key, optional) => format!(
"valueFrom:\n secretKeyRef:\n name: {}\n key: {}\n optional: {}",
name, key, optional
),
Self::ResourceFieldRef(resource, divisor) => format!(
"valueFrom:\n resourceFieldRef:\n resource: {}\n divisor: {}",
resource, divisor
),
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sEnvFromSource {
pub prefix: Option<String>,
pub source: X86K8sEnvFromSourceType,
}
#[derive(Debug, Clone)]
pub enum X86K8sEnvFromSourceType {
ConfigMapRef(String, bool),
SecretRef(String, bool),
}
#[derive(Debug, Clone)]
pub struct X86K8sResourceRequirements {
pub requests: X86K8sResourceList,
pub limits: X86K8sResourceList,
}
#[derive(Debug, Clone, Default)]
pub struct X86K8sResourceList {
pub cpu: Option<String>,
pub memory: Option<String>,
pub ephemeral_storage: Option<String>,
pub gpu: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sVolumeMount {
pub name: String,
pub mount_path: String,
pub sub_path: Option<String>,
pub read_only: bool,
pub mount_propagation: Option<X86K8sMountPropagation>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sMountPropagation {
None,
HostToContainer,
Bidirectional,
}
impl X86K8sMountPropagation {
pub fn as_str(&self) -> &str {
match self {
Self::None => "None",
Self::HostToContainer => "HostToContainer",
Self::Bidirectional => "Bidirectional",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sVolume {
pub name: String,
pub source: X86K8sVolumeSource,
}
#[derive(Debug, Clone)]
pub enum X86K8sVolumeSource {
EmptyDir(String),
HostPath(String, Option<String>),
ConfigMap(String, Option<i32>, bool),
Secret(String, Option<i32>, bool),
PersistentVolumeClaim(String, bool),
NFS(String, String, bool),
CSI(String, HashMap<String, String>, bool),
Ephemeral(String),
Projected(Vec<X86K8sVolumeProjection>),
}
#[derive(Debug, Clone)]
pub struct X86K8sVolumeProjection {
pub source: X86K8sProjectionSource,
}
#[derive(Debug, Clone)]
pub enum X86K8sProjectionSource {
Secret(String, Vec<X86K8sKeyToPath>),
ConfigMap(String, Vec<X86K8sKeyToPath>),
DownwardAPI(Vec<X86K8sDownwardAPIVolumeFile>),
ServiceAccountToken(String, Option<String>, Option<i64>),
}
#[derive(Debug, Clone)]
pub struct X86K8sKeyToPath {
pub key: String,
pub path: String,
pub mode: Option<i32>,
}
#[derive(Debug, Clone)]
pub struct X86K8sDownwardAPIVolumeFile {
pub path: String,
pub field_ref: Option<X86K8sObjectFieldSelector>,
pub resource_ref: Option<X86K8sResourceFieldSelector>,
pub mode: Option<i32>,
}
#[derive(Debug, Clone)]
pub struct X86K8sObjectFieldSelector {
pub api_version: String,
pub field_path: String,
}
#[derive(Debug, Clone)]
pub struct X86K8sResourceFieldSelector {
pub container_name: String,
pub resource: String,
pub divisor: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sProbe {
pub handler: X86K8sProbeHandler,
pub initial_delay_secs: u64,
pub period_secs: u64,
pub timeout_secs: u64,
pub success_threshold: u64,
pub failure_threshold: u64,
}
#[derive(Debug, Clone)]
pub enum X86K8sProbeHandler {
HttpGet(String, u16, String, Vec<X86K8sHttpHeader>),
TcpSocket(u16, Option<String>),
Exec(Vec<String>),
Grpc(u16, Option<String>),
}
#[derive(Debug, Clone)]
pub struct X86K8sHttpHeader {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone)]
pub struct X86K8sLifecycle {
pub post_start: Option<X86K8sLifecycleHandler>,
pub pre_stop: Option<X86K8sLifecycleHandler>,
}
#[derive(Debug, Clone)]
pub struct X86K8sLifecycleHandler {
pub exec: Option<Vec<String>>,
pub http_get: Option<(String, u16, String)>,
pub tcp_socket: Option<(u16, Option<String>)>,
}
#[derive(Debug, Clone)]
pub struct X86K8sPodSecurityContext {
pub run_as_user: Option<i64>,
pub run_as_group: Option<i64>,
pub run_as_non_root: Option<bool>,
pub fs_group: Option<i64>,
pub fs_group_change_policy: Option<String>,
pub supplemental_groups: Vec<i64>,
pub sysctls: Vec<X86K8sSysctl>,
pub seccomp_profile: Option<X86K8sSeccompProfile>,
pub se_linux_options: Option<X86K8sSELinuxOptions>,
}
#[derive(Debug, Clone)]
pub struct X86K8sSecurityContext {
pub capabilities: Option<X86K8sCapabilities>,
pub privileged: Option<bool>,
pub read_only_root_filesystem: Option<bool>,
pub allow_privilege_escalation: Option<bool>,
pub run_as_user: Option<i64>,
pub run_as_group: Option<i64>,
pub run_as_non_root: Option<bool>,
pub seccomp_profile: Option<X86K8sSeccompProfile>,
pub se_linux_options: Option<X86K8sSELinuxOptions>,
}
#[derive(Debug, Clone)]
pub struct X86K8sCapabilities {
pub add: Vec<String>,
pub drop: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sSeccompProfile {
pub profile_type: X86K8sSeccompProfileType,
pub localhost_profile: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sSeccompProfileType {
RuntimeDefault,
Localhost,
Unconfined,
}
impl X86K8sSeccompProfileType {
pub fn as_str(&self) -> &str {
match self {
Self::RuntimeDefault => "RuntimeDefault",
Self::Localhost => "Localhost",
Self::Unconfined => "Unconfined",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sSELinuxOptions {
pub level: Option<String>,
pub role: Option<String>,
pub user: Option<String>,
pub selinux_type: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sSysctl {
pub name: String,
pub value: String,
}
#[derive(Debug, Clone)]
pub struct X86K8sToleration {
pub key: Option<String>,
pub operator: X86K8sTolerationOperator,
pub value: Option<String>,
pub effect: Option<X86K8sTaintEffect>,
pub toleration_seconds: Option<u64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sTolerationOperator {
Equal,
Exists,
}
impl X86K8sTolerationOperator {
pub fn as_str(&self) -> &str {
match self {
Self::Equal => "Equal",
Self::Exists => "Exists",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sTaintEffect {
NoSchedule,
PreferNoSchedule,
NoExecute,
}
impl X86K8sTaintEffect {
pub fn as_str(&self) -> &str {
match self {
Self::NoSchedule => "NoSchedule",
Self::PreferNoSchedule => "PreferNoSchedule",
Self::NoExecute => "NoExecute",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sAffinity {
pub node_affinity: Option<X86K8sNodeAffinity>,
pub pod_affinity: Option<X86K8sPodAffinity>,
pub pod_anti_affinity: Option<X86K8sPodAntiAffinity>,
}
#[derive(Debug, Clone)]
pub struct X86K8sNodeAffinity {
pub required: Option<X86K8sNodeSelector>,
pub preferred: Vec<X86K8sPreferredSchedulingTerm>,
}
#[derive(Debug, Clone)]
pub struct X86K8sNodeSelector {
pub node_selector_terms: Vec<X86K8sNodeSelectorTerm>,
}
#[derive(Debug, Clone)]
pub struct X86K8sNodeSelectorTerm {
pub match_expressions: Vec<X86K8sNodeSelectorRequirement>,
pub match_fields: Vec<X86K8sNodeSelectorRequirement>,
}
#[derive(Debug, Clone)]
pub struct X86K8sNodeSelectorRequirement {
pub key: String,
pub operator: X86K8sNodeSelectorOperator,
pub values: Vec<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sNodeSelectorOperator {
In,
NotIn,
Exists,
DoesNotExist,
Gt,
Lt,
}
impl X86K8sNodeSelectorOperator {
pub fn as_str(&self) -> &str {
match self {
Self::In => "In",
Self::NotIn => "NotIn",
Self::Exists => "Exists",
Self::DoesNotExist => "DoesNotExist",
Self::Gt => "Gt",
Self::Lt => "Lt",
}
}
}
#[derive(Debug, Clone)]
pub struct X86K8sPreferredSchedulingTerm {
pub weight: i32,
pub preference: X86K8sNodeSelectorTerm,
}
#[derive(Debug, Clone)]
pub struct X86K8sPodAffinity {
pub required: Vec<X86K8sPodAffinityTerm>,
pub preferred: Vec<X86K8sWeightedPodAffinityTerm>,
}
#[derive(Debug, Clone)]
pub struct X86K8sPodAntiAffinity {
pub required: Vec<X86K8sPodAffinityTerm>,
pub preferred: Vec<X86K8sWeightedPodAffinityTerm>,
}
#[derive(Debug, Clone)]
pub struct X86K8sPodAffinityTerm {
pub label_selector: X86K8sLabelSelector,
pub namespaces: Vec<String>,
pub topology_key: String,
pub namespace_selector: Option<X86K8sLabelSelector>,
}
#[derive(Debug, Clone)]
pub struct X86K8sWeightedPodAffinityTerm {
pub weight: i32,
pub pod_affinity_term: X86K8sPodAffinityTerm,
}
#[derive(Debug, Clone)]
pub struct X86K8sLabelSelector {
pub match_labels: HashMap<String, String>,
pub match_expressions: Vec<X86K8sLabelSelectorRequirement>,
}
#[derive(Debug, Clone)]
pub struct X86K8sLabelSelectorRequirement {
pub key: String,
pub operator: String,
pub values: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sTopologySpreadConstraint {
pub max_skew: i32,
pub topology_key: String,
pub when_unsatisfiable: X86K8sUnsatisfiableConstraintAction,
pub label_selector: Option<X86K8sLabelSelector>,
pub min_domains: Option<i32>,
pub node_affinity_policy: Option<X86K8sNodeInclusionPolicy>,
pub node_taints_policy: Option<X86K8sNodeInclusionPolicy>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sUnsatisfiableConstraintAction {
DoNotSchedule,
ScheduleAnyway,
}
impl X86K8sUnsatisfiableConstraintAction {
pub fn as_str(&self) -> &str {
match self {
Self::DoNotSchedule => "DoNotSchedule",
Self::ScheduleAnyway => "ScheduleAnyway",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86K8sNodeInclusionPolicy {
Honor,
Ignore,
}
impl X86K8sNodeInclusionPolicy {
pub fn as_str(&self) -> &str {
match self {
Self::Honor => "Honor",
Self::Ignore => "Ignore",
}
}
}
impl X86K8sPodSpec {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
namespace: "default".to_string(),
labels: HashMap::new(),
annotations: HashMap::new(),
containers: Vec::new(),
init_containers: Vec::new(),
volumes: Vec::new(),
restart_policy: X86K8sRestartPolicy::Always,
service_account: None,
node_selector: HashMap::new(),
tolerations: Vec::new(),
affinity: None,
security_context: None,
termination_grace_period_secs: 30,
dns_policy: X86K8sDnsPolicy::ClusterFirst,
host_network: false,
host_pid: false,
host_ipc: false,
share_process_namespace: false,
subdomain: None,
scheduler_name: None,
priority_class_name: None,
runtime_class_name: None,
topology_spread_constraints: Vec::new(),
}
}
pub fn add_container(&mut self, container: X86K8sContainer) -> &mut Self {
self.containers.push(container);
self
}
pub fn add_label(&mut self, key: &str, value: &str) -> &mut Self {
self.labels.insert(key.to_string(), value.to_string());
self
}
pub fn with_restart_policy(&mut self, policy: X86K8sRestartPolicy) -> &mut Self {
self.restart_policy = policy;
self
}
pub fn generate_yaml(&self, kind: X86K8sResourceKind) -> String {
let mut y = String::new();
y.push_str(&format!("apiVersion: {}\n", kind.api_version()));
y.push_str(&format!("kind: {}\n", kind.kind_str()));
y.push_str("metadata:\n");
y.push_str(&format!(" name: {}\n", self.name));
y.push_str(&format!(" namespace: {}\n", self.namespace));
if !self.labels.is_empty() {
y.push_str(" labels:\n");
for (k, v) in &self.labels {
y.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
if !self.annotations.is_empty() {
y.push_str(" annotations:\n");
for (k, v) in &self.annotations {
y.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
y.push_str("spec:\n");
y.push_str(&format!(" restartPolicy: {}\n", self.restart_policy.as_str()));
if let Some(ref sa) = self.service_account {
y.push_str(&format!(" serviceAccountName: {}\n", sa));
}
y.push_str(&format!(" terminationGracePeriodSeconds: {}\n", self.termination_grace_period_secs));
y.push_str(&format!(" dnsPolicy: {}\n", self.dns_policy.as_str()));
y.push_str(&format!(" hostNetwork: {}\n", self.host_network));
y.push_str(&format!(" hostPID: {}\n", self.host_pid));
y.push_str(&format!(" hostIPC: {}\n", self.host_ipc));
y.push_str(&format!(" shareProcessNamespace: {}\n", self.share_process_namespace));
if !self.node_selector.is_empty() {
y.push_str(" nodeSelector:\n");
for (k, v) in &self.node_selector {
y.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
y.push_str(" containers:\n");
for container in &self.containers {
y.push_str(&format!(" - name: {}\n", container.name));
y.push_str(&format!(" image: {}\n", container.image));
y.push_str(&format!(" imagePullPolicy: {}\n", container.image_pull_policy.as_str()));
if !container.command.is_empty() {
y.push_str(" command:\n");
for cmd in &container.command {
y.push_str(&format!(" - {}\n", cmd));
}
}
if !container.ports.is_empty() {
y.push_str(" ports:\n");
for port in &container.ports {
y.push_str(&format!(" - containerPort: {}\n", port.container_port));
y.push_str(&format!(" protocol: {}\n", port.protocol.as_str()));
if let Some(ref name) = port.name {
y.push_str(&format!(" name: {}\n", name));
}
}
}
if !container.env.is_empty() {
y.push_str(" env:\n");
for env in &container.env {
y.push_str(&format!(" - name: {}\n", env.name));
if let Some(ref val) = env.value {
y.push_str(&format!(" value: \"{}\"\n", val));
}
}
}
y.push_str(" resources:\n");
y.push_str(" requests:\n");
if let Some(ref cpu) = container.resources.requests.cpu {
y.push_str(&format!(" cpu: \"{}\"\n", cpu));
}
if let Some(ref mem) = container.resources.requests.memory {
y.push_str(&format!(" memory: \"{}\"\n", mem));
}
y.push_str(" limits:\n");
if let Some(ref cpu) = container.resources.limits.cpu {
y.push_str(&format!(" cpu: \"{}\"\n", cpu));
}
if let Some(ref mem) = container.resources.limits.memory {
y.push_str(&format!(" memory: \"{}\"\n", mem));
}
}
y
}
}
impl X86K8sContainer {
pub fn new(name: &str, image: &str) -> Self {
Self {
name: name.to_string(),
image: image.to_string(),
image_pull_policy: X86K8sImagePullPolicy::IfNotPresent,
command: Vec::new(),
args: Vec::new(),
working_dir: None,
ports: Vec::new(),
env_from: Vec::new(),
env: Vec::new(),
resources: X86K8sResourceRequirements {
requests: X86K8sResourceList {
cpu: Some("100m".to_string()),
memory: Some("128Mi".to_string()),
ephemeral_storage: None,
gpu: None,
},
limits: X86K8sResourceList {
cpu: Some("500m".to_string()),
memory: Some("256Mi".to_string()),
ephemeral_storage: None,
gpu: None,
},
},
volume_mounts: Vec::new(),
liveness_probe: None,
readiness_probe: None,
startup_probe: None,
lifecycle: None,
security_context: None,
stdin: false,
stdin_once: false,
tty: false,
}
}
pub fn with_command(&mut self, cmd: Vec<&str>) -> &mut Self {
self.command = cmd.iter().map(|s| s.to_string()).collect();
self
}
pub fn with_port(&mut self, port: u16) -> &mut Self {
self.ports.push(X86K8sContainerPort {
name: Some(format!("port-{}", port)),
container_port: port,
host_port: None,
protocol: X86K8sProtocol::TCP,
host_ip: None,
});
self
}
pub fn with_http_liveness(&mut self, path: &str, port: u16) -> &mut Self {
self.liveness_probe = Some(X86K8sProbe {
handler: X86K8sProbeHandler::HttpGet(path.to_string(), port, "HTTP".to_string(), vec![]),
initial_delay_secs: 10,
period_secs: 15,
timeout_secs: 5,
success_threshold: 1,
failure_threshold: 3,
});
self
}
pub fn with_http_readiness(&mut self, path: &str, port: u16) -> &mut Self {
self.readiness_probe = Some(X86K8sProbe {
handler: X86K8sProbeHandler::HttpGet(path.to_string(), port, "HTTP".to_string(), vec![]),
initial_delay_secs: 5,
period_secs: 10,
timeout_secs: 3,
success_threshold: 2,
failure_threshold: 3,
});
self
}
}
#[derive(Debug, Clone)]
pub struct X86HelmChart {
pub name: String,
pub api_version: String,
pub version: String,
pub app_version: String,
pub description: String,
pub chart_type: Option<String>,
pub keywords: Vec<String>,
pub home: Option<String>,
pub sources: Vec<String>,
pub maintainers: Vec<X86HelmMaintainer>,
pub dependencies: Vec<X86HelmDependency>,
pub icon: Option<String>,
pub values_schema: Option<String>,
pub templates: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct X86HelmMaintainer {
pub name: String,
pub email: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86HelmDependency {
pub name: String,
pub version: String,
pub repository: String,
pub condition: Option<String>,
pub tags: Vec<String>,
pub alias: Option<String>,
}
impl X86HelmChart {
pub fn new(name: &str, version: &str) -> Self {
Self {
name: name.to_string(),
api_version: X86_HELM_CHART_API_VERSION.to_string(),
version: version.to_string(),
app_version: version.to_string(),
description: format!("Helm chart for {}", name),
chart_type: Some("application".to_string()),
keywords: vec!["x86".into(), "clang".into()],
home: None,
sources: Vec::new(),
maintainers: Vec::new(),
dependencies: Vec::new(),
icon: None,
values_schema: None,
templates: HashMap::new(),
}
}
pub fn generate_chart_yaml(&self) -> String {
let mut y = format!(
r#"apiVersion: {}
name: {}
version: {}
appVersion: {}
description: "{}"
type: {}
keywords:
"#,
self.api_version, self.name, self.version, self.app_version,
self.description,
self.chart_type.as_deref().unwrap_or("application")
);
for kw in &self.keywords {
y.push_str(&format!(" - {}\n", kw));
}
if let Some(ref home) = self.home {
y.push_str(&format!("home: {}\n", home));
}
if !self.sources.is_empty() {
y.push_str("sources:\n");
for s in &self.sources {
y.push_str(&format!(" - {}\n", s));
}
}
if !self.maintainers.is_empty() {
y.push_str("maintainers:\n");
for m in &self.maintainers {
y.push_str(&format!(" - name: {}\n", m.name));
if let Some(ref email) = m.email {
y.push_str(&format!(" email: {}\n", email));
}
if let Some(ref url) = m.url {
y.push_str(&format!(" url: {}\n", url));
}
}
}
if !self.dependencies.is_empty() {
y.push_str("dependencies:\n");
for dep in &self.dependencies {
y.push_str(&format!(" - name: {}\n version: {}\n repository: {}\n",
dep.name, dep.version, dep.repository));
if let Some(ref alias) = dep.alias {
y.push_str(&format!(" alias: {}\n", alias));
}
}
}
if let Some(ref icon) = self.icon {
y.push_str(&format!("icon: {}\n", icon));
}
y
}
pub fn add_template(&mut self, name: &str, content: &str) -> &mut Self {
self.templates.insert(name.to_string(), content.to_string());
self
}
pub fn generate_values_yaml(&self) -> String {
format!(
r#"# Default values for {}.
# Generated by clang-cloud-x86
replicaCount: 1
image:
repository: x86-app
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
nodeSelector: {{}}
tolerations: []
affinity: {{}}
x86Optimizations:
cpuTarget: x86-64-v3
mtune: generic
march: x86-64-v3
"#,
self.name
)
}
}
#[derive(Debug, Clone)]
pub struct X86KustomizeOverlay {
pub name: String,
pub bases: Vec<String>,
pub resources: Vec<String>,
pub patches: Vec<X86KustomizePatch>,
pub config_map_generator: Vec<X86KustomizeConfigMapGenerator>,
pub secret_generator: Vec<X86KustomizeSecretGenerator>,
pub images: Vec<X86KustomizeImage>,
pub name_prefix: Option<String>,
pub name_suffix: Option<String>,
pub namespace: Option<String>,
pub common_labels: HashMap<String, String>,
pub common_annotations: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct X86KustomizePatch {
pub path: String,
pub target: Option<X86KustomizePatchTarget>,
}
#[derive(Debug, Clone)]
pub struct X86KustomizePatchTarget {
pub group: Option<String>,
pub version: Option<String>,
pub kind: Option<String>,
pub name: Option<String>,
pub namespace: Option<String>,
pub label_selector: Option<String>,
pub annotation_selector: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86KustomizeConfigMapGenerator {
pub name: String,
pub behavior: Option<String>,
pub files: Vec<String>,
pub literals: Vec<String>,
pub envs: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86KustomizeSecretGenerator {
pub name: String,
pub behavior: Option<String>,
pub files: Vec<String>,
pub literals: Vec<String>,
pub envs: Vec<String>,
pub secret_type: Option<String>,
}
#[derive(Debug, Clone)]
pub struct X86KustomizeImage {
pub name: String,
pub new_name: Option<String>,
pub new_tag: Option<String>,
pub digest: Option<String>,
}
impl X86KustomizeOverlay {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
bases: Vec::new(),
resources: Vec::new(),
patches: Vec::new(),
config_map_generator: Vec::new(),
secret_generator: Vec::new(),
images: Vec::new(),
name_prefix: None,
name_suffix: None,
namespace: None,
common_labels: HashMap::new(),
common_annotations: HashMap::new(),
}
}
pub fn generate_kustomization_yaml(&self) -> String {
let mut y = format!("# Kustomization overlay: {}\n", self.name);
y.push_str("apiVersion: kustomize.config.k8s.io/v1beta1\n");
y.push_str("kind: Kustomization\n");
if let Some(ref prefix) = self.name_prefix {
y.push_str(&format!("namePrefix: {}\n", prefix));
}
if let Some(ref suffix) = self.name_suffix {
y.push_str(&format!("nameSuffix: {}\n", suffix));
}
if let Some(ref ns) = self.namespace {
y.push_str(&format!("namespace: {}\n", ns));
}
if !self.bases.is_empty() {
y.push_str("bases:\n");
for base in &self.bases {
y.push_str(&format!(" - {}\n", base));
}
}
if !self.resources.is_empty() {
y.push_str("resources:\n");
for res in &self.resources {
y.push_str(&format!(" - {}\n", res));
}
}
if !self.images.is_empty() {
y.push_str("images:\n");
for img in &self.images {
y.push_str(&format!(" - name: {}\n", img.name));
if let Some(ref new_name) = img.new_name {
y.push_str(&format!(" newName: {}\n", new_name));
}
if let Some(ref new_tag) = img.new_tag {
y.push_str(&format!(" newTag: {}\n", new_tag));
}
}
}
if !self.common_labels.is_empty() {
y.push_str("commonLabels:\n");
for (k, v) in &self.common_labels {
y.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
if !self.patches.is_empty() {
y.push_str("patches:\n");
for patch in &self.patches {
y.push_str(&format!(" - path: {}\n", patch.path));
}
}
if !self.config_map_generator.is_empty() {
y.push_str("configMapGenerator:\n");
for cm in &self.config_map_generator {
y.push_str(&format!(" - name: {}\n", cm.name));
if !cm.literals.is_empty() {
y.push_str(" literals:\n");
for lit in &cm.literals {
y.push_str(&format!(" - {}\n", lit));
}
}
}
}
y
}
}
#[derive(Debug, Clone)]
pub struct X86OperatorSdkPattern {
pub operator_name: String,
pub api_group: String,
pub api_version: String,
pub kind: String,
pub multi_namespace: bool,
pub cluster_scoped: bool,
pub webhooks_enabled: bool,
pub conversion_webhooks: bool,
pub controller_runtime_version: String,
pub resource_limits: X86K8sResourceRequirements,
pub rbac_rules: Vec<X86K8sRbacRule>,
pub crd_spec_version: String,
pub additional_print_columns: Vec<X86K8sAdditionalPrinterColumn>,
}
#[derive(Debug, Clone)]
pub struct X86K8sRbacRule {
pub api_groups: Vec<String>,
pub resources: Vec<String>,
pub verbs: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86K8sAdditionalPrinterColumn {
pub name: String,
pub column_type: String,
pub json_path: String,
pub description: String,
pub priority: i32,
}
impl X86OperatorSdkPattern {
pub fn new(operator_name: &str, kind: &str) -> Self {
Self {
operator_name: operator_name.to_string(),
api_group: "x86.llvm.io".to_string(),
api_version: "v1alpha1".to_string(),
kind: kind.to_string(),
multi_namespace: false,
cluster_scoped: false,
webhooks_enabled: true,
conversion_webhooks: false,
controller_runtime_version: "v0.17.0".to_string(),
resource_limits: X86K8sResourceRequirements {
requests: X86K8sResourceList {
cpu: Some("200m".to_string()),
memory: Some("256Mi".to_string()),
ephemeral_storage: None,
gpu: None,
},
limits: X86K8sResourceList {
cpu: Some("1000m".to_string()),
memory: Some("512Mi".to_string()),
ephemeral_storage: None,
gpu: None,
},
},
rbac_rules: vec![
X86K8sRbacRule {
api_groups: vec!["".into()],
resources: vec!["pods".into(), "services".into(), "configmaps".into()],
verbs: vec!["get".into(), "list".into(), "watch".into(), "create".into(), "update".into(), "delete".into()],
},
],
crd_spec_version: "v1".to_string(),
additional_print_columns: Vec::new(),
}
}
pub fn generate_operator_yaml(&self) -> String {
format!(
r#"apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
name: {operator}-v{version}
namespace: placeholder
spec:
displayName: {kind} Operator
description: X86-optimized operator for {kind}
version: {version}.0
maturity: alpha
provider:
name: LLVM Native
installModes:
- type: OwnNamespace
supported: true
- type: SingleNamespace
supported: true
- type: MultiNamespace
supported: {multi_ns}
- type: AllNamespaces
supported: {cluster}
install:
strategy: deployment
spec:
deployments:
- name: {operator}-controller
spec:
replicas: 1
selector:
matchLabels:
app: {operator}
template:
metadata:
labels:
app: {operator}
spec:
serviceAccountName: {operator}
containers:
- name: controller
image: {operator}:latest
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
permissions:
- serviceAccountName: {operator}
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
customresourcedefinitions:
owned:
- name: {kind_lower}s.{group}
version: {api_version}
kind: {kind}
displayName: {kind}
"#,
operator = self.operator_name,
version = self.api_version.trim_start_matches('v'),
kind = self.kind,
kind_lower = self.kind.to_lowercase(),
group = self.api_group,
api_version = self.api_version,
multi_ns = self.multi_namespace,
cluster = self.cluster_scoped,
)
}
}
#[derive(Debug, Clone)]
pub struct X86KubernetesSupport {
pub enabled: bool,
pub kubeconfig_path: Option<String>,
pub context: Option<String>,
pub namespace: String,
pub deployments: Vec<String>,
pub services: Vec<String>,
pub helm_charts: Vec<X86HelmChart>,
pub kustomize_overlays: Vec<X86KustomizeOverlay>,
pub operators: Vec<X86OperatorSdkPattern>,
pub default_replicas: u32,
pub rolling_update_enabled: bool,
pub resource_quotas: Option<X86K8sResourceRequirements>,
pub network_policies: bool,
pub pod_security_standards: bool,
pub istio_integration: bool,
pub linkerd_integration: bool,
pub cert_manager_integration: bool,
}
impl X86KubernetesSupport {
pub fn new() -> Self {
Self {
enabled: true,
kubeconfig_path: None,
context: None,
namespace: "default".to_string(),
deployments: Vec::new(),
services: Vec::new(),
helm_charts: Vec::new(),
kustomize_overlays: Vec::new(),
operators: Vec::new(),
default_replicas: 2,
rolling_update_enabled: true,
resource_quotas: None,
network_policies: false,
pod_security_standards: true,
istio_integration: false,
linkerd_integration: false,
cert_manager_integration: false,
}
}
pub fn full() -> Self {
let mut ks = Self::new();
ks.network_policies = true;
ks.pod_security_standards = true;
ks.cert_manager_integration = true;
ks
}
pub fn generate_deployment(&self, name: &str, image: &str) -> String {
let mut pod = X86K8sPodSpec::new(name);
pod.add_label("app", name);
pod.add_label("x86-optimized", "true");
let mut container = X86K8sContainer::new(name, image);
container.with_port(8080);
container.with_http_liveness("/healthz", 8080);
container.with_http_readiness("/readyz", 8080);
pod.add_container(container);
let mut yaml = pod.generate_yaml(X86K8sResourceKind::Deployment);
yaml.push_str(&format!(" replicas: {}\n", self.default_replicas));
yaml.push_str(" selector:\n matchLabels:\n");
for (k, v) in &pod.labels {
yaml.push_str(&format!(" {}: \"{}\"\n", k, v));
}
if self.rolling_update_enabled {
yaml.push_str(" strategy:\n type: RollingUpdate\n rollingUpdate:\n maxSurge: 1\n maxUnavailable: 0\n");
}
yaml
}
pub fn generate_service(&self, name: &str) -> String {
format!(
r#"apiVersion: v1
kind: Service
metadata:
name: {name}
namespace: {namespace}
labels:
app: {name}
x86-optimized: "true"
spec:
type: ClusterIP
selector:
app: {name}
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: metrics
port: 9090
targetPort: 9090
protocol: TCP
"#,
name = name,
namespace = self.namespace
)
}
pub fn generate_configmap(&self, name: &str) -> String {
format!(
r#"apiVersion: v1
kind: ConfigMap
metadata:
name: {name}
namespace: {namespace}
labels:
app: {name}
x86-optimized: "true"
data:
TARGET_TRIPLE: "x86_64-unknown-linux-gnu"
OPT_LEVEL: "3"
MARCH: "x86-64-v3"
MTUNE: "generic"
LTO_MODE: "thin"
DEBUG_INFO: "false"
LIBC: "gnu"
CLANG_STANDARD: "c++17"
"#,
name = name,
namespace = self.namespace
)
}
pub fn generate_ingress(&self, name: &str, host: &str) -> String {
format!(
r#"apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {name}
namespace: {namespace}
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- {host}
secretName: {name}-tls
rules:
- host: {host}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {name}
port:
number: 80
"#,
name = name,
namespace = self.namespace,
host = host
)
}
pub fn describe(&self) -> String {
format!(
"X86KubernetesSupport enabled={} namespace={} deployments={} services={} helm_charts={} overlays={} operators={}\n",
self.enabled, self.namespace,
self.deployments.len(), self.services.len(),
self.helm_charts.len(), self.kustomize_overlays.len(),
self.operators.len()
)
}
}
impl Default for X86KubernetesSupport {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86BuildMatrix {
pub name: String,
pub os_matrix: Vec<X86BuildOS>,
pub compiler_matrix: Vec<X86CompilerVersion>,
pub build_type_matrix: Vec<X86BuildType>,
pub feature_flags: Vec<String>,
pub exclude: Vec<X86BuildMatrixExclude>,
pub include: Vec<X86BuildMatrixInclude>,
}
#[derive(Debug, Clone)]
pub struct X86BuildOS {
pub name: String,
pub runner: String,
pub container: Option<String>,
pub package_manager: String,
pub pre_install: Vec<String>,
}
impl X86BuildOS {
pub fn ubuntu_2204() -> Self {
Self {
name: "ubuntu-22.04".to_string(),
runner: X86_GHA_RUNNER_UBUNTU.to_string(),
container: None,
package_manager: "apt-get".to_string(),
pre_install: vec![
"apt-get update".into(),
"apt-get install -y build-essential cmake ninja-build".into(),
],
}
}
pub fn windows_2022() -> Self {
Self {
name: "windows-2022".to_string(),
runner: X86_GHA_RUNNER_WINDOWS.to_string(),
container: None,
package_manager: "choco".to_string(),
pre_install: vec![
"choco install cmake ninja llvm".into(),
],
}
}
pub fn macos_13() -> Self {
Self {
name: "macos-13".to_string(),
runner: X86_GHA_RUNNER_MACOS.to_string(),
container: None,
package_manager: "brew".to_string(),
pre_install: vec![
"brew install cmake ninja llvm".into(),
],
}
}
pub fn alpine_container() -> Self {
Self {
name: "alpine".to_string(),
runner: X86_GHA_RUNNER_UBUNTU.to_string(),
container: Some("alpine:3.19".to_string()),
package_manager: "apk".to_string(),
pre_install: vec![
"apk add build-base cmake ninja clang".into(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct X86CompilerVersion {
pub name: String,
pub cc: String,
pub cxx: String,
pub version: String,
pub extra_flags: Vec<String>,
}
impl X86CompilerVersion {
pub fn clang_18() -> Self {
Self {
name: "clang-18".to_string(),
cc: "clang-18".to_string(),
cxx: "clang++-18".to_string(),
version: "18.1".to_string(),
extra_flags: vec!["-stdlib=libc++".into()],
}
}
pub fn clang_17() -> Self {
Self {
name: "clang-17".to_string(),
cc: "clang-17".to_string(),
cxx: "clang++-17".to_string(),
version: "17.0".to_string(),
extra_flags: vec!["-stdlib=libc++".into()],
}
}
pub fn gcc_13() -> Self {
Self {
name: "gcc-13".to_string(),
cc: "gcc-13".to_string(),
cxx: "g++-13".to_string(),
version: "13.2".to_string(),
extra_flags: Vec::new(),
}
}
pub fn gcc_12() -> Self {
Self {
name: "gcc-12".to_string(),
cc: "gcc-12".to_string(),
cxx: "g++-12".to_string(),
version: "12.3".to_string(),
extra_flags: Vec::new(),
}
}
pub fn msvc_2022() -> Self {
Self {
name: "msvc-2022".to_string(),
cc: "cl.exe".to_string(),
cxx: "cl.exe".to_string(),
version: "19.39".to_string(),
extra_flags: vec!["/std:c++20".into()],
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86BuildType {
Debug,
Release,
RelWithDebInfo,
MinSizeRel,
Asan,
Tsan,
Ubsan,
Coverage,
LTO,
Custom(String),
}
impl X86BuildType {
pub fn cmake_build_type(&self) -> &str {
match self {
Self::Debug => "Debug",
Self::Release => "Release",
Self::RelWithDebInfo => "RelWithDebInfo",
Self::MinSizeRel => "MinSizeRel",
Self::Asan => "AsanClang",
Self::Tsan => "TsanClang",
Self::Ubsan => "UbsanClang",
Self::Coverage => "Coverage",
Self::LTO => "ReleaseLTO",
Self::Custom(s) => s,
}
}
pub fn cmake_flags(&self) -> Vec<(&str, &str)> {
let mut flags = Vec::new();
match self {
Self::Debug => {
flags.push(("CMAKE_BUILD_TYPE", "Debug"));
flags.push(("ENABLE_OPTIMIZATIONS", "OFF"));
}
Self::Release => {
flags.push(("CMAKE_BUILD_TYPE", "Release"));
flags.push(("ENABLE_OPTIMIZATIONS", "ON"));
}
Self::RelWithDebInfo => {
flags.push(("CMAKE_BUILD_TYPE", "RelWithDebInfo"));
flags.push(("ENABLE_DEBUG_INFO", "ON"));
}
Self::MinSizeRel => {
flags.push(("CMAKE_BUILD_TYPE", "MinSizeRel"));
}
Self::Asan => {
flags.push(("CMAKE_BUILD_TYPE", "Debug"));
flags.push(("ENABLE_ASAN", "ON"));
}
Self::Tsan => {
flags.push(("CMAKE_BUILD_TYPE", "Debug"));
flags.push(("ENABLE_TSAN", "ON"));
}
Self::Ubsan => {
flags.push(("CMAKE_BUILD_TYPE", "Debug"));
flags.push(("ENABLE_UBSAN", "ON"));
}
Self::Coverage => {
flags.push(("CMAKE_BUILD_TYPE", "Debug"));
flags.push(("ENABLE_COVERAGE", "ON"));
}
Self::LTO => {
flags.push(("CMAKE_BUILD_TYPE", "Release"));
flags.push(("ENABLE_LTO", "ON"));
flags.push(("CMAKE_INTERPROCEDURAL_OPTIMIZATION", "ON"));
}
Self::Custom(_) => {}
}
flags
}
}
impl fmt::Display for X86BuildType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Custom(s) => write!(f, "{}", s),
_ => write!(f, "{:?}", self),
}
}
}
#[derive(Debug, Clone)]
pub struct X86BuildMatrixExclude {
pub os: Option<String>,
pub compiler: Option<String>,
pub build_type: Option<String>,
pub reason: String,
}
#[derive(Debug, Clone)]
pub struct X86BuildMatrixInclude {
pub os: String,
pub compiler: String,
pub build_type: String,
pub extra_flags: Vec<String>,
pub name: Option<String>,
}
impl X86BuildMatrix {
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
os_matrix: vec![X86BuildOS::ubuntu_2204(), X86BuildOS::macos_13()],
compiler_matrix: vec![X86CompilerVersion::clang_18(), X86CompilerVersion::gcc_13()],
build_type_matrix: vec![X86BuildType::Debug, X86BuildType::Release],
feature_flags: Vec::new(),
exclude: Vec::new(),
include: Vec::new(),
}
}
pub fn full_matrix() -> Self {
Self {
os_matrix: vec![
X86BuildOS::ubuntu_2204(),
X86BuildOS::windows_2022(),
X86BuildOS::macos_13(),
X86BuildOS::alpine_container(),
],
compiler_matrix: vec![
X86CompilerVersion::clang_18(),
X86CompilerVersion::clang_17(),
X86CompilerVersion::gcc_13(),
X86CompilerVersion::gcc_12(),
],
build_type_matrix: vec![
X86BuildType::Debug,
X86BuildType::Release,
X86BuildType::RelWithDebInfo,
X86BuildType::Asan,
X86BuildType::Tsan,
X86BuildType::Ubsan,
X86BuildType::LTO,
],
..Self::new("full")
}
}
pub fn total_combinations(&self) -> usize {
self.os_matrix.len() * self.compiler_matrix.len() * self.build_type_matrix.len()
- self.exclude.len()
+ self.include.len()
}
pub fn generate_github_matrix(&self) -> String {
let mut yaml = String::from("strategy:\n fail-fast: false\n matrix:\n");
yaml.push_str(" os:\n");
for os in &self.os_matrix {
yaml.push_str(&format!(" - {}\n", os.name));
}
yaml.push_str(" compiler:\n");
for compiler in &self.compiler_matrix {
yaml.push_str(&format!(" - {}\n", compiler.name));
}
yaml.push_str(" build_type:\n");
for bt in &self.build_type_matrix {
yaml.push_str(&format!(" - {}\n", bt));
}
if !self.exclude.is_empty() {
yaml.push_str(" exclude:\n");
for ex in &self.exclude {
yaml.push_str(" - ");
let mut parts = Vec::new();
if let Some(ref os) = ex.os { parts.push(format!("os: {}", os)); }
if let Some(ref c) = ex.compiler { parts.push(format!("compiler: {}", c)); }
if let Some(ref bt) = ex.build_type { parts.push(format!("build_type: {}", bt)); }
yaml.push_str(&parts.join(", "));
yaml.push_str(&format!(" # {}\n", ex.reason));
}
}
if !self.include.is_empty() {
yaml.push_str(" include:\n");
for inc in &self.include {
yaml.push_str(&format!(" - os: {}\n compiler: {}\n build_type: {}\n",
inc.os, inc.compiler, inc.build_type));
}
}
yaml
}
}
#[derive(Debug, Clone)]
pub struct X86CachingStrategy {
pub cache_type: X86CacheType,
pub cache_key: String,
pub cache_paths: Vec<String>,
pub restore_keys: Vec<String>,
pub max_cache_size_mb: usize,
pub compression_level: u8,
pub s3_bucket: Option<String>,
pub s3_endpoint: Option<String>,
pub gha_cache_enabled: bool,
pub local_cache_dir: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86CacheType {
Ccache,
Sccache,
CcacheWithS3,
SccacheWithS3,
SccacheWithGCS,
BuildDirectory,
ConanCache,
VcpkgCache,
DockerLayerCache,
Custom(String),
}
impl X86CacheType {
pub fn tool_name(&self) -> &str {
match self {
Self::Ccache => "ccache",
Self::Sccache => "sccache",
Self::CcacheWithS3 => "ccache",
Self::SccacheWithS3 => "sccache",
Self::SccacheWithGCS => "sccache",
Self::BuildDirectory => "build_dir",
Self::ConanCache => "conan",
Self::VcpkgCache => "vcpkg",
Self::DockerLayerCache => "docker",
Self::Custom(s) => s,
}
}
pub fn env_vars(&self) -> Vec<(String, String)> {
match self {
Self::Sccache | Self::SccacheWithS3 | Self::SccacheWithGCS => {
vec![
("CMAKE_C_COMPILER_LAUNCHER".into(), "sccache".into()),
("CMAKE_CXX_COMPILER_LAUNCHER".into(), "sccache".into()),
]
}
Self::Ccache | Self::CcacheWithS3 => {
vec![
("CMAKE_C_COMPILER_LAUNCHER".into(), "ccache".into()),
("CMAKE_CXX_COMPILER_LAUNCHER".into(), "ccache".into()),
("CCACHE_MAXSIZE".into(), "5G".into()),
]
}
_ => Vec::new(),
}
}
pub fn s3_command(&self, bucket: &str) -> Option<String> {
match self {
Self::SccacheWithS3 => Some(format!(
"export SCCACHE_BUCKET={}\nexport SCCACHE_S3_USE_SSL=true",
bucket
)),
Self::CcacheWithS3 => Some(format!(
"ccache -o remote_storage=s3://{}", bucket
)),
_ => None,
}
}
}
impl X86CachingStrategy {
pub fn ccache_default() -> Self {
Self {
cache_type: X86CacheType::Ccache,
cache_key: "ccache-x86-${{ runner.os }}-${{ github.ref }}".to_string(),
cache_paths: vec!["~/.cache/ccache".into()],
restore_keys: vec!["ccache-x86-${{ runner.os }}-".to_string()],
max_cache_size_mb: 5120,
compression_level: 6,
s3_bucket: None,
s3_endpoint: None,
gha_cache_enabled: true,
local_cache_dir: None,
}
}
pub fn sccache_s3_default(bucket: &str) -> Self {
Self {
cache_type: X86CacheType::SccacheWithS3,
cache_key: "sccache-x86-${{ runner.os }}-${{ hashFiles('**/CMakeLists.txt') }}".to_string(),
cache_paths: vec!["~/.cache/sccache".into()],
restore_keys: vec!["sccache-x86-${{ runner.os }}-".to_string()],
max_cache_size_mb: 20480,
compression_level: 6,
s3_bucket: Some(bucket.to_string()),
s3_endpoint: None,
gha_cache_enabled: false,
local_cache_dir: None,
}
}
pub fn generate_github_cache_step(&self) -> String {
if !self.gha_cache_enabled {
return String::new();
}
let step = format!(
r#" - name: Cache ({})
uses: actions/cache@v4
with:
path: {}
key: ${{{{ runner.os }}}}-{}-${{{{ hashFiles('**/CMakeLists.txt') }}}}
restore-keys: |
${{{{ runner.os }}}}-{}-
"#,
self.cache_type.tool_name(),
self.cache_paths.join("\n "),
self.cache_type.tool_name(),
self.cache_type.tool_name(),
);
step
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86CiSystemType {
GitHubActions,
GitLabCI,
Jenkins,
CircleCI,
AzurePipelines,
Buildkite,
DroneCI,
TeamCity,
Custom(String),
}
impl X86CiSystemType {
pub fn as_str(&self) -> &str {
match self {
Self::GitHubActions => "github-actions",
Self::GitLabCI => "gitlab-ci",
Self::Jenkins => "jenkins",
Self::CircleCI => "circleci",
Self::AzurePipelines => "azure-pipelines",
Self::Buildkite => "buildkite",
Self::DroneCI => "drone",
Self::TeamCity => "teamcity",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone)]
pub struct X86ArtifactConfig {
pub name: String,
pub paths: Vec<String>,
pub retention_days: u32,
pub compression: X86ArtifactCompression,
pub destination: X86ArtifactDestination,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ArtifactCompression {
None,
Zip,
TarGz,
TarZstd,
TarXz,
}
impl X86ArtifactCompression {
pub fn extension(&self) -> &str {
match self {
Self::None => "",
Self::Zip => ".zip",
Self::TarGz => ".tar.gz",
Self::TarZstd => ".tar.zst",
Self::TarXz => ".tar.xz",
}
}
}
#[derive(Debug, Clone)]
pub enum X86ArtifactDestination {
GitHubRelease,
GitLabPackage,
S3(String),
GCS(String),
AzureBlob(String),
JFrogArtifactory(String),
Nexus(String),
LocalPath(String),
DockerRegistry(String),
}
impl X86ArtifactDestination {
pub fn upload_command(&self, artifact_name: &str) -> String {
match self {
Self::GitHubRelease => format!("gh release upload v1.0 {}", artifact_name),
Self::GitLabPackage => format!("curl --header \"JOB-TOKEN: $CI_JOB_TOKEN\" --upload-file {} \"${{CI_API_V4_URL}}/projects/${{CI_PROJECT_ID}}/packages/generic/x86-artifacts/1.0/\"", artifact_name),
Self::S3(bucket) => format!("aws s3 cp {} s3://{}/artifacts/", artifact_name, bucket),
Self::GCS(bucket) => format!("gsutil cp {} gs://{}/artifacts/", artifact_name, bucket),
Self::AzureBlob(container) => format!("az storage blob upload --account-name storage --container-name {} --name {} --file {}", container, artifact_name, artifact_name),
Self::JFrogArtifactory(url) => format!("jfrog rt upload {} {}/artifacts/", artifact_name, url),
Self::Nexus(url) => format!("curl -u $NEXUS_USER:$NEXUS_PASS --upload-file {} {}/repository/releases/", artifact_name, url),
Self::LocalPath(path) => format!("cp {} {}/", artifact_name, path),
Self::DockerRegistry(registry) => format!("docker push {}/{}", registry, artifact_name),
}
}
}
impl X86ArtifactConfig {
pub fn new(name: &str, paths: Vec<&str>) -> Self {
Self {
name: name.to_string(),
paths: paths.iter().map(|s| s.to_string()).collect(),
retention_days: 30,
compression: X86ArtifactCompression::TarZstd,
destination: X86ArtifactDestination::GitHubRelease,
}
}
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone)]
pub struct X86CI_CD_Support {
pub enabled: bool,
pub ci_system: X86CiSystemType,
pub build_matrix: X86BuildMatrix,
pub caching: X86CachingStrategy,
pub artifacts: Vec<X86ArtifactConfig>,
pub pre_build_commands: Vec<String>,
pub build_commands: Vec<String>,
pub test_commands: Vec<String>,
pub post_build_commands: Vec<String>,
pub deploy_commands: Vec<String>,
pub notify_on: Vec<X86CiNotification>,
pub timeout_minutes: u32,
pub concurrency_group: Option<String>,
pub environment: HashMap<String, String>,
pub secrets: HashMap<String, String>,
pub docker_services: Vec<X86CiDockerService>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86CiNotification {
Slack(String),
Email(String),
Discord(String),
Teams(String),
Webhook(String),
OnSuccess,
OnFailure,
OnAlways,
}
#[derive(Debug, Clone)]
pub struct X86CiDockerService {
pub name: String,
pub image: String,
pub ports: Vec<String>,
pub env: HashMap<String, String>,
pub options: Vec<String>,
}
impl X86CI_CD_Support {
pub fn new() -> Self {
Self {
enabled: true,
ci_system: X86CiSystemType::GitHubActions,
build_matrix: X86BuildMatrix::new("x86-ci"),
caching: X86CachingStrategy::ccache_default(),
artifacts: Vec::new(),
pre_build_commands: vec![
"cmake -B build -G Ninja".into(),
" -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}".into(),
" -DCMAKE_C_COMPILER=${{ matrix.cc }}".into(),
" -DCMAKE_CXX_COMPILER=${{ matrix.cxx }}".into(),
],
build_commands: vec![
"cmake --build build --parallel $(nproc)".into(),
],
test_commands: vec![
"cd build && ctest --output-on-failure -j$(nproc)".into(),
],
post_build_commands: Vec::new(),
deploy_commands: Vec::new(),
notify_on: vec![X86CiNotification::OnFailure],
timeout_minutes: 60,
concurrency_group: Some("ci-${{ github.ref }}".into()),
environment: HashMap::new(),
secrets: HashMap::new(),
docker_services: Vec::new(),
}
}
pub fn for_all_ci() -> Self {
let mut ci = Self::new();
ci.build_matrix = X86BuildMatrix::full_matrix();
ci.caching = X86CachingStrategy::sccache_s3_default("x86-build-cache");
ci
}
pub fn generate_github_workflow(&self) -> String {
let mut yaml = format!(
r#"# GitHub Actions workflow generated by clang-cloud-x86
name: X86 CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: {}
cancel-in-progress: true
jobs:
build:
runs-on: ${{{{ matrix.os }}}}
"#,
self.concurrency_group.as_deref().unwrap_or("ci-${{ github.ref }}")
);
yaml.push_str(&self.build_matrix.generate_github_matrix());
if let Some(ref container) = self.build_matrix.os_matrix.first().and_then(|o| o.container.as_ref()) {
yaml.push_str(&format!(" container:\n image: {}\n", container));
}
yaml.push_str(" steps:\n");
yaml.push_str(" - uses: actions/checkout@v4\n");
if self.caching.gha_cache_enabled {
yaml.push_str(&self.caching.generate_github_cache_step());
}
yaml.push_str(&format!(
r#" - name: Setup Build Environment
run: |
{}
"#,
self.build_matrix.os_matrix.first()
.map(|o| o.pre_install.join("\n "))
.unwrap_or_default()
));
yaml.push_str(" - name: Install Dependencies\n run: |\n");
if self.caching.cache_type.tool_name() == "ccache" {
yaml.push_str(" sudo apt-get install -y ccache\n");
}
if self.caching.cache_type.tool_name() == "sccache" {
yaml.push_str(" cargo install sccache\n");
}
yaml.push('\n');
yaml.push_str(" - name: Configure CMake\n run: |\n");
for cmd in &self.pre_build_commands {
yaml.push_str(&format!(" {}\n", cmd));
}
yaml.push('\n');
yaml.push_str(" - name: Build\n run: |\n");
for cmd in &self.build_commands {
yaml.push_str(&format!(" {}\n", cmd));
}
yaml.push('\n');
yaml.push_str(" - name: Test\n run: |\n");
for cmd in &self.test_commands {
yaml.push_str(&format!(" {}\n", cmd));
}
yaml.push('\n');
for artifact in &self.artifacts {
yaml.push_str(&format!(
r#" - name: Upload {}
uses: actions/upload-artifact@v4
with:
name: {}
path: {}
retention-days: {}
"#,
artifact.name,
artifact.name,
artifact.paths.join("\n "),
artifact.retention_days
));
}
yaml
}
pub fn generate_gitlab_ci(&self) -> String {
let mut yaml = String::from("# GitLab CI generated by clang-cloud-x86\n\n");
yaml.push_str("stages:\n - build\n - test\n - deploy\n\n");
yaml.push_str("variables:\n");
yaml.push_str(" CCACHE_DIR: \"$CI_PROJECT_DIR/.ccache\"\n");
yaml.push_str(" CCACHE_MAXSIZE: \"5G\"\n\n");
yaml.push_str("cache:\n");
yaml.push_str(" key: \"$CI_COMMIT_REF_SLUG\"\n");
yaml.push_str(" paths:\n - .ccache/\n - build/\n\n");
for os in &self.build_matrix.os_matrix {
for compiler in &self.build_matrix.compiler_matrix {
for bt in &self.build_matrix.build_type_matrix {
let job_name = format!("build-{}-{}-{}",
os.name.replace('.', "").replace('-', "_"),
compiler.name.replace('.', "").replace('-', "_"),
bt.to_string().to_lowercase().replace("(", "_").replace(")", ""));
yaml.push_str(&format!("{}:\n", job_name));
yaml.push_str(&format!(" stage: build\n"));
if os.name.contains("ubuntu") || os.name.contains("alpine") {
yaml.push_str(&format!(" image: {}\n",
os.container.as_deref().unwrap_or("ubuntu:22.04")));
}
yaml.push_str(" before_script:\n");
for cmd in &os.pre_install {
yaml.push_str(&format!(" - {}\n", cmd));
}
yaml.push_str(" script:\n");
yaml.push_str(&format!(" - export CC={}\n", compiler.cc));
yaml.push_str(&format!(" - export CXX={}\n", compiler.cxx));
yaml.push_str(" - cmake -B build -DCMAKE_BUILD_TYPE=Release\n");
yaml.push_str(" - cmake --build build --parallel $(nproc)\n");
yaml.push_str(" - cd build && ctest --output-on-failure\n");
yaml.push_str(" artifacts:\n");
yaml.push_str(" paths:\n - build/\n");
yaml.push_str(" expire_in: 7 days\n\n");
}
}
}
yaml
}
pub fn generate_jenkinsfile(&self) -> String {
let mut jf = String::from("// Jenkins Pipeline generated by clang-cloud-x86\n\n");
jf.push_str("pipeline {\n");
jf.push_str(" agent any\n\n");
jf.push_str(" environment {\n");
jf.push_str(" CCACHE_DIR = \"${WORKSPACE}/.ccache\"\n");
jf.push_str(" CCACHE_MAXSIZE = '5G'\n");
jf.push_str(" }\n\n");
jf.push_str(" stages {\n");
jf.push_str(" stage('Build') {\n");
jf.push_str(" parallel {\n");
for os in &self.build_matrix.os_matrix {
for compiler in &self.build_matrix.compiler_matrix {
let stage_name = format!("{}_{}", os.name.replace(".", "_"), compiler.name.replace(".", "_"));
jf.push_str(&format!(" stage('{}') {{\n", stage_name));
jf.push_str(" agent { label 'x86-64' }\n");
jf.push_str(" steps {\n");
jf.push_str(&format!(" sh '''\n"));
jf.push_str(&format!(" export CC={}\n", compiler.cc));
jf.push_str(&format!(" export CXX={}\n", compiler.cxx));
jf.push_str(" cmake -B build -DCMAKE_BUILD_TYPE=Release\n");
jf.push_str(" cmake --build build --parallel \\$(nproc)\n");
jf.push_str(" cd build && ctest --output-on-failure\n");
jf.push_str(" '''\n");
jf.push_str(" }\n");
jf.push_str(" }\n");
}
}
jf.push_str(" }\n");
jf.push_str(" }\n");
jf.push_str(" }\n\n");
jf.push_str(" post {\n");
jf.push_str(" failure {\n");
jf.push_str(" echo 'Build failed!'\n");
jf.push_str(" }\n");
jf.push_str(" success {\n");
jf.push_str(" echo 'Build succeeded!'\n");
jf.push_str(" }\n");
jf.push_str(" }\n");
jf.push_str("}\n");
jf
}
pub fn generate_circleci_config(&self) -> String {
let cc = format!(
r#"# CircleCI config generated by clang-cloud-x86
version: 2.1
orbs:
cmake: circleci/cmake@1.0
executors:
x86-executor:
docker:
- image: ubuntu:22.04
resource_class: medium
environment:
CCACHE_DIR: /tmp/ccache
CCACHE_MAXSIZE: 5G
commands:
setup-build:
steps:
- run:
name: Install Dependencies
command: |
apt-get update
apt-get install -y build-essential cmake ninja-build clang ccache
- run:
name: Configure CMake
command: |
cmake -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
build:
steps:
- run:
name: Build
command: cmake --build build --parallel 4
test:
steps:
- run:
name: Test
command: cd build && ctest --output-on-failure
jobs:
build-and-test:
executor: x86-executor
steps:
- checkout
- setup-build
- build
- test
workflows:
version: 2
build:
jobs:
- build-and-test
"#
);
cc
}
pub fn describe(&self) -> String {
format!(
"X86CI_CD_Support system={:?} matrix_combinations={} artifacts={} timeout={}m\n",
self.ci_system,
self.build_matrix.total_combinations(),
self.artifacts.len(),
self.timeout_minutes
)
}
}
impl Default for X86CI_CD_Support {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86TerraformConfig {
pub required_providers: Vec<X86TerraformProvider>,
pub backend: Option<X86TerraformBackend>,
pub variables: HashMap<String, X86TerraformVariable>,
pub resources: Vec<String>,
pub outputs: HashMap<String, String>,
pub modules: Vec<X86TerraformModule>,
pub locals: HashMap<String, String>,
pub data_sources: Vec<String>,
pub terraform_version: String,
pub provider_configs: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct X86TerraformProvider {
pub name: String,
pub source: String,
pub version: String,
pub configuration: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct X86TerraformBackend {
pub backend_type: X86TerraformBackendType,
pub configuration: HashMap<String, String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86TerraformBackendType {
S3,
GCS,
AzureRM,
Local,
HTTP,
Consul,
Etcd,
Kubernetes,
Postgres,
TerraformCloud,
}
impl X86TerraformBackendType {
pub fn as_str(&self) -> &str {
match self {
Self::S3 => "s3",
Self::GCS => "gcs",
Self::AzureRM => "azurerm",
Self::Local => "local",
Self::HTTP => "http",
Self::Consul => "consul",
Self::Etcd => "etcd",
Self::Kubernetes => "kubernetes",
Self::Postgres => "pg",
Self::TerraformCloud => "cloud",
}
}
}
#[derive(Debug, Clone)]
pub struct X86TerraformVariable {
pub description: String,
pub var_type: String,
pub default: Option<String>,
pub sensitive: bool,
pub validation: Option<X86TerraformValidation>,
}
#[derive(Debug, Clone)]
pub struct X86TerraformValidation {
pub condition: String,
pub error_message: String,
}
#[derive(Debug, Clone)]
pub struct X86TerraformModule {
pub name: String,
pub source: String,
pub version: Option<String>,
pub variables: HashMap<String, String>,
}
impl X86TerraformConfig {
pub fn new_aws_compute() -> Self {
let mut config = Self {
required_providers: vec![
X86TerraformProvider {
name: "aws".to_string(),
source: "hashicorp/aws".to_string(),
version: "~> 5.0".to_string(),
configuration: HashMap::new(),
},
],
backend: Some(X86TerraformBackend {
backend_type: X86TerraformBackendType::S3,
configuration: {
let mut m = HashMap::new();
m.insert("bucket".into(), "x86-tfstate".into());
m.insert("key".into(), "terraform.tfstate".into());
m.insert("region".into(), "us-east-1".into());
m.insert("encrypt".into(), "true".into());
m
},
}),
variables: HashMap::new(),
resources: Vec::new(),
outputs: HashMap::new(),
modules: Vec::new(),
locals: HashMap::new(),
data_sources: Vec::new(),
terraform_version: ">= 1.6".to_string(),
provider_configs: HashMap::new(),
};
config.variables.insert("instance_type".into(), X86TerraformVariable {
description: "EC2 instance type for compute node".into(),
var_type: "string".into(),
default: Some("\"c6i.xlarge\"".into()),
sensitive: false,
validation: None,
});
config.variables.insert("ami_id".into(), X86TerraformVariable {
description: "AMI ID (x86_64)".into(),
var_type: "string".into(),
default: Some("\"ami-0c7217cdde317cfec\"".into()),
sensitive: false,
validation: Some(X86TerraformValidation {
condition: "can(regex(\"^ami-\", var.ami_id))".into(),
error_message: "AMI ID must start with 'ami-'".into(),
}),
});
config.resources.push(r#"
resource "aws_instance" "x86_compute" {
ami = var.ami_id
instance_type = var.instance_type
cpu_core_count = 4
cpu_threads_per_core = 2
cpu_options {
core_count = 4
threads_per_core = 2
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
instance_metadata_tags = "enabled"
}
root_block_device {
volume_type = "gp3"
volume_size = 100
iops = 3000
throughput = 125
}
user_data = base64encode(templatefile("${path.module}/user_data.sh", {
x86_optimizations = "true"
}))
tags = {
Name = "x86-compute-node"
Environment = var.environment
Optimized = "x86-64-v3"
}
}
"#.to_string());
config.outputs.insert("instance_id".into(), "aws_instance.x86_compute.id".into());
config.outputs.insert("public_ip".into(), "aws_instance.x86_compute.public_ip".into());
config
}
pub fn generate_main_tf(&self) -> String {
let mut tf = String::new();
tf.push_str(&format!("# Terraform configuration generated by clang-cloud-x86\n\n"));
tf.push_str(&format!("terraform {{\n required_version = \"{}\"\n", self.terraform_version));
if !self.required_providers.is_empty() {
tf.push_str(" required_providers {\n");
for p in &self.required_providers {
tf.push_str(&format!(" {} = {{\n source = \"{}\"\n version = \"{}\"\n }}\n",
p.name, p.source, p.version));
}
tf.push_str(" }\n");
}
if let Some(ref backend) = self.backend {
tf.push_str(&format!(" backend \"{}\" {{\n", backend.backend_type.as_str()));
for (k, v) in &backend.configuration {
tf.push_str(&format!(" {} = \"{}\"\n", k, v));
}
tf.push_str(" }\n");
}
tf.push_str("}\n\n");
for (name, config) in &self.provider_configs {
tf.push_str(&format!("provider \"{}\" {{\n{}\n}}\n\n", name, config));
}
for (name, var) in &self.variables {
tf.push_str(&format!("variable \"{}\" {{\n", name));
tf.push_str(&format!(" description = \"{}\"\n", var.description));
tf.push_str(&format!(" type = {}\n", var.var_type));
if let Some(ref default) = var.default {
tf.push_str(&format!(" default = {}\n", default));
}
if var.sensitive {
tf.push_str(" sensitive = true\n");
}
if let Some(ref validation) = var.validation {
tf.push_str(" validation {\n");
tf.push_str(&format!(" condition = {}\n", validation.condition));
tf.push_str(&format!(" error_message = \"{}\"\n", validation.error_message));
tf.push_str(" }\n");
}
tf.push_str("}\n\n");
}
if !self.locals.is_empty() {
tf.push_str("locals {\n");
for (k, v) in &self.locals {
tf.push_str(&format!(" {} = {}\n", k, v));
}
tf.push_str("}\n\n");
}
for ds in &self.data_sources {
tf.push_str(&ds);
tf.push('\n');
}
for res in &self.resources {
tf.push_str(&res);
tf.push('\n');
}
for module in &self.modules {
tf.push_str(&format!("module \"{}\" {{\n", module.name));
tf.push_str(&format!(" source = \"{}\"\n", module.source));
if let Some(ref ver) = module.version {
tf.push_str(&format!(" version = \"{}\"\n", ver));
}
for (k, v) in &module.variables {
tf.push_str(&format!(" {} = {}\n", k, v));
}
tf.push_str("}\n\n");
}
for (name, value) in &self.outputs {
tf.push_str(&format!("output \"{}\" {{\n value = {}\n}}\n\n", name, value));
}
tf
}
pub fn generate_user_data_script(&self) -> String {
r#"#!/bin/bash
# X86-optimized compute node setup
set -euo pipefail
# Install Clang and build tools
apt-get update
apt-get install -y \
clang-18 \
lld-18 \
cmake \
ninja-build \
ccache \
sccache
# X86-64 v3 optimizations
export CFLAGS="-march=x86-64-v3 -mtune=generic -O3 -flto=thin"
export CXXFLAGS="-march=x86-64-v3 -mtune=generic -O3 -flto=thin"
export LDFLAGS="-fuse-ld=lld -flto=thin"
# Setup ccache with S3 backend
ccache -o max_size=10G
ccache -o compression=true
ccache -o compression_level=6
echo "X86 compute node ready"
"#.to_string()
}
}
#[derive(Debug, Clone)]
pub struct X86PulumiConfig {
pub project_name: String,
pub runtime: String,
pub description: String,
pub stack_name: String,
pub resources: Vec<String>,
pub config: HashMap<String, String>,
pub exports: HashMap<String, String>,
}
impl X86PulumiConfig {
pub fn new(project_name: &str) -> Self {
Self {
project_name: project_name.to_string(),
runtime: "nodejs".to_string(),
description: "X86 infrastructure powered by Pulumi".to_string(),
stack_name: "dev".to_string(),
resources: Vec::new(),
config: HashMap::new(),
exports: HashMap::new(),
}
}
pub fn generate_pulumi_yaml(&self) -> String {
format!(
r#"name: {}
runtime: {}
description: {}
"#,
self.project_name, self.runtime, self.description
)
}
pub fn generate_pulumi_stack_yaml(&self) -> String {
let mut yaml = String::from("config:\n");
yaml.push_str(" aws:region: us-east-1\n");
yaml.push_str(" x86:instanceType: c6i.xlarge\n");
for (k, v) in &self.config {
yaml.push_str(&format!(" {}: {}\n", k, v));
}
yaml
}
pub fn generate_typescript_template(&self) -> String {
format!(
r#"// X86 compute infrastructure (Pulumi)
// Generated by clang-cloud-x86
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Security group for x86 compute
const x86Sg = new aws.ec2.SecurityGroup("x86-sg", {{
description: "X86 compute security group",
ingress: [
{{ protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["10.0.0.0/8"] }},
{{ protocol: "tcp", fromPort: 8080, toPort: 8080, cidrBlocks: ["0.0.0.0/0"] }},
],
egress: [
{{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"] }},
],
}});
// X86-optimized EC2 instance
const x86Instance = new aws.ec2.Instance("x86-compute", {{
ami: "ami-0c7217cdde317cfec",
instanceType: "c6i.xlarge",
cpuCoreCount: 4,
cpuThreadsPerCore: 2,
metadataOptions: {{
httpEndpoint: "enabled",
httpTokens: "required",
}},
rootBlockDevice: {{
volumeType: "gp3",
volumeSize: 100,
iops: 3000,
throughput: 125,
}},
vpcSecurityGroupIds: [x86Sg.id],
tags: {{
Name: "x86-compute",
Environment: "dev",
Optimized: "x86-64-v3",
}},
}});
export const instanceId = x86Instance.id;
export const publicIp = x86Instance.publicIp;
"#,
)
}
}
#[derive(Debug, Clone)]
pub struct X86AnsiblePlaybook {
pub name: String,
pub hosts: String,
pub r#become: bool,
pub vars: HashMap<String, String>,
pub tasks: Vec<X86AnsibleTask>,
pub handlers: Vec<X86AnsibleHandler>,
pub roles: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86AnsibleTask {
pub name: String,
pub module: String,
pub args: HashMap<String, String>,
pub when: Option<String>,
pub register_var: Option<String>,
pub changed_when: Option<String>,
pub notify: Vec<String>,
pub tags: Vec<String>,
pub loop_items: Option<Vec<String>>,
pub r#become: Option<bool>,
}
#[derive(Debug, Clone)]
pub struct X86AnsibleHandler {
pub name: String,
pub module: String,
pub args: HashMap<String, String>,
}
impl X86AnsibleTask {
pub fn new(name: &str, module: &str) -> Self {
Self {
name: name.to_string(),
module: module.to_string(),
args: HashMap::new(),
when: None,
register_var: None,
changed_when: None,
notify: Vec::new(),
tags: Vec::new(),
loop_items: None,
r#become: None,
}
}
pub fn arg(&mut self, key: &str, value: &str) -> &mut Self {
self.args.insert(key.to_string(), value.to_string());
self
}
pub fn with_when(&mut self, condition: &str) -> &mut Self {
self.when = Some(condition.to_string());
self
}
}
impl X86AnsiblePlaybook {
pub fn new(name: &str, hosts: &str) -> Self {
Self {
name: name.to_string(),
hosts: hosts.to_string(),
r#become: true,
vars: HashMap::new(),
tasks: Vec::new(),
handlers: Vec::new(),
roles: Vec::new(),
}
}
pub fn compiler_install_playbook() -> Self {
let mut pb = Self::new("Install Clang/LLVM toolchain on X86", "all");
pb.vars.insert("clang_version".into(), "18".into());
pb.vars.insert("llvm_version".into(), "18".into());
pb.vars.insert("install_dir".into(), "/usr/local".into());
pb.vars.insert("x86_optimize".into(), "true".into());
pb.tasks.push({
let mut t = X86AnsibleTask::new("Update apt cache", "apt");
t.arg("update_cache", "yes");
t.arg("cache_valid_time", "3600");
t.tags = vec!["packages".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Install build dependencies", "apt");
t.arg("name", "{{ item }}");
t.arg("state", "present");
t.loop_items = Some(vec![
"build-essential".into(),
"cmake".into(),
"ninja-build".into(),
"ccache".into(),
"python3".into(),
"libncurses5-dev".into(),
"libzstd-dev".into(),
]);
t.tags = vec!["packages".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Download LLVM source", "get_url");
t.arg("url", "https://github.com/llvm/llvm-project/releases/download/llvmorg-{{ llvm_version }}.1.0/llvm-project-{{ llvm_version }}.1.0.src.tar.xz");
t.arg("dest", "/tmp/llvm.tar.xz");
t.tags = vec!["download".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Extract LLVM source", "unarchive");
t.arg("src", "/tmp/llvm.tar.xz");
t.arg("dest", "/tmp");
t.arg("remote_src", "yes");
t.tags = vec!["extract".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Configure LLVM build", "command");
t.arg("cmd", "cmake -S /tmp/llvm-project-{{ llvm_version }}.1.0.src/llvm -B /tmp/llvm-build -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS='clang;lld' -DLLVM_TARGETS_TO_BUILD='X86' -DCMAKE_INSTALL_PREFIX={{ install_dir }} -DLLVM_USE_LINKER=lld -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache");
t.arg("chdir", "/tmp");
t.tags = vec!["build".into()];
t.when = Some("x86_optimize".into());
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Build LLVM", "command");
t.arg("cmd", "cmake --build /tmp/llvm-build --parallel {{ ansible_processor_vcpus }}");
t.tags = vec!["build".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Install LLVM", "command");
t.arg("cmd", "cmake --install /tmp/llvm-build");
t.tags = vec!["install".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Verify Clang installation", "command");
t.arg("cmd", "clang-{{ clang_version }} --version");
t.register_var = Some("clang_version_output".into());
t.tags = vec!["verify".into()];
t
});
pb.tasks.push({
let mut t = X86AnsibleTask::new("Cleanup build artifacts", "file");
t.arg("path", "/tmp/llvm-{{ item }}");
t.arg("state", "absent");
t.loop_items = Some(vec!["build".into(), "tar.xz".into()]);
t.tags = vec!["cleanup".into()];
t
});
pb
}
pub fn generate_yaml(&self) -> String {
let mut yaml = String::from("---\n");
yaml.push_str(&format!("- name: {}\n", self.name));
yaml.push_str(&format!(" hosts: {}\n", self.hosts));
yaml.push_str(&format!(" become: {}\n", if self.r#become { "yes" } else { "no" }));
if !self.vars.is_empty() {
yaml.push_str(" vars:\n");
for (k, v) in &self.vars {
yaml.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
if !self.roles.is_empty() {
yaml.push_str(" roles:\n");
for role in &self.roles {
yaml.push_str(&format!(" - {}\n", role));
}
}
if !self.tasks.is_empty() {
yaml.push_str(" tasks:\n");
for task in &self.tasks {
yaml.push_str(&format!(" - name: {}\n", task.name));
yaml.push_str(&format!(" {}:\n", task.module));
for (k, v) in &task.args {
if v.contains('\n') {
yaml.push_str(&format!(" {}: |\n {}\n", k, v.replace('\n', "\n ")));
} else {
yaml.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
if let Some(ref when) = task.when {
yaml.push_str(&format!(" when: {}\n", when));
}
if let Some(ref reg) = task.register_var {
yaml.push_str(&format!(" register: {}\n", reg));
}
if !task.notify.is_empty() {
yaml.push_str(" notify:\n");
for n in &task.notify {
yaml.push_str(&format!(" - {}\n", n));
}
}
if !task.tags.is_empty() {
yaml.push_str(" tags:\n");
for tag in &task.tags {
yaml.push_str(&format!(" - {}\n", tag));
}
}
if let Some(ref items) = task.loop_items {
yaml.push_str(" loop:\n");
for item in items {
yaml.push_str(&format!(" - \"{}\"\n", item));
}
}
}
}
if !self.handlers.is_empty() {
yaml.push_str(" handlers:\n");
for handler in &self.handlers {
yaml.push_str(&format!(" - name: {}\n", handler.name));
yaml.push_str(&format!(" {}:\n", handler.module));
for (k, v) in &handler.args {
yaml.push_str(&format!(" {}: \"{}\"\n", k, v));
}
}
}
yaml
}
}
#[derive(Debug, Clone)]
pub struct X86InfraAsCode {
pub enabled: bool,
pub terraform: Option<X86TerraformConfig>,
pub pulumi: Option<X86PulumiConfig>,
pub ansible: Option<X86AnsiblePlaybook>,
pub cloudformation: bool,
pub arm_templates: bool,
pub deployment_manager: bool,
pub bicep: bool,
pub cdk: bool,
}
impl X86InfraAsCode {
pub fn new() -> Self {
Self {
enabled: true,
terraform: Some(X86TerraformConfig::new_aws_compute()),
pulumi: None,
ansible: Some(X86AnsiblePlaybook::compiler_install_playbook()),
cloudformation: false,
arm_templates: false,
deployment_manager: false,
bicep: false,
cdk: false,
}
}
pub fn full() -> Self {
let mut iac = Self::new();
iac.pulumi = Some(X86PulumiConfig::new("x86-infra"));
iac.cloudformation = true;
iac.cdk = true;
iac
}
pub fn describe(&self) -> String {
format!(
"X86InfraAsCode enabled={} terraform={} pulumi={} ansible={}\n",
self.enabled,
self.terraform.is_some(),
self.pulumi.is_some(),
self.ansible.is_some()
)
}
}
impl Default for X86InfraAsCode {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86OpenTelemetryConfig {
pub enabled: bool,
pub exporter: X86OtelExporterType,
pub endpoint: String,
pub service_name: String,
pub service_version: String,
pub sample_rate: f64,
pub batch_timeout_ms: u64,
pub max_queue_size: usize,
pub max_export_batch_size: usize,
pub compression: X86OtelCompression,
pub headers: HashMap<String, String>,
pub resource_attributes: HashMap<String, String>,
pub span_processors: Vec<X86OtelSpanProcessor>,
pub propagators: Vec<X86OtelPropagator>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86OtelExporterType {
OtlpGrpc,
OtlpHttp,
Jaeger,
Zipkin,
Console,
Prometheus,
None,
Custom(String),
}
impl X86OtelExporterType {
pub fn protocol(&self) -> &str {
match self {
Self::OtlpGrpc => "grpc",
Self::OtlpHttp => "http/protobuf",
Self::Jaeger => "jaeger/thrift",
Self::Zipkin => "http/json",
Self::Console => "console",
Self::Prometheus => "prometheus",
Self::None => "none",
Self::Custom(_) => "custom",
}
}
pub fn default_endpoint(&self) -> &str {
match self {
Self::OtlpGrpc => "http://localhost:4317",
Self::OtlpHttp => "http://localhost:4318",
Self::Jaeger => "http://localhost:14268/api/traces",
Self::Zipkin => "http://localhost:9411/api/v2/spans",
Self::Console => "stdout",
Self::Prometheus => "http://localhost:9090",
Self::None => "",
Self::Custom(_) => "",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86OtelCompression {
None,
Gzip,
Zstd,
Deflate,
}
impl X86OtelCompression {
pub fn as_str(&self) -> &str {
match self {
Self::None => "none",
Self::Gzip => "gzip",
Self::Zstd => "zstd",
Self::Deflate => "deflate",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86OtelSpanProcessor {
Simple,
Batch,
Custom(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86OtelPropagator {
TraceContext,
Baggage,
B3,
B3Multi,
Jaeger,
XRay,
OtTrace,
Custom(String),
}
impl X86OtelPropagator {
pub fn header_keys(&self) -> Vec<&str> {
match self {
Self::TraceContext => vec!["traceparent", "tracestate"],
Self::Baggage => vec!["baggage"],
Self::B3 => vec!["b3"],
Self::B3Multi => vec!["X-B3-TraceId", "X-B3-SpanId", "X-B3-ParentSpanId", "X-B3-Sampled", "X-B3-Flags"],
Self::Jaeger => vec!["uber-trace-id"],
Self::XRay => vec!["X-Amzn-Trace-Id"],
Self::OtTrace => vec!["ot-tracer-traceid", "ot-tracer-spanid", "ot-tracer-sampled"],
Self::Custom(_) => vec![],
}
}
pub fn inject_header_format(&self, trace_id: &str, span_id: &str) -> String {
match self {
Self::TraceContext => format!("00-{}-{}-01", trace_id, span_id),
Self::B3 => format!("{}-{}-1", trace_id, span_id),
Self::B3Multi => format!(
"X-B3-TraceId: {}\nX-B3-SpanId: {}\nX-B3-Sampled: 1",
trace_id, span_id
),
Self::Jaeger => format!("{}:{}:0:1", trace_id, span_id),
Self::XRay => format!("Root=1-{trace_id};Parent={span_id};Sampled=1",
trace_id = &trace_id[..8], span_id = span_id),
Self::OtTrace => format!("{}:{}:0:1", trace_id, span_id),
_ => format!("trace-id: {}", trace_id),
}
}
}
impl X86OpenTelemetryConfig {
pub fn new(service_name: &str) -> Self {
Self {
enabled: true,
exporter: X86OtelExporterType::OtlpGrpc,
endpoint: "http://localhost:4317".to_string(),
service_name: service_name.to_string(),
service_version: "1.0.0".to_string(),
sample_rate: 1.0,
batch_timeout_ms: 5000,
max_queue_size: 2048,
max_export_batch_size: 512,
compression: X86OtelCompression::Gzip,
headers: HashMap::new(),
resource_attributes: HashMap::new(),
span_processors: vec![X86OtelSpanProcessor::Batch],
propagators: vec![X86OtelPropagator::TraceContext, X86OtelPropagator::Baggage],
}
}
pub fn generate_cpp_includes(&self) -> String {
let mut includes = String::new();
includes.push_str("#include <opentelemetry/exporters/otlp/otlp_grpc_exporter.h>\n");
includes.push_str("#include <opentelemetry/sdk/trace/simple_processor.h>\n");
includes.push_str("#include <opentelemetry/sdk/trace/batch_span_processor.h>\n");
includes.push_str("#include <opentelemetry/sdk/trace/tracer_provider.h>\n");
includes.push_str("#include <opentelemetry/trace/provider.h>\n");
includes.push_str("#include <opentelemetry/context/propagation/global_propagator.h>\n");
includes.push_str("#include <opentelemetry/context/propagation/text_map_propagator.h>\n");
includes
}
pub fn generate_cpp_setup(&self) -> String {
format!(
r#"// OpenTelemetry setup generated by clang-cloud-x86
void setup_telemetry() {{
namespace otel = opentelemetry;
// Create OTLP exporter
otel::exporter::otlp::OtlpGrpcExporterOptions opts;
opts.endpoint = "{}";
opts.use_ssl_credentials = false;
auto exporter = std::make_unique<otel::exporter::otlp::OtlpGrpcExporter>(opts);
// Create batch span processor
otel::sdk::trace::BatchSpanProcessorOptions batch_opts;
batch_opts.max_queue_size = {};
batch_opts.schedule_delay_millis = std::chrono::milliseconds({});
batch_opts.max_export_batch_size = {};
auto processor = std::make_unique<otel::sdk::trace::BatchSpanProcessor>(
std::move(exporter), batch_opts);
// Create tracer provider
auto provider = std::make_shared<otel::sdk::trace::TracerProvider>(std::move(processor));
otel::trace::Provider::SetTracerProvider(provider);
// Set up propagators
otel::context::propagation::GlobalTextMapPropagator::SetGlobalPropagator(
opentelemetry::context::propagation::HttpTraceContext()
);
}}
auto get_tracer() {{
auto provider = opentelemetry::trace::Provider::GetTracerProvider();
return provider->GetTracer("{}", "{}");
}}
"#,
self.endpoint,
self.max_queue_size,
self.batch_timeout_ms,
self.max_export_batch_size,
self.service_name,
self.service_version
)
}
}
#[derive(Debug, Clone)]
pub struct X86StructuredLogging {
pub enabled: bool,
pub format: X86LogFormat,
pub level: X86LogLevel,
pub output: X86LogOutput,
pub include_timestamp: bool,
pub include_trace_id: bool,
pub include_span_id: bool,
pub include_file_location: bool,
pub include_thread_id: bool,
pub fields: HashMap<String, String>,
pub redact_patterns: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86LogFormat {
Json,
Logfmt,
Text,
Syslog,
CEF,
LEEF,
Custom(String),
}
impl X86LogFormat {
pub fn as_str(&self) -> &str {
match self {
Self::Json => "json",
Self::Logfmt => "logfmt",
Self::Text => "text",
Self::Syslog => "syslog",
Self::CEF => "cef",
Self::LEEF => "leef",
Self::Custom(_) => "custom",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum X86LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
Fatal,
}
impl X86LogLevel {
pub fn as_str(&self) -> &str {
match self {
Self::Trace => "TRACE",
Self::Debug => "DEBUG",
Self::Info => "INFO",
Self::Warn => "WARN",
Self::Error => "ERROR",
Self::Fatal => "FATAL",
}
}
pub fn from_str(s: &str) -> Option<Self> {
match s.to_uppercase().as_str() {
"TRACE" => Some(Self::Trace),
"DEBUG" => Some(Self::Debug),
"INFO" => Some(Self::Info),
"WARN" | "WARNING" => Some(Self::Warn),
"ERROR" => Some(Self::Error),
"FATAL" | "CRITICAL" => Some(Self::Fatal),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86LogOutput {
Stdout,
Stderr,
File(String),
Syslog,
Journald,
TCP(String),
UDP(String),
HTTP(String),
}
impl X86StructuredLogging {
pub fn new() -> Self {
Self {
enabled: true,
format: X86LogFormat::Json,
level: X86LogLevel::Info,
output: X86LogOutput::Stdout,
include_timestamp: true,
include_trace_id: true,
include_span_id: true,
include_file_location: false,
include_thread_id: false,
fields: HashMap::new(),
redact_patterns: Vec::new(),
}
}
pub fn format_log(&self, level: X86LogLevel, message: &str, extra: &HashMap<String, String>) -> String {
match self.format {
X86LogFormat::Json => {
let mut fields: Vec<String> = Vec::new();
fields.push(format!("\"level\":\"{}\"", level.as_str()));
fields.push(format!("\"message\":\"{}\"", message.replace('\"', "\\\"")));
if self.include_timestamp {
fields.push(format!("\"timestamp\":\"{}\"", "2024-01-01T00:00:00Z"));
}
if self.include_trace_id {
fields.push("\"trace_id\":\"00000000000000000000000000000000\"".to_string());
}
if self.include_span_id {
fields.push("\"span_id\":\"0000000000000000\"".to_string());
}
for (k, v) in extra {
fields.push(format!("\"{}\":\"{}\"", k, v.replace('\"', "\\\"")));
}
format!("{{{}}}", fields.join(","))
}
X86LogFormat::Logfmt => {
let mut parts = vec![
format!("level={}", level.as_str().to_lowercase()),
format!("msg=\"{}\"", message.replace('"', "\\\"")),
];
for (k, v) in extra {
parts.push(format!("{}=\"{}\"", k, v.replace('"', "\\\"")));
}
parts.join(" ")
}
X86LogFormat::Text => {
format!("[{}] {}", level.as_str(), message)
}
X86LogFormat::Syslog => {
format!("<{}>{} - {}", level as u8 + 1, "clang-cloud-x86", message)
}
_ => format!("{}: {}", level.as_str(), message),
}
}
}
impl Default for X86StructuredLogging {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86MetricsConfig {
pub enabled: bool,
pub prometheus_enabled: bool,
pub endpoint: String,
pub metrics_path: String,
pub namespace: String,
pub subsystem: String,
pub counters: Vec<X86MetricCounter>,
pub gauges: Vec<X86MetricGauge>,
pub histograms: Vec<X86MetricHistogram>,
pub summaries: Vec<X86MetricSummary>,
pub collect_interval_ms: u64,
pub push_gateway_url: Option<String>,
pub opentelemetry_metrics: bool,
}
#[derive(Debug, Clone)]
pub struct X86MetricCounter {
pub name: String,
pub help: String,
pub labels: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86MetricGauge {
pub name: String,
pub help: String,
pub labels: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct X86MetricHistogram {
pub name: String,
pub help: String,
pub labels: Vec<String>,
pub buckets: Vec<f64>,
}
#[derive(Debug, Clone)]
pub struct X86MetricSummary {
pub name: String,
pub help: String,
pub labels: Vec<String>,
pub quantiles: Vec<f64>,
}
impl X86MetricsConfig {
pub fn new(namespace: &str) -> Self {
Self {
enabled: true,
prometheus_enabled: true,
endpoint: "0.0.0.0:9090".to_string(),
metrics_path: "/metrics".to_string(),
namespace: namespace.to_string(),
subsystem: "x86_compiler".to_string(),
counters: vec![
X86MetricCounter {
name: "compilations_total".to_string(),
help: "Total number of compilations".to_string(),
labels: vec!["target".into(), "status".into()],
},
X86MetricCounter {
name: "optimizations_applied".to_string(),
help: "Number of optimizations applied".to_string(),
labels: vec!["pass_name".into()],
},
X86MetricCounter {
name: "container_builds_total".to_string(),
help: "Total container builds".to_string(),
labels: vec!["registry".into(), "status".into()],
},
],
gauges: vec![
X86MetricGauge {
name: "active_compilations".to_string(),
help: "Currently active compilations".to_string(),
labels: Vec::new(),
},
X86MetricGauge {
name: "cache_size_bytes".to_string(),
help: "Current cache size in bytes".to_string(),
labels: vec!["cache_type".into()],
},
],
histograms: vec![
X86MetricHistogram {
name: "compilation_duration_seconds".to_string(),
help: "Compilation duration in seconds".to_string(),
labels: vec!["target".into()],
buckets: vec![0.1, 0.5, 1.0, 5.0, 10.0, 30.0, 60.0, 120.0, 300.0],
},
X86MetricHistogram {
name: "binary_size_bytes".to_string(),
help: "Compiled binary size in bytes".to_string(),
labels: vec!["target".into()],
buckets: vec![1024.0, 10240.0, 102400.0, 1_048_576.0, 10_485_760.0, 104_857_600.0],
},
],
summaries: vec![
X86MetricSummary {
name: "request_latency".to_string(),
help: "Request latency summary".to_string(),
labels: vec!["endpoint".into()],
quantiles: vec![0.5, 0.9, 0.95, 0.99],
},
],
collect_interval_ms: 15000,
push_gateway_url: None,
opentelemetry_metrics: true,
}
}
pub fn generate_prometheus_metric(&self, counter: &X86MetricCounter, value: u64) -> String {
let label_str = if counter.labels.is_empty() {
String::new()
} else {
counter.labels.iter().map(|l| format!("{}=\"\"", l)).collect::<Vec<_>>().join(",")
};
format!("# HELP {}_{} {}\n# TYPE {}_{} counter\n{}_{}{{{}}} {}\n",
self.namespace, counter.name, counter.help,
self.namespace, counter.name,
self.namespace, counter.name,
label_str, value
)
}
pub fn generate_prometheus_gauge(&self, gauge: &X86MetricGauge, value: f64) -> String {
format!("# HELP {}_{} {}\n# TYPE {}_{} gauge\n{}_{} {}\n",
self.namespace, gauge.name, gauge.help,
self.namespace, gauge.name,
self.namespace, gauge.name,
value
)
}
pub fn generate_metrics_endpoint(&self) -> String {
format!(
r#"# X86 Prometheus metrics endpoint
# Generated by clang-cloud-x86
# HELP x86_compiler_build_info Build information
# TYPE x86_compiler_build_info gauge
x86_compiler_build_info{{version="1.0.0",target="x86_64-unknown-linux-gnu"}} 1
# HELP x86_compiler_compilations_total Total compilations
# TYPE x86_compiler_compilations_total counter
x86_compiler_compilations_total{{target="x86_64",status="success"}} 0
x86_compiler_compilations_total{{target="x86_64",status="failure"}} 0
# HELP x86_compiler_compilation_duration_seconds Compilation duration
# TYPE x86_compiler_compilation_duration_seconds histogram
x86_compiler_compilation_duration_seconds_bucket{{le="0.1"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="0.5"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="1"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="5"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="10"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="30"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="60"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="120"}} 0
x86_compiler_compilation_duration_seconds_bucket{{le="+Inf"}} 0
x86_compiler_compilation_duration_seconds_sum 0
x86_compiler_compilation_duration_seconds_count 0
# HELP x86_compiler_active_compilations Active compilations
# TYPE x86_compiler_active_compilations gauge
x86_compiler_active_compilations 0
# HELP x86_compiler_container_builds_total Container builds
# TYPE x86_compiler_container_builds_total counter
x86_compiler_container_builds_total{{registry="docker.io",status="success"}} 0
"#
)
}
}
#[derive(Debug, Clone)]
pub struct X86HealthCheck {
pub enabled: bool,
pub liveness_path: String,
pub readiness_path: String,
pub startup_path: Option<String>,
pub port: u16,
pub checks: Vec<X86HealthCheckComponent>,
pub response_format: X86HealthCheckFormat,
pub timeout_ms: u64,
}
#[derive(Debug, Clone)]
pub struct X86HealthCheckComponent {
pub name: String,
pub check_type: X86HealthCheckType,
pub critical: bool,
pub interval_secs: u64,
pub timeout_ms: u64,
}
#[derive(Debug, Clone)]
pub enum X86HealthCheckType {
HttpGet(String),
TcpConnect(String, u16),
Exec(String),
Grpc(String),
Database(String),
Cache(String),
Queue(String),
FileExists(String),
DiskSpace(String, u64),
Memory(u64),
Custom(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86HealthCheckFormat {
Plain,
Json,
Prometheus,
}
impl X86HealthCheckFormat {
pub fn content_type(&self) -> &str {
match self {
Self::Plain => "text/plain",
Self::Json => "application/json",
Self::Prometheus => "text/plain; version=0.0.4",
}
}
}
impl X86HealthCheck {
pub fn new(port: u16) -> Self {
Self {
enabled: true,
liveness_path: "/healthz".to_string(),
readiness_path: "/readyz".to_string(),
startup_path: Some("/startupz".to_string()),
port,
checks: vec![
X86HealthCheckComponent {
name: "disk-space".into(),
check_type: X86HealthCheckType::DiskSpace("/".into(), 100 * 1024 * 1024),
critical: true,
interval_secs: 30,
timeout_ms: 5000,
},
X86HealthCheckComponent {
name: "memory".into(),
check_type: X86HealthCheckType::Memory(50 * 1024 * 1024),
critical: false,
interval_secs: 15,
timeout_ms: 1000,
},
],
response_format: X86HealthCheckFormat::Json,
timeout_ms: 5000,
}
}
pub fn generate_health_handler_cpp(&self) -> String {
format!(
r#"// Health check handler generated by clang-cloud-x86
#include <string>
#include <unordered_map>
std::string health_check_response(const std::string& path) {{
std::unordered_map<std::string, bool> checks;
checks["disk-space"] = true;
checks["memory"] = true;
checks["compile-service"] = true;
bool is_healthy = true;
for (const auto& [name, ok] : checks) {{
if (!ok) {{ is_healthy = false; break; }}
}}
if (path == "{liveness}") {{
return "OK";
}}
if (path == "{readiness}") {{
return is_healthy ? "OK" : "NOT READY";
}}
return "UNKNOWN";
}}
"#,
liveness = self.liveness_path,
readiness = self.readiness_path
)
}
}
#[derive(Debug, Clone)]
pub struct X86Observability {
pub enabled: bool,
pub otel: X86OpenTelemetryConfig,
pub logging: X86StructuredLogging,
pub metrics: X86MetricsConfig,
pub health_check: X86HealthCheck,
pub distributed_tracing: X86DistributedTracing,
}
#[derive(Debug, Clone)]
pub struct X86DistributedTracing {
pub enabled: bool,
pub propagators: Vec<X86DistributedTracingPropagator>,
pub baggage_enabled: bool,
pub baggage_max_items: usize,
pub baggage_max_bytes_per_item: usize,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86DistributedTracingPropagator {
W3CTraceContext,
B3,
B3Multi,
Jaeger,
Datadog,
AWSXRay,
Lightstep,
Custom(String),
}
impl X86DistributedTracingPropagator {
pub fn inject_headers_template(&self, trace_id: &str, span_id: &str, sampled: bool) -> String {
let sampled_str = if sampled { "01" } else { "00" };
match self {
Self::W3CTraceContext => {
format!("traceparent: 00-{}-{}-{}\ntracestate: vendor=opentelemetry",
trace_id, span_id, sampled_str)
}
Self::B3 => {
format!("b3: {}-{}-{}",
trace_id, span_id, if sampled { "1" } else { "0" })
}
Self::B3Multi => {
format!("X-B3-TraceId: {}\nX-B3-SpanId: {}\nX-B3-ParentSpanId: {}\nX-B3-Sampled: {}",
trace_id, span_id, span_id, if sampled { "1" } else { "0" })
}
Self::Jaeger => {
format!("uber-trace-id: {}:{}:0:{}",
trace_id, span_id, if sampled { "1" } else { "0" })
}
Self::Datadog => {
format!("x-datadog-trace-id: {}\nx-datadog-parent-id: {}\nx-datadog-sampling-priority: {}",
trace_id, span_id, if sampled { "1" } else { "0" })
}
Self::AWSXRay => {
format!("X-Amzn-Trace-Id: Root=1-{trace_8};Parent={span_id};Sampled={sampled}",
trace_8 = &trace_id[..8],
span_id = span_id,
sampled = if sampled { "1" } else { "0" })
}
Self::Lightstep => {
format!("ot-tracer-traceid: {}\not-tracer-spanid: {}\not-tracer-sampled: {}",
trace_id, span_id, if sampled { "true" } else { "false" })
}
Self::Custom(_) => format!("x-trace-id: {}\nx-span-id: {}", trace_id, span_id),
}
}
}
impl Default for X86DistributedTracing {
fn default() -> Self {
Self {
enabled: true,
propagators: vec![
X86DistributedTracingPropagator::W3CTraceContext,
X86DistributedTracingPropagator::B3Multi,
],
baggage_enabled: true,
baggage_max_items: 180,
baggage_max_bytes_per_item: 4096,
}
}
}
impl X86Observability {
pub fn new(service_name: &str) -> Self {
Self {
enabled: true,
otel: X86OpenTelemetryConfig::new(service_name),
logging: X86StructuredLogging::new(),
metrics: X86MetricsConfig::new(service_name),
health_check: X86HealthCheck::new(8080),
distributed_tracing: X86DistributedTracing::default(),
}
}
pub fn full(service_name: &str) -> Self {
let mut obs = Self::new(service_name);
obs.otel.enabled = true;
obs.logging.enabled = true;
obs.metrics.enabled = true;
obs.health_check.enabled = true;
obs.distributed_tracing.enabled = true;
obs
}
pub fn describe(&self) -> String {
format!(
"X86Observability enabled={} otel={} prometheus={} health_check={} tracing={}\n",
self.enabled,
self.otel.enabled,
self.metrics.prometheus_enabled,
self.health_check.enabled,
self.distributed_tracing.enabled,
)
}
}
impl Default for X86Observability {
fn default() -> Self {
Self::new("x86-cloud-app")
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86SecretsBackend {
EnvironmentVariable,
File,
HashiCorpVault,
AWSSecretsManager,
GCPSecretManager,
AzureKeyVault,
KubernetesSecret,
DockerSecret,
SSMParameterStore,
Doppler,
Custom(String),
}
impl X86SecretsBackend {
pub fn as_str(&self) -> &str {
match self {
Self::EnvironmentVariable => "env",
Self::File => "file",
Self::HashiCorpVault => "vault",
Self::AWSSecretsManager => "aws-secrets-manager",
Self::GCPSecretManager => "gcp-secret-manager",
Self::AzureKeyVault => "azure-key-vault",
Self::KubernetesSecret => "kubernetes-secret",
Self::DockerSecret => "docker-secret",
Self::SSMParameterStore => "aws-ssm",
Self::Doppler => "doppler",
Self::Custom(_) => "custom",
}
}
pub fn fetch_command_template(&self) -> &str {
match self {
Self::AWSSecretsManager => "aws secretsmanager get-secret-value --secret-id {name} --query SecretString --output text",
Self::GCPSecretManager => "gcloud secrets versions access latest --secret={name}",
Self::AzureKeyVault => "az keyvault secret show --vault-name {vault} --name {name} --query value -o tsv",
Self::HashiCorpVault => "vault kv get -field=data secret/{path}",
Self::SSMParameterStore => "aws ssm get-parameter --name {name} --with-decryption --query Parameter.Value --output text",
Self::Doppler => "doppler secrets get {name} --plain",
_ => "echo $SECRET_{name}",
}
}
}
#[derive(Debug, Clone)]
pub struct X86SecretsConfig {
pub backend: X86SecretsBackend,
pub secret_names: HashMap<String, String>,
pub vault_addr: Option<String>,
pub vault_token: Option<String>,
pub vault_role_id: Option<String>,
pub vault_secret_id: Option<String>,
pub aws_region: Option<String>,
pub gcp_project: Option<String>,
pub azure_vault_name: Option<String>,
pub rotation_policy: X86SecretsRotationPolicy,
pub cache_ttl_secs: u64,
pub encryption_enabled: bool,
pub audit_logging: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86SecretsRotationPolicy {
None,
OnDemand,
Daily,
Weekly,
Monthly,
Custom(u64),
}
impl X86SecretsRotationPolicy {
pub fn as_seconds(&self) -> u64 {
match self {
Self::None => 0,
Self::OnDemand => 0,
Self::Daily => 86400,
Self::Weekly => 604800,
Self::Monthly => 2592000,
Self::Custom(secs) => *secs,
}
}
}
impl X86SecretsConfig {
pub fn env_var_default() -> Self {
Self {
backend: X86SecretsBackend::EnvironmentVariable,
secret_names: HashMap::new(),
vault_addr: None,
vault_token: None,
vault_role_id: None,
vault_secret_id: None,
aws_region: Some("us-east-1".into()),
gcp_project: None,
azure_vault_name: None,
rotation_policy: X86SecretsRotationPolicy::OnDemand,
cache_ttl_secs: 300,
encryption_enabled: true,
audit_logging: false,
}
}
pub fn vault_default(addr: &str, token: &str) -> Self {
Self {
backend: X86SecretsBackend::HashiCorpVault,
secret_names: HashMap::new(),
vault_addr: Some(addr.to_string()),
vault_token: Some(token.to_string()),
vault_role_id: None,
vault_secret_id: None,
aws_region: None,
gcp_project: None,
azure_vault_name: None,
rotation_policy: X86SecretsRotationPolicy::Daily,
cache_ttl_secs: 3600,
encryption_enabled: true,
audit_logging: true,
}
}
pub fn aws_secrets_manager(region: &str) -> Self {
Self {
backend: X86SecretsBackend::AWSSecretsManager,
secret_names: HashMap::new(),
vault_addr: None,
vault_token: None,
vault_role_id: None,
vault_secret_id: None,
aws_region: Some(region.to_string()),
gcp_project: None,
azure_vault_name: None,
rotation_policy: X86SecretsRotationPolicy::Daily,
cache_ttl_secs: 600,
encryption_enabled: true,
audit_logging: true,
}
}
pub fn add_secret(&mut self, name: &str, secret_id: &str) -> &mut Self {
self.secret_names.insert(name.to_string(), secret_id.to_string());
self
}
pub fn generate_env_file(&self) -> String {
let mut content = String::from("# Generated by clang-cloud-x86\n# Secrets configuration\n\n");
for (name, id) in &self.secret_names {
match self.backend {
X86SecretsBackend::EnvironmentVariable => {
let upper = name.to_uppercase();
let var_name = format!("{}_SECRET", upper);
content.push_str(&format!("{}=${{{}}}\n", var_name, var_name));
}
X86SecretsBackend::AWSSecretsManager => {
content.push_str(&format!("{}_SECRET=$(aws secretsmanager get-secret-value --secret-id {} --region {} --query SecretString --output text)\n",
name.to_uppercase(), id, self.aws_region.as_deref().unwrap_or("us-east-1")));
}
X86SecretsBackend::HashiCorpVault => {
content.push_str(&format!("{}_SECRET=$(vault kv get -field=data secret/{})\n",
name.to_uppercase(), id));
}
_ => {
content.push_str(&format!("{}_SECRET=<fetch from {}>\n",
name.to_uppercase(), self.backend.as_str()));
}
}
}
content
}
}
#[derive(Debug, Clone)]
pub struct X86IamConfig {
pub provider: X86CloudProvider,
pub role_arn: Option<String>,
pub role_session_name: Option<String>,
pub external_id: Option<String>,
pub policy_arns: Vec<String>,
pub assume_role_policy: Option<String>,
pub duration_seconds: u64,
pub web_identity_token_file: Option<String>,
pub source_identity: Option<String>,
pub tags: HashMap<String, String>,
pub transitive_tag_keys: Vec<String>,
pub permissions_boundary: Option<String>,
pub inline_policies: HashMap<String, String>,
}
impl X86IamConfig {
pub fn new(provider: X86CloudProvider) -> Self {
Self {
provider,
role_arn: None,
role_session_name: Some("x86-cloud-session".into()),
external_id: None,
policy_arns: Vec::new(),
assume_role_policy: None,
duration_seconds: 3600,
web_identity_token_file: None,
source_identity: None,
tags: HashMap::new(),
transitive_tag_keys: Vec::new(),
permissions_boundary: None,
inline_policies: HashMap::new(),
}
}
pub fn aws_lambda_execution() -> Self {
let mut config = Self::new(X86CloudProvider::AWS);
config.role_session_name = Some("x86-lambda-execution".into());
config.policy_arns = vec![
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole".into(),
"arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess".into(),
];
config.duration_seconds = 900;
config
}
pub fn aws_ecs_task_execution() -> Self {
let mut config = Self::new(X86CloudProvider::AWS);
config.role_session_name = Some("x86-ecs-task-execution".into());
config.policy_arns = vec![
"arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy".into(),
"arn:aws:iam::aws:policy/CloudWatchLogsFullAccess".into(),
];
config
}
pub fn generate_trust_policy(&self) -> String {
format!(
r#"{{
"Version": "2012-10-17",
"Statement": [
{{
"Effect": "Allow",
"Principal": {{
"Service": "ecs-tasks.amazonaws.com"
}},
"Action": "sts:AssumeRole",
"Condition": {{
"StringEquals": {{
"aws:SourceAccount": "123456789012"
}}
}}
}}
]
}}"#
)
}
pub fn sts_assume_command(&self) -> String {
let mut cmd = String::from("aws sts assume-role");
if let Some(ref role_arn) = self.role_arn {
cmd.push_str(&format!(" --role-arn {}", role_arn));
}
if let Some(ref session_name) = self.role_session_name {
cmd.push_str(&format!(" --role-session-name {}", session_name));
}
if let Some(ref ext_id) = self.external_id {
cmd.push_str(&format!(" --external-id {}", ext_id));
}
cmd.push_str(&format!(" --duration-seconds {}", self.duration_seconds));
cmd
}
}
#[derive(Debug, Clone)]
pub struct X86TlsConfig {
pub enabled: bool,
pub min_version: X86TlsVersion,
pub max_version: X86TlsVersion,
pub cert_file: Option<String>,
pub key_file: Option<String>,
pub ca_file: Option<String>,
pub ca_path: Option<String>,
pub verify_peer: bool,
pub verify_hostname: bool,
pub client_cert_required: bool,
pub cipher_suites: Vec<String>,
pub signature_algorithms: Vec<String>,
pub curves: Vec<String>,
pub alpn_protocols: Vec<String>,
pub session_cache_enabled: bool,
pub session_tickets_enabled: bool,
pub ocsp_stapling: bool,
pub sct_enabled: bool,
pub early_data: bool,
pub renegotiation_allowed: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum X86TlsVersion {
SSLv3,
TLSv10,
TLSv11,
TLSv12,
TLSv13,
}
impl X86TlsVersion {
pub fn as_str(&self) -> &str {
match self {
Self::SSLv3 => "SSLv3",
Self::TLSv10 => "TLSv1.0",
Self::TLSv11 => "TLSv1.1",
Self::TLSv12 => "TLSv1.2",
Self::TLSv13 => "TLSv1.3",
}
}
}
impl X86TlsConfig {
pub fn secure_default() -> Self {
Self {
enabled: true,
min_version: X86TlsVersion::TLSv12,
max_version: X86TlsVersion::TLSv13,
cert_file: None,
key_file: None,
ca_file: None,
ca_path: None,
verify_peer: true,
verify_hostname: true,
client_cert_required: false,
cipher_suites: vec![
"TLS_AES_256_GCM_SHA384".into(),
"TLS_CHACHA20_POLY1305_SHA256".into(),
"TLS_AES_128_GCM_SHA256".into(),
],
signature_algorithms: vec![
"ecdsa_secp256r1_sha256".into(),
"ecdsa_secp384r1_sha384".into(),
"rsa_pss_rsae_sha256".into(),
],
curves: vec![
"X25519".into(),
"P-256".into(),
"P-384".into(),
],
alpn_protocols: vec!["h2".into(), "http/1.1".into()],
session_cache_enabled: true,
session_tickets_enabled: true,
ocsp_stapling: true,
sct_enabled: false,
early_data: false,
renegotiation_allowed: false,
}
}
pub fn mtls_default(cert_file: &str, key_file: &str, ca_file: &str) -> Self {
let mut config = Self::secure_default();
config.cert_file = Some(cert_file.to_string());
config.key_file = Some(key_file.to_string());
config.ca_file = Some(ca_file.to_string());
config.client_cert_required = true;
config
}
pub fn generate_openssl_command(&self) -> String {
let mut cmd = String::from("openssl s_server");
if let Some(ref cert) = self.cert_file {
cmd.push_str(&format!(" -cert {}", cert));
}
if let Some(ref key) = self.key_file {
cmd.push_str(&format!(" -key {}", key));
}
if let Some(ref ca) = self.ca_file {
cmd.push_str(&format!(" -CAfile {}", ca));
}
if self.verify_peer {
cmd.push_str(" -Verify 2");
}
cmd
}
pub fn to_env_vars(&self) -> Vec<(String, String)> {
let mut vars = Vec::new();
if let Some(ref cert) = self.cert_file {
vars.push(("TLS_CERT_FILE".into(), cert.clone()));
}
if let Some(ref key) = self.key_file {
vars.push(("TLS_KEY_FILE".into(), key.clone()));
}
if let Some(ref ca) = self.ca_file {
vars.push(("TLS_CA_FILE".into(), ca.clone()));
}
vars
}
}
#[derive(Debug, Clone)]
pub struct X86SignedUrlConfig {
pub provider: X86CloudProvider,
pub url_signer: X86UrlSigner,
pub expiration_secs: u64,
pub region: Option<String>,
pub bucket: Option<String>,
pub key: Option<String>,
pub content_type: Option<String>,
pub content_disposition: Option<String>,
pub acl: Option<String>,
pub custom_headers: HashMap<String, String>,
pub signing_algorithm: X86SigningAlgorithm,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86UrlSigner {
AWSS3PresignedUrl,
AWSCloudFrontSignedUrl,
GCPStorageSignedUrl,
AzureStorageSasToken,
CloudflareR2PresignedUrl,
Custom(String),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86SigningAlgorithm {
HMACSHA1,
HMACSHA256,
RSA2048SHA256,
ECDSAP256SHA256,
HMACSHA256WithQuery,
}
impl X86SigningAlgorithm {
pub fn as_str(&self) -> &str {
match self {
Self::HMACSHA1 => "HMAC-SHA1",
Self::HMACSHA256 => "HMAC-SHA256",
Self::RSA2048SHA256 => "RSA2048-SHA256",
Self::ECDSAP256SHA256 => "ECDSA-P256-SHA256",
Self::HMACSHA256WithQuery => "HMAC-SHA256",
}
}
}
impl X86SignedUrlConfig {
pub fn aws_s3_presigned(bucket: &str, key: &str, expiration_secs: u64) -> Self {
Self {
provider: X86CloudProvider::AWS,
url_signer: X86UrlSigner::AWSS3PresignedUrl,
expiration_secs,
region: Some("us-east-1".into()),
bucket: Some(bucket.to_string()),
key: Some(key.to_string()),
content_type: None,
content_disposition: None,
acl: None,
custom_headers: HashMap::new(),
signing_algorithm: X86SigningAlgorithm::HMACSHA256,
}
}
pub fn gcp_storage_signed(bucket: &str, key: &str, expiration_secs: u64) -> Self {
Self {
provider: X86CloudProvider::GCP,
url_signer: X86UrlSigner::GCPStorageSignedUrl,
expiration_secs,
region: None,
bucket: Some(bucket.to_string()),
key: Some(key.to_string()),
content_type: None,
content_disposition: None,
acl: None,
custom_headers: HashMap::new(),
signing_algorithm: X86SigningAlgorithm::RSA2048SHA256,
}
}
pub fn generate_command(&self) -> String {
match self.url_signer {
X86UrlSigner::AWSS3PresignedUrl => {
format!(
"aws s3 presign s3://{}/{}{} --expires-in {}",
self.bucket.as_deref().unwrap_or("bucket"),
self.key.as_deref().unwrap_or("file"),
if let Some(ref ct) = self.content_type {
format!(" --content-type {}", ct)
} else {
String::new()
},
self.expiration_secs
)
}
X86UrlSigner::GCPStorageSignedUrl => {
format!(
"gsutil signurl -d {}s -m GET {} gs://{}/{}",
self.expiration_secs,
"<key-file>",
self.bucket.as_deref().unwrap_or("bucket"),
self.key.as_deref().unwrap_or("file"),
)
}
X86UrlSigner::AzureStorageSasToken => {
format!(
"az storage blob generate-sas \
--account-name {} \
--container-name {} \
--name {} \
--permissions r \
--expiry $(date -u -d \"+{} seconds\" +%Y-%m-%dT%H:%MZ) \
--https-only \
--output tsv",
"<account>",
self.bucket.as_deref().unwrap_or("container"),
self.key.as_deref().unwrap_or("blob"),
self.expiration_secs,
)
}
_ => format!("generate-signed-url --provider={} --bucket={} --key={}",
self.provider,
self.bucket.as_deref().unwrap_or("bucket"),
self.key.as_deref().unwrap_or("key")),
}
}
}
#[derive(Debug, Clone)]
pub struct X86WebhookVerification {
pub enabled: bool,
pub provider: X86WebhookProvider,
pub signing_secret: Option<String>,
pub signature_header: String,
pub timestamp_header: Option<String>,
pub tolerance_secs: u64,
pub algorithms: Vec<X86SigningAlgorithm>,
pub required_headers: Vec<String>,
pub ip_allowlist: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86WebhookProvider {
GitHub,
GitLab,
Stripe,
Twilio,
Slack,
Discord,
Shopify,
PagerDuty,
Datadog,
AWS,
GCP,
Azure,
Custom(String),
}
impl X86WebhookProvider {
pub fn signature_header(&self) -> &str {
match self {
Self::GitHub => "X-Hub-Signature-256",
Self::GitLab => "X-Gitlab-Token",
Self::Stripe => "Stripe-Signature",
Self::Twilio => "X-Twilio-Signature",
Self::Slack => "X-Slack-Signature",
Self::Discord => "X-Signature-Ed25519",
Self::Shopify => "X-Shopify-Hmac-SHA256",
Self::PagerDuty => "X-PagerDuty-Signature",
Self::Datadog => "X-Datadog-Signature-256",
Self::AWS => "X-Amz-Sns-Message-Type",
Self::GCP => "X-Goog-Channel-Token",
Self::Azure => "aeg-signature",
Self::Custom(_) => "X-Signature",
}
}
pub fn timestamp_header(&self) -> Option<&str> {
match self {
Self::GitHub | Self::Stripe | Self::Slack => Some("X-Request-Timestamp"),
Self::Twilio => Some("X-Twilio-Timestamp"),
_ => None,
}
}
pub fn verify_template(&self) -> String {
match self {
Self::GitHub => {
"HMAC-SHA256(payload, secret) == hex_decode(signature_header)".to_string()
}
Self::Stripe => {
"HMAC-SHA256(timestamp + '.' + payload, secret) == signature_header".to_string()
}
Self::Slack => {
"HMAC-SHA256('v0:' + timestamp + ':' + payload, secret) == 'v0=' + signature_header".to_string()
}
_ => {
"HMAC-SHA256(payload, secret) == signature_header_value".to_string()
}
}
}
}
impl X86WebhookVerification {
pub fn new(provider: X86WebhookProvider, secret: &str) -> Self {
let sig_header = provider.signature_header().to_string();
let ts_header = provider.timestamp_header().map(|s| s.to_string());
let req_headers = vec![sig_header.clone()];
Self {
enabled: true,
provider,
signing_secret: Some(secret.to_string()),
signature_header: sig_header,
timestamp_header: ts_header,
tolerance_secs: 300,
algorithms: vec![X86SigningAlgorithm::HMACSHA256],
required_headers: req_headers,
ip_allowlist: Vec::new(),
}
}
pub fn generate_cpp_verifier(&self) -> String {
format!(
r#"// Webhook signature verification generated by clang-cloud-x86
// Provider: {}
// Header: {}
#include <string>
#include <vector>
#include <openssl/hmac.h>
bool verify_webhook_signature(
const std::string& payload,
const std::string& signature_header_value,
const std::string& secret
) {{
// Compute HMAC-SHA256
unsigned char result[EVP_MAX_MD_SIZE];
unsigned int result_len;
HMAC(
EVP_sha256(),
secret.c_str(), static_cast<int>(secret.size()),
reinterpret_cast<const unsigned char*>(payload.c_str()), payload.size(),
result, &result_len
);
// Convert signature header from hex
std::string expected_hex;
for (unsigned int i = 0; i < result_len; i++) {{
char hex[3];
snprintf(hex, sizeof(hex), "%02x", result[i]);
expected_hex += hex;
}}
// Compare (constant-time for security)
if (expected_hex.size() != signature_header_value.size()) {{
return false;
}}
// Build expected: sha256=...
std::string expected = expected_hex;
bool match = true;
for (size_t i = 0; i < expected.size(); i++) {{
match &= (expected[i] == signature_header_value[i + 7]);
}}
return match;
}}
bool verify_timestamp(const std::string& timestamp_header, uint64_t tolerance_secs) {{
uint64_t timestamp = std::stoull(timestamp_header);
uint64_t now = static_cast<uint64_t>(std::time(nullptr));
return (now - timestamp) <= tolerance_secs;
}}
"#,
self.provider.signature_header(),
self.signature_header
)
}
}
#[derive(Debug, Clone)]
pub struct X86CloudSecurity {
pub enabled: bool,
pub secrets: X86SecretsConfig,
pub iam: X86IamConfig,
pub tls: X86TlsConfig,
pub signed_url: Option<X86SignedUrlConfig>,
pub webhook_verification: Option<X86WebhookVerification>,
pub encryption_at_rest: bool,
pub encryption_in_transit: bool,
pub audit_logging: bool,
pub vulnerability_scanning: bool,
pub compliance_frameworks: Vec<X86ComplianceFramework>,
pub security_headers: Vec<String>,
pub cors_config: Option<X86CorsConfig>,
pub rate_limiting_enabled: bool,
}
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum X86ComplianceFramework {
SOC2,
HIPAA,
PCI_DSS,
FedRAMP,
GDPR,
CCPA,
ISO27001,
NIST800_53,
CIS,
Custom(String),
}
impl X86ComplianceFramework {
pub fn as_str(&self) -> &str {
match self {
Self::SOC2 => "SOC2",
Self::HIPAA => "HIPAA",
Self::PCI_DSS => "PCI-DSS",
Self::FedRAMP => "FedRAMP",
Self::GDPR => "GDPR",
Self::CCPA => "CCPA",
Self::ISO27001 => "ISO-27001",
Self::NIST800_53 => "NIST-800-53",
Self::CIS => "CIS",
Self::Custom(_) => "Custom",
}
}
}
#[derive(Debug, Clone)]
pub struct X86CorsConfig {
pub allow_origin: Vec<String>,
pub allow_methods: Vec<String>,
pub allow_headers: Vec<String>,
pub expose_headers: Vec<String>,
pub max_age_secs: u64,
pub allow_credentials: bool,
}
impl X86CorsConfig {
pub fn default_permissive() -> Self {
Self {
allow_origin: vec!["*".into()],
allow_methods: vec!["GET".into(), "POST".into(), "PUT".into(), "DELETE".into(), "OPTIONS".into()],
allow_headers: vec!["Content-Type".into(), "Authorization".into(), "X-Request-ID".into()],
expose_headers: vec!["X-Request-ID".into(), "X-Trace-ID".into()],
max_age_secs: 86400,
allow_credentials: false,
}
}
}
impl X86CloudSecurity {
pub fn new() -> Self {
Self {
enabled: true,
secrets: X86SecretsConfig::env_var_default(),
iam: X86IamConfig::new(X86CloudProvider::AWS),
tls: X86TlsConfig::secure_default(),
signed_url: None,
webhook_verification: None,
encryption_at_rest: true,
encryption_in_transit: true,
audit_logging: true,
vulnerability_scanning: true,
compliance_frameworks: vec![X86ComplianceFramework::SOC2],
security_headers: vec![
"X-Content-Type-Options: nosniff".into(),
"X-Frame-Options: DENY".into(),
"X-XSS-Protection: 1; mode=block".into(),
"Strict-Transport-Security: max-age=31536000; includeSubDomains".into(),
"Content-Security-Policy: default-src 'self'".into(),
"Referrer-Policy: strict-origin-when-cross-origin".into(),
"Permissions-Policy: geolocation=(), microphone=()".into(),
],
cors_config: Some(X86CorsConfig::default_permissive()),
rate_limiting_enabled: true,
}
}
pub fn production() -> Self {
let mut sec = Self::new();
sec.tls = X86TlsConfig::secure_default();
sec.encryption_at_rest = true;
sec.encryption_in_transit = true;
sec.audit_logging = true;
sec.vulnerability_scanning = true;
sec.compliance_frameworks = vec![
X86ComplianceFramework::SOC2,
X86ComplianceFramework::ISO27001,
];
sec
}
pub fn describe(&self) -> String {
let mut d = format!("X86CloudSecurity enabled={}\n", self.enabled);
d.push_str(&format!(" Secrets backend: {:?}\n", self.secrets.backend));
d.push_str(&format!(" TLS: {} (min: {:?}, max: {:?})\n",
if self.tls.enabled { "enabled" } else { "disabled" },
self.tls.min_version, self.tls.max_version));
d.push_str(&format!(" Encryption at-rest: {} in-transit: {}\n",
self.encryption_at_rest, self.encryption_in_transit));
d.push_str(&format!(" Audit logging: {}\n", self.audit_logging));
d.push_str(&format!(" Compliance: {:?}\n", self.compliance_frameworks.iter().map(|f| f.as_str()).collect::<Vec<_>>()));
d
}
}
impl Default for X86CloudSecurity {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86CloudDriver {
pub cloud: X86Cloud,
pub source_files: Vec<String>,
pub output_file: Option<String>,
pub verbose: bool,
pub dry_run: bool,
pub dockerfile_output: Option<String>,
pub k8s_output_dir: Option<String>,
pub ci_output: Option<String>,
pub tf_output_dir: Option<String>,
}
impl X86CloudDriver {
pub fn new(cloud: X86Cloud) -> Self {
Self {
cloud,
source_files: Vec::new(),
output_file: None,
verbose: false,
dry_run: false,
dockerfile_output: Some("Dockerfile".to_string()),
k8s_output_dir: Some("k8s/".to_string()),
ci_output: Some(".github/workflows/ci.yml".to_string()),
tf_output_dir: Some("terraform/".to_string()),
}
}
pub fn add_source(&mut self, file: &str) -> &mut Self {
self.source_files.push(file.to_string());
self
}
pub fn compile_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.push("-target".to_string());
flags.push("x86_64-unknown-linux-gnu".to_string());
flags.push("-DCLOUD_X86_ENABLED=1".to_string());
flags.push("-DCLOUD_PROVIDER=".to_string() + self.cloud.provider.as_str());
if self.cloud.container_support.enabled {
flags.push("-DX86_CONTAINER_SUPPORT=1".to_string());
if self.cloud.container_support.buildkit_enabled {
flags.push("-DX86_BUILDKIT_ENABLED=1".to_string());
}
}
if self.cloud.serverless_support.enabled {
flags.push("-DX86_SERVERLESS_SUPPORT=1".to_string());
if self.cloud.serverless_support.x86_optimizations {
flags.push("-march=x86-64-v3".to_string());
}
}
if self.cloud.kubernetes_support.enabled {
flags.push("-DX86_K8S_SUPPORT=1".to_string());
}
if self.cloud.observability.enabled {
flags.push("-DX86_OBSERVABILITY=1".to_string());
if self.cloud.observability.otel.enabled {
flags.push("-DX86_OPENTELEMETRY=1".to_string());
}
}
if self.cloud.security.enabled {
flags.push("-DX86_CLOUD_SECURITY=1".to_string());
if self.cloud.security.tls.enabled {
flags.push("-DX86_CLOUD_TLS=1".to_string());
}
}
flags.push("-O3".to_string());
flags.push("-flto=thin".to_string());
flags.push("-fuse-ld=lld".to_string());
flags
}
pub fn linkage_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
flags.push("-lstdc++".to_string());
flags.push("-lpthread".to_string());
flags.push("-ldl".to_string());
if self.cloud.observability.enabled && self.cloud.observability.otel.enabled {
flags.push("-lopentelemetry_trace".to_string());
flags.push("-lopentelemetry_exporter_otlp_grpc".to_string());
}
if self.cloud.security.enabled && self.cloud.security.tls.enabled {
flags.push("-lssl".to_string());
flags.push("-lcrypto".to_string());
}
flags
}
pub fn compile(&self) -> X86CloudCompileResult {
let mut result = X86CloudCompileResult::new();
let flags = self.compile_flags();
result.flags_used = flags.clone();
result.source_files = self.source_files.clone();
if self.dry_run {
result.success = true;
return result;
}
result.success = !self.source_files.is_empty();
result.files_compiled = self.source_files.len();
result.output = self.output_file.clone()
.unwrap_or_else(|| "a.out".to_string());
if result.success {
if self.cloud.container_support.enabled {
result.dockerfile_generated = self.dockerfile_output.clone();
}
if self.cloud.kubernetes_support.enabled {
result.k8s_manifests_generated = self.k8s_output_dir.clone();
}
if self.cloud.ci_cd_support.enabled {
result.ci_config_generated = self.ci_output.clone();
}
if self.cloud.infra_as_code.enabled {
result.tf_config_generated = self.tf_output_dir.clone();
}
}
result
}
pub fn describe(&self) -> String {
format!(
"X86CloudDriver sources={} output={} verbose={} dry_run={}\n Flags: {:?}",
self.source_files.len(),
self.output_file.as_deref().unwrap_or("default"),
self.verbose, self.dry_run,
self.compile_flags()
)
}
}
impl Default for X86CloudDriver {
fn default() -> Self {
Self::new(X86Cloud::default())
}
}
#[derive(Debug, Clone)]
pub struct X86CloudCompileResult {
pub success: bool,
pub files_compiled: usize,
pub output: String,
pub flags_used: Vec<String>,
pub source_files: Vec<String>,
pub dockerfile_generated: Option<String>,
pub k8s_manifests_generated: Option<String>,
pub ci_config_generated: Option<String>,
pub tf_config_generated: Option<String>,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub compile_time_ms: u64,
}
impl X86CloudCompileResult {
pub fn new() -> Self {
Self {
success: false,
files_compiled: 0,
output: String::new(),
flags_used: Vec::new(),
source_files: Vec::new(),
dockerfile_generated: None,
k8s_manifests_generated: None,
ci_config_generated: None,
tf_config_generated: None,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
}
}
pub fn is_clean(&self) -> bool {
self.success && self.errors.is_empty()
}
pub fn summary(&self) -> String {
format!(
"X86Cloud result: success={} files={} artifacts={{dockerfile:{}, k8s:{}, ci:{}, tf:{}}} time={}ms",
self.success,
self.files_compiled,
self.dockerfile_generated.is_some(),
self.k8s_manifests_generated.is_some(),
self.ci_config_generated.is_some(),
self.tf_config_generated.is_some(),
self.compile_time_ms
)
}
}
impl Default for X86CloudCompileResult {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct X86CloudPipeline {
pub cloud: X86Cloud,
pub driver: X86CloudDriver,
pub results: Vec<X86CloudCompileResult>,
pub artifacts: X86CloudArtifactBundle,
pub summary: String,
}
impl X86CloudPipeline {
pub fn new(cloud: X86Cloud) -> Self {
Self {
driver: X86CloudDriver::new(cloud.clone()),
cloud,
results: Vec::new(),
artifacts: X86CloudArtifactBundle::new(),
summary: String::new(),
}
}
pub fn run(&mut self) {
self.artifacts = self.cloud.generate_all_artifacts();
let result = self.driver.compile();
self.results.push(result);
self.summary = format!(
"X86CloudPipeline run complete.\n Provider: {}\n Target: {}\n Artifacts: {}\n Result: {}",
self.cloud.provider,
self.cloud.target,
self.artifacts.count(),
if self.results.last().map(|r| r.success).unwrap_or(false) { "OK" } else { "FAILED" }
);
}
pub fn generate_all(&self) -> String {
let mut output = String::new();
output.push_str(&format!("# X86 Cloud Pipeline - {}\n\n", self.cloud.project_name));
output.push_str(&self.cloud.describe());
if let Some(ref dockerfile) = self.artifacts.dockerfile {
output.push_str("\n## Dockerfile\n```dockerfile\n");
output.push_str(dockerfile);
output.push_str("\n```\n");
}
if let Some(ref k8s_deploy) = self.artifacts.k8s_deployment {
output.push_str("\n## Kubernetes Deployment\n```yaml\n");
output.push_str(k8s_deploy);
output.push_str("\n```\n");
}
if let Some(ref k8s_svc) = self.artifacts.k8s_service {
output.push_str("\n## Kubernetes Service\n```yaml\n");
output.push_str(k8s_svc);
output.push_str("\n```\n");
}
if let Some(ref gh_workflow) = self.artifacts.github_workflow {
output.push_str("\n## GitHub Actions Workflow\n```yaml\n");
output.push_str(gh_workflow);
output.push_str("\n```\n");
}
if let Some(ref gitlab_ci) = self.artifacts.gitlab_ci {
output.push_str("\n## GitLab CI\n```yaml\n");
output.push_str(gitlab_ci);
output.push_str("\n```\n");
}
output
}
pub fn describe(&self) -> String {
self.summary.clone()
}
}
impl Default for X86CloudPipeline {
fn default() -> Self {
Self::new(X86Cloud::default())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cloud_provider_as_str() {
assert_eq!(X86CloudProvider::AWS.as_str(), "aws");
assert_eq!(X86CloudProvider::Azure.as_str(), "azure");
assert_eq!(X86CloudProvider::GCP.as_str(), "gcp");
}
#[test]
fn test_cloud_provider_default_region() {
assert_eq!(X86CloudProvider::AWS.default_region(), "us-east-1");
assert_eq!(X86CloudProvider::Azure.default_region(), "eastus");
assert_eq!(X86CloudProvider::GCP.default_region(), "us-central1");
}
#[test]
fn test_cloud_provider_container_registry() {
assert_eq!(
X86CloudProvider::AWS.container_registry_url(),
"public.ecr.aws"
);
assert_eq!(
X86CloudProvider::GCP.container_registry_url(),
"gcr.io"
);
}
#[test]
fn test_cloud_provider_display() {
assert_eq!(format!("{}", X86CloudProvider::AWS), "aws");
assert_eq!(format!("{}", X86CloudProvider::SelfHosted), "self-hosted");
}
#[test]
fn test_cloud_target_as_str() {
assert_eq!(X86CloudTarget::Container.as_str(), "container");
assert_eq!(X86CloudTarget::Serverless.as_str(), "serverless");
assert_eq!(X86CloudTarget::Kubernetes.as_str(), "kubernetes");
assert_eq!(X86CloudTarget::VM.as_str(), "vm");
assert_eq!(X86CloudTarget::Edge.as_str(), "edge");
}
#[test]
fn test_x86_cloud_new() {
let cloud = X86Cloud::new(X86CloudProvider::AWS, "us-west-2");
assert_eq!(cloud.region, "us-west-2");
assert_eq!(cloud.provider, X86CloudProvider::AWS);
assert!(cloud.enabled);
}
#[test]
fn test_x86_cloud_aws_default() {
let cloud = X86Cloud::aws_default();
assert_eq!(cloud.provider, X86CloudProvider::AWS);
assert_eq!(cloud.region, "us-east-1");
}
#[test]
fn test_x86_cloud_azure_default() {
let cloud = X86Cloud::azure_default();
assert_eq!(cloud.provider, X86CloudProvider::Azure);
assert_eq!(cloud.region, "eastus");
}
#[test]
fn test_x86_cloud_gcp_default() {
let cloud = X86Cloud::gcp_default();
assert_eq!(cloud.provider, X86CloudProvider::GCP);
assert_eq!(cloud.region, "us-central1");
}
#[test]
fn test_x86_cloud_for_serverless() {
let cloud = X86Cloud::for_serverless();
assert_eq!(cloud.target, X86CloudTarget::Serverless);
assert!(cloud.serverless_support.enabled);
}
#[test]
fn test_x86_cloud_for_kubernetes() {
let cloud = X86Cloud::for_kubernetes();
assert_eq!(cloud.target, X86CloudTarget::Kubernetes);
assert!(cloud.kubernetes_support.enabled);
}
#[test]
fn test_x86_cloud_for_hybrid() {
let cloud = X86Cloud::for_hybrid();
assert_eq!(cloud.target, X86CloudTarget::Hybrid);
assert!(cloud.container_support.enabled);
assert!(cloud.serverless_support.enabled);
assert!(cloud.kubernetes_support.enabled);
}
#[test]
fn test_x86_cloud_with_tag() {
let mut cloud = X86Cloud::default();
cloud.with_tag("env", "prod").with_tag("team", "x86");
assert_eq!(cloud.tags.get("env").unwrap(), "prod");
assert_eq!(cloud.tags.get("team").unwrap(), "x86");
}
#[test]
fn test_x86_cloud_with_environment() {
let mut cloud = X86Cloud::default();
cloud.with_environment("production");
assert_eq!(cloud.environment, "production");
}
#[test]
fn test_x86_cloud_describe() {
let cloud = X86Cloud::default();
let desc = cloud.describe();
assert!(desc.contains("X86Cloud"));
assert!(desc.contains(cloud.region.as_str()));
}
#[test]
fn test_x86_cloud_to_json() {
let cloud = X86Cloud::default();
let json = cloud.to_json();
assert!(json.contains("\"provider\""));
assert!(json.contains("\"region\""));
}
#[test]
fn test_x86_cloud_default() {
let cloud = X86Cloud::default();
assert_eq!(cloud.provider, X86CloudProvider::AWS);
assert_eq!(cloud.target, X86CloudTarget::Container);
assert!(cloud.enabled);
}
#[test]
fn test_x86_cloud_generate_all_artifacts() {
let cloud = X86Cloud::default();
let bundle = cloud.generate_all_artifacts();
assert!(bundle.count() > 0);
}
#[test]
fn test_artifact_bundle_new() {
let bundle = X86CloudArtifactBundle::new();
assert_eq!(bundle.count(), 0);
}
#[test]
fn test_artifact_bundle_count() {
let mut bundle = X86CloudArtifactBundle::new();
bundle.dockerfile = Some("FROM ubuntu".to_string());
assert_eq!(bundle.count(), 1);
bundle.github_workflow = Some("name: CI".to_string());
assert_eq!(bundle.count(), 2);
}
#[test]
fn test_artifact_bundle_artifacts() {
let mut bundle = X86CloudArtifactBundle::new();
bundle.dockerfile = Some("FROM ubuntu".to_string());
let names = bundle.artifacts();
assert!(names.contains(&"Dockerfile".to_string()));
}
#[test]
fn test_container_base_image_names() {
assert_eq!(X86ContainerBaseImage::Alpine.image_name("3.19"), "alpine:3.19");
assert_eq!(X86ContainerBaseImage::Ubuntu.image_name("22.04"), "ubuntu:22.04");
assert_eq!(X86ContainerBaseImage::Scratch.image_name(""), "scratch");
}
#[test]
fn test_container_base_image_default_tags() {
assert_eq!(X86ContainerBaseImage::Alpine.default_tag(), "3.19");
assert_eq!(X86ContainerBaseImage::Ubuntu.default_tag(), "22.04");
}
#[test]
fn test_container_package_manager() {
assert_eq!(X86ContainerBaseImage::Alpine.package_manager(), "apk");
assert_eq!(X86ContainerBaseImage::Ubuntu.package_manager(), "apt-get");
assert_eq!(X86ContainerBaseImage::CentOS.package_manager(), "yum");
assert_eq!(X86ContainerBaseImage::Distroless.package_manager(), "none");
}
#[test]
fn test_build_stage_new() {
let stage = X86BuildStage::new("builder", X86ContainerBaseImage::Ubuntu);
assert_eq!(stage.name, "builder");
assert!(!stage.is_final);
}
#[test]
fn test_build_stage_builder() {
let stage = X86BuildStage::builder("build");
assert_eq!(stage.name, "build");
assert!(!stage.is_final);
assert!(stage.run_commands.len() >= 2);
}
#[test]
fn test_build_stage_runner() {
let stage = X86BuildStage::runner("runtime", X86ContainerBaseImage::Alpine);
assert_eq!(stage.name, "runtime");
assert!(stage.is_final);
}
#[test]
fn test_build_stage_add_run() {
let mut stage = X86BuildStage::new("test", X86ContainerBaseImage::Ubuntu);
stage.add_run("echo hello");
assert_eq!(stage.run_commands[0], "echo hello");
}
#[test]
fn test_build_stage_add_copy() {
let mut stage = X86BuildStage::new("test", X86ContainerBaseImage::Ubuntu);
stage.add_copy("src", "/app");
assert_eq!(stage.copy_instructions[0], ("src".to_string(), "/app".to_string()));
}
#[test]
fn test_build_stage_add_env() {
let mut stage = X86BuildStage::new("test", X86ContainerBaseImage::Ubuntu);
stage.add_env("NODE_ENV", "production");
assert_eq!(stage.env_vars.get("NODE_ENV").unwrap(), "production");
}
#[test]
fn test_build_stage_with_workdir() {
let mut stage = X86BuildStage::new("test", X86ContainerBaseImage::Ubuntu);
stage.with_workdir("/app");
assert_eq!(stage.workdir.unwrap(), "/app");
}
#[test]
fn test_build_stage_with_entrypoint() {
let mut stage = X86BuildStage::new("test", X86ContainerBaseImage::Ubuntu);
stage.with_entrypoint(vec!["/app/server"]);
assert_eq!(stage.entrypoint.unwrap(), vec!["/app/server"]);
}
#[test]
fn test_build_stage_generate() {
let stage = X86BuildStage::builder("build");
let dockerfile = stage.generate();
assert!(dockerfile.contains("FROM"));
assert!(dockerfile.contains("AS build"));
assert!(dockerfile.contains("RUN"));
}
#[test]
fn test_healthcheck_new() {
let hc = X86ContainerHealthcheck::new(vec!["CMD", "echo ok"]);
assert_eq!(hc.interval_secs, 30);
assert_eq!(hc.retries, 3);
}
#[test]
fn test_healthcheck_http_get() {
let hc = X86ContainerHealthcheck::http_get("/health", 8080);
assert_eq!(hc.test.len(), 2);
assert!(hc.test[0].contains("CMD-SHELL"));
}
#[test]
fn test_healthcheck_tcp() {
let hc = X86ContainerHealthcheck::tcp_check(5432);
assert_eq!(hc.test.len(), 2);
}
#[test]
fn test_healthcheck_generate() {
let hc = X86ContainerHealthcheck::http_get("/health", 8080);
let r#gen = hc.generate();
assert!(r#gen.contains("HEALTHCHECK"));
assert!(r#gen.contains("interval="));
assert!(r#gen.contains("timeout="));
assert!(r#gen.contains("retries="));
}
#[test]
fn test_container_support_new() {
let cs = X86ContainerSupport::new();
assert!(cs.enabled);
assert!(cs.buildkit_enabled);
}
#[test]
fn test_container_support_full() {
let cs = X86ContainerSupport::full();
assert!(cs.multi_stage);
assert!(cs.buildkit_enabled);
assert!(cs.provenance_enabled);
}
#[test]
fn test_container_support_minimal() {
let cs = X86ContainerSupport::minimal();
assert!(!cs.multi_stage);
assert!(!cs.buildkit_enabled);
assert!(!cs.provenance_enabled);
}
#[test]
fn test_container_support_generate_dockerfile() {
let mut cs = X86ContainerSupport::new();
let stage = X86BuildStage::builder("build");
cs.add_stage(stage);
let df = cs.generate_dockerfile();
assert!(df.contains("# syntax="));
assert!(df.contains("FROM"));
}
#[test]
fn test_container_support_empty_dockerfile() {
let cs = X86ContainerSupport::new();
let df = cs.generate_dockerfile();
assert!(df.contains("FROM"));
assert!(!df.is_empty());
}
#[test]
fn test_container_support_buildx_command() {
let cs = X86ContainerSupport::new();
let cmd = cs.buildx_command();
assert!(cmd.contains("docker buildx build"));
assert!(cmd.contains("-t x86-app:latest"));
}
#[test]
fn test_container_support_describe() {
let cs = X86ContainerSupport::new();
let desc = cs.describe();
assert!(desc.contains("X86ContainerSupport"));
assert!(desc.contains("x86-app"));
}
#[test]
fn test_container_support_default() {
let cs = X86ContainerSupport::default();
assert!(cs.enabled);
}
#[test]
fn test_registry_dockerhub() {
let reg = X86ContainerRegistry::dockerhub("myuser", "myapp", "v1.0");
assert_eq!(reg.registry_url, "registry-1.docker.io");
assert_eq!(reg.repository, "myuser/myapp");
}
#[test]
fn test_registry_ecr() {
let reg = X86ContainerRegistry::ecr("123456789012", "myapp", "us-east-1");
assert!(reg.registry_url.contains("ecr"));
assert!(reg.registry_url.contains("amazonaws.com"));
}
#[test]
fn test_registry_gcr() {
let reg = X86ContainerRegistry::gcr("myproject", "myapp", "us");
assert!(reg.registry_url.contains("pkg.dev"));
}
#[test]
fn test_registry_acr() {
let reg = X86ContainerRegistry::acr("myregistry", "myapp");
assert!(reg.registry_url.contains("azurecr.io"));
}
#[test]
fn test_registry_full_image_path() {
let reg = X86ContainerRegistry::dockerhub("user", "app", "latest");
let path = reg.full_image_path();
assert_eq!(path, "registry-1.docker.io/user/app:latest");
}
#[test]
fn test_registry_login_command() {
let reg = X86ContainerRegistry::ecr("123456789012", "app", "us-east-1");
let cmd = reg.login_command();
assert!(cmd.contains("aws ecr get-login-password"));
}
#[test]
fn test_oci_manifest_new() {
let manifest = X86OciManifest::new("sha256:aaa", 1024);
assert_eq!(manifest.schema_version, 2);
assert_eq!(manifest.config.digest, "sha256:aaa");
}
#[test]
fn test_oci_manifest_add_layer() {
let mut manifest = X86OciManifest::new("sha256:aaa", 1024);
manifest.add_layer(X86OciLayer::new("sha256:bbb", 2048));
assert_eq!(manifest.layers.len(), 1);
}
#[test]
fn test_oci_manifest_to_json() {
let mut manifest = X86OciManifest::new("sha256:aaa", 1024);
manifest.add_layer(X86OciLayer::new("sha256:bbb", 2048));
let json = manifest.to_json();
assert!(json.contains("\"schemaVersion\":2"));
assert!(json.contains("\"layers\":["));
}
#[test]
fn test_oci_image_config_new() {
let config = X86OciImageConfig::new_x86_64();
assert_eq!(config.architecture, "amd64");
assert_eq!(config.os, "linux");
}
#[test]
fn test_oci_image_config_to_json() {
let config = X86OciImageConfig::new_x86_64();
let json = config.to_json();
assert!(json.contains("\"architecture\""));
assert!(json.contains("\"os\""));
}
#[test]
fn test_build_matrix_new() {
let matrix = X86BuildMatrix::new("test");
assert_eq!(matrix.name, "test");
assert!(matrix.os_matrix.len() >= 2);
assert!(matrix.compiler_matrix.len() >= 2);
assert!(matrix.build_type_matrix.len() >= 2);
}
#[test]
fn test_build_matrix_full() {
let matrix = X86BuildMatrix::full_matrix();
assert!(matrix.os_matrix.len() >= 3);
assert!(matrix.build_type_matrix.len() >= 5);
}
#[test]
fn test_build_matrix_total_combinations() {
let matrix = X86BuildMatrix::new("test");
let expected: usize = matrix.os_matrix.len()
* matrix.compiler_matrix.len()
* matrix.build_type_matrix.len();
assert_eq!(matrix.total_combinations(), expected);
}
#[test]
fn test_build_matrix_generate_github() {
let matrix = X86BuildMatrix::new("test");
let yaml = matrix.generate_github_matrix();
assert!(yaml.contains("matrix:"));
assert!(yaml.contains("os:"));
assert!(yaml.contains("compiler:"));
assert!(yaml.contains("build_type:"));
}
#[test]
fn test_build_os_ubuntu() {
let os = X86BuildOS::ubuntu_2204();
assert_eq!(os.runner, "ubuntu-22.04");
assert!(os.pre_install.len() >= 2);
}
#[test]
fn test_build_os_windows() {
let os = X86BuildOS::windows_2022();
assert_eq!(os.runner, "windows-2022");
}
#[test]
fn test_build_os_macos() {
let os = X86BuildOS::macos_13();
assert_eq!(os.runner, "macos-13");
}
#[test]
fn test_compiler_version_clang_18() {
let compiler = X86CompilerVersion::clang_18();
assert_eq!(compiler.cc, "clang-18");
assert_eq!(compiler.cxx, "clang++-18");
}
#[test]
fn test_compiler_version_gcc() {
let compiler = X86CompilerVersion::gcc_13();
assert_eq!(compiler.cc, "gcc-13");
}
#[test]
fn test_compiler_version_msvc() {
let compiler = X86CompilerVersion::msvc_2022();
assert_eq!(compiler.cc, "cl.exe");
}
#[test]
fn test_build_type_cmake_flags() {
let flags = X86BuildType::Release.cmake_flags();
assert!(flags.contains(&("CMAKE_BUILD_TYPE", "Release")));
let asan_flags = X86BuildType::Asan.cmake_flags();
assert!(asan_flags.contains(&("ENABLE_ASAN", "ON")));
}
#[test]
fn test_build_type_cmake_build_type() {
assert_eq!(X86BuildType::Debug.cmake_build_type(), "Debug");
assert_eq!(X86BuildType::LTO.cmake_build_type(), "ReleaseLTO");
}
#[test]
fn test_caching_ccache_default() {
let cache = X86CachingStrategy::ccache_default();
assert_eq!(cache.cache_type.tool_name(), "ccache");
assert!(cache.gha_cache_enabled);
}
#[test]
fn test_caching_sccache_s3() {
let cache = X86CachingStrategy::sccache_s3_default("my-bucket");
assert_eq!(cache.cache_type.tool_name(), "sccache");
assert_eq!(cache.s3_bucket.as_deref(), Some("my-bucket"));
assert!(!cache.gha_cache_enabled);
}
#[test]
fn test_cache_type_env_vars() {
let vars = X86CacheType::Sccache.env_vars();
let keys: Vec<&str> = vars.iter().map(|(k, _)| k.as_str()).collect();
assert!(keys.contains(&"CMAKE_C_COMPILER_LAUNCHER"));
let vars_ccache = X86CacheType::Ccache.env_vars();
let keys_ccache: Vec<&str> = vars_ccache.iter().map(|(k, _)| k.as_str()).collect();
assert!(keys_ccache.contains(&"CMAKE_C_COMPILER_LAUNCHER"));
}
#[test]
fn test_cache_type_s3_command() {
let cmd = X86CacheType::SccacheWithS3.s3_command("my-bucket");
assert!(cmd.is_some());
assert!(cmd.unwrap().contains("SCCACHE_BUCKET=my-bucket"));
}
#[test]
fn test_ci_cd_support_new() {
let ci = X86CI_CD_Support::new();
assert!(ci.enabled);
assert!(matches!(ci.ci_system, X86CiSystemType::GitHubActions));
}
#[test]
fn test_ci_cd_support_for_all_ci() {
let ci = X86CI_CD_Support::for_all_ci();
assert!(ci.build_matrix.total_combinations() > 10);
}
#[test]
fn test_ci_cd_generate_github_workflow() {
let ci = X86CI_CD_Support::new();
let yaml = ci.generate_github_workflow();
assert!(yaml.contains("name: X86 CI/CD"));
assert!(yaml.contains("on:"));
assert!(yaml.contains("jobs:"));
}
#[test]
fn test_ci_cd_generate_gitlab_ci() {
let ci = X86CI_CD_Support::new();
let yaml = ci.generate_gitlab_ci();
assert!(yaml.contains("stages:"));
assert!(yaml.contains("build"));
assert!(yaml.contains("test"));
}
#[test]
fn test_ci_cd_generate_jenkinsfile() {
let ci = X86CI_CD_Support::new();
let jf = ci.generate_jenkinsfile();
assert!(jf.contains("pipeline {"));
assert!(jf.contains("stage"));
}
#[test]
fn test_ci_cd_generate_circleci_config() {
let ci = X86CI_CD_Support::new();
let cc = ci.generate_circleci_config();
assert!(cc.contains("version: 2.1"));
assert!(cc.contains("workflows:"));
}
#[test]
fn test_ci_cd_describe() {
let ci = X86CI_CD_Support::new();
let desc = ci.describe();
assert!(desc.contains("X86CI_CD_Support"));
}
#[test]
fn test_artifact_config_new() {
let artifact = X86ArtifactConfig::new("binary", vec!["build/release/*"]);
assert_eq!(artifact.name, "binary");
assert_eq!(artifact.retention_days, 30);
}
#[test]
fn test_artifact_compression_extension() {
assert_eq!(X86ArtifactCompression::TarGz.extension(), ".tar.gz");
assert_eq!(X86ArtifactCompression::TarZstd.extension(), ".tar.zst");
assert_eq!(X86ArtifactCompression::None.extension(), "");
}
#[test]
fn test_artifact_destination_upload_command() {
let cmd = X86ArtifactDestination::S3("my-bucket".into())
.upload_command("binary.tar.zst");
assert!(cmd.contains("aws s3 cp"));
assert!(cmd.contains("my-bucket"));
}
#[test]
fn test_k8s_support_new() {
let ks = X86KubernetesSupport::new();
assert!(ks.enabled);
assert_eq!(ks.namespace, "default");
assert_eq!(ks.default_replicas, 2);
}
#[test]
fn test_k8s_support_full() {
let ks = X86KubernetesSupport::full();
assert!(ks.network_policies);
assert!(ks.pod_security_standards);
assert!(ks.cert_manager_integration);
}
#[test]
fn test_k8s_generate_deployment() {
let ks = X86KubernetesSupport::new();
let yaml = ks.generate_deployment("my-app", "myapp:v1");
assert!(yaml.contains("kind: Deployment"));
assert!(yaml.contains("myapp:v1"));
assert!(yaml.contains("replicas: 2"));
}
#[test]
fn test_k8s_generate_service() {
let ks = X86KubernetesSupport::new();
let yaml = ks.generate_service("my-app");
assert!(yaml.contains("kind: Service"));
assert!(yaml.contains("port: 80"));
assert!(yaml.contains("metrics"));
}
#[test]
fn test_k8s_generate_configmap() {
let ks = X86KubernetesSupport::new();
let yaml = ks.generate_configmap("my-config");
assert!(yaml.contains("kind: ConfigMap"));
assert!(yaml.contains("TARGET_TRIPLE"));
assert!(yaml.contains("MARCH"));
}
#[test]
fn test_k8s_generate_ingress() {
let ks = X86KubernetesSupport::new();
let yaml = ks.generate_ingress("my-app", "app.example.com");
assert!(yaml.contains("kind: Ingress"));
assert!(yaml.contains("app.example.com"));
}
#[test]
fn test_k8s_describe() {
let ks = X86KubernetesSupport::new();
let desc = ks.describe();
assert!(desc.contains("X86KubernetesSupport"));
}
#[test]
fn test_pod_spec_new() {
let pod = X86K8sPodSpec::new("my-pod");
assert_eq!(pod.name, "my-pod");
assert_eq!(pod.namespace, "default");
assert!(matches!(pod.restart_policy, X86K8sRestartPolicy::Always));
}
#[test]
fn test_pod_spec_add_container() {
let mut pod = X86K8sPodSpec::new("my-pod");
let container = X86K8sContainer::new("app", "image:v1");
pod.add_container(container);
assert_eq!(pod.containers.len(), 1);
assert_eq!(pod.containers[0].name, "app");
}
#[test]
fn test_pod_spec_generate_yaml() {
let mut pod = X86K8sPodSpec::new("my-pod");
pod.add_label("app", "test");
let container = X86K8sContainer::new("app", "image:v1");
pod.add_container(container);
let yaml = pod.generate_yaml(X86K8sResourceKind::Deployment);
assert!(yaml.contains("apiVersion:"));
assert!(yaml.contains("kind: Deployment"));
assert!(yaml.contains("my-pod"));
}
#[test]
fn test_k8s_container_new() {
let container = X86K8sContainer::new("app", "myapp:v1");
assert_eq!(container.name, "app");
assert_eq!(container.image, "myapp:v1");
assert!(matches!(container.image_pull_policy, X86K8sImagePullPolicy::IfNotPresent));
}
#[test]
fn test_k8s_container_with_command() {
let mut container = X86K8sContainer::new("app", "image:v1");
container.with_command(vec!["/app/server", "--port=8080"]);
assert_eq!(container.command.len(), 2);
}
#[test]
fn test_k8s_container_with_port() {
let mut container = X86K8sContainer::new("app", "image:v1");
container.with_port(8080);
container.with_port(9090);
assert_eq!(container.ports.len(), 2);
}
#[test]
fn test_helm_chart_new() {
let chart = X86HelmChart::new("myapp", "1.0.0");
assert_eq!(chart.name, "myapp");
assert_eq!(chart.api_version, X86_HELM_CHART_API_VERSION);
}
#[test]
fn test_helm_chart_generate_chart_yaml() {
let chart = X86HelmChart::new("myapp", "1.0.0");
let yaml = chart.generate_chart_yaml();
assert!(yaml.contains("apiVersion: v2"));
assert!(yaml.contains("name: myapp"));
assert!(yaml.contains("version: 1.0.0"));
}
#[test]
fn test_helm_chart_generate_values_yaml() {
let chart = X86HelmChart::new("myapp", "1.0.0");
let yaml = chart.generate_values_yaml();
assert!(yaml.contains("replicaCount:"));
assert!(yaml.contains("x86Optimizations:"));
}
#[test]
fn test_helm_chart_add_template() {
let mut chart = X86HelmChart::new("myapp", "1.0.0");
chart.add_template("deployment.yaml", "apiVersion: apps/v1");
assert_eq!(chart.templates.len(), 1);
}
#[test]
fn test_kustomize_overlay_new() {
let overlay = X86KustomizeOverlay::new("production");
assert_eq!(overlay.name, "production");
}
#[test]
fn test_kustomize_generate_yaml() {
let mut overlay = X86KustomizeOverlay::new("production");
overlay.namespace = Some("prod".into());
overlay.common_labels.insert("env".into(), "prod".into());
let yaml = overlay.generate_kustomization_yaml();
assert!(yaml.contains("kustomize.config.k8s.io/v1beta1"));
assert!(yaml.contains("namespace: prod"));
}
#[test]
fn test_operator_sdk_new() {
let op = X86OperatorSdkPattern::new("my-operator", "CompilerJob");
assert_eq!(op.kind, "CompilerJob");
assert_eq!(op.api_group, "x86.llvm.io");
}
#[test]
fn test_operator_generate_yaml() {
let op = X86OperatorSdkPattern::new("my-operator", "CompilerJob");
let yaml = op.generate_operator_yaml();
assert!(yaml.contains("ClusterServiceVersion"));
assert!(yaml.contains("my-operator"));
}
#[test]
fn test_serverless_support_new() {
let ss = X86ServerlessSupport::new();
assert!(ss.enabled);
assert!(ss.x86_optimizations);
assert!(ss.cold_start_optimization);
}
#[test]
fn test_serverless_support_full() {
let ss = X86ServerlessSupport::full();
assert!(ss.tiered_compilation);
assert!(ss.keep_warm);
}
#[test]
fn test_serverless_add_lambda() {
let mut ss = X86ServerlessSupport::new();
let func = X86AwsLambdaFunction::new("myFunc", "handler.main");
ss.add_lambda(func);
assert_eq!(ss.lambda_functions.len(), 1);
}
#[test]
fn test_serverless_add_azure() {
let mut ss = X86ServerlessSupport::new();
let func = X86AzureFunction::http_trigger("myFunc", "api/{id}");
ss.add_azure(func);
assert_eq!(ss.azure_functions.len(), 1);
}
#[test]
fn test_serverless_add_gcp() {
let mut ss = X86ServerlessSupport::new();
let func = X86GcpFunction::new("myFunc", "handler");
ss.add_gcp(func);
assert_eq!(ss.gcp_functions.len(), 1);
}
#[test]
fn test_serverless_add_worker() {
let mut ss = X86ServerlessSupport::new();
let worker = X86CfWorker::new("my-worker");
ss.add_worker(worker);
assert_eq!(ss.cf_workers.len(), 1);
}
#[test]
fn test_serverless_add_wasm() {
let mut ss = X86ServerlessSupport::new();
let wasm = X86WasmEdgeFunction::new("edge-func");
ss.add_wasm(wasm);
assert_eq!(ss.wasm_functions.len(), 1);
}
#[test]
fn test_serverless_to_clang_flags() {
let ss = X86ServerlessSupport::new();
let flags = ss.to_clang_flags();
assert!(!flags.is_empty());
assert!(flags.contains(&"-march=x86-64-v3".to_string()));
}
#[test]
fn test_serverless_describe() {
let ss = X86ServerlessSupport::new();
let desc = ss.describe();
assert!(desc.contains("X86ServerlessSupport"));
}
#[test]
fn test_lambda_function_new() {
let func = X86AwsLambdaFunction::new("testFunc", "handler.main");
assert_eq!(func.name, "testFunc");
assert_eq!(func.memory_mb, 128);
assert_eq!(func.timeout_secs, 30);
}
#[test]
fn test_lambda_generate_cfn_resource() {
let func = X86AwsLambdaFunction::new("testFunc", "handler.main");
let yaml = func.generate_cfn_resource();
assert!(yaml.contains("AWS::Lambda::Function"));
assert!(yaml.contains("testFunc"));
}
#[test]
fn test_lambda_generate_cpp_handler() {
let func = X86AwsLambdaFunction::new("testFunc", "handler.main");
let cpp = func.generate_cpp_handler();
assert!(cpp.contains("my_handler"));
assert!(cpp.contains("aws::lambda_runtime"));
}
#[test]
fn test_lambda_event_type_struct_name() {
assert_eq!(
X86AwsLambdaEventType::ApiGatewayV2.struct_name(),
"ApiGatewayV2Request"
);
assert_eq!(
X86AwsLambdaEventType::S3.struct_name(),
"S3Event"
);
}
#[test]
fn test_lambda_context_new() {
let ctx = X86AwsLambdaContext::new("myFunc", "req-123");
assert_eq!(ctx.function_name, "myFunc");
assert_eq!(ctx.aws_request_id, "req-123");
}
#[test]
fn test_azure_http_trigger() {
let func = X86AzureFunction::http_trigger("myFunc", "api/data");
assert!(matches!(func.trigger, X86AzureTriggerType::Http));
assert_eq!(func.route.as_deref(), Some("api/data"));
}
#[test]
fn test_azure_timer_trigger() {
let func = X86AzureFunction::timer_trigger("myFunc", "0 */5 * * * *");
assert!(matches!(func.trigger, X86AzureTriggerType::Timer));
assert_eq!(func.schedule.as_deref(), Some("0 */5 * * * *"));
}
#[test]
fn test_azure_queue_trigger() {
let func = X86AzureFunction::queue_trigger("myFunc", "myqueue", "AzureWebJobsStorage");
assert!(matches!(func.trigger, X86AzureTriggerType::Queue));
assert_eq!(func.queue_name.as_deref(), Some("myqueue"));
}
#[test]
fn test_azure_generate_function_json() {
let func = X86AzureFunction::http_trigger("myFunc", "api/hello");
let json = func.generate_function_json();
assert!(json.contains("httpTrigger"));
assert!(json.contains("myFunc"));
}
#[test]
fn test_azure_auth_level() {
assert_eq!(X86AzureAuthLevel::Anonymous.as_str(), "anonymous");
assert_eq!(X86AzureAuthLevel::Function.as_str(), "function");
assert_eq!(X86AzureAuthLevel::Admin.as_str(), "admin");
}
#[test]
fn test_gcp_function_new() {
let func = X86GcpFunction::new("myFunc", "handlerFunc");
assert_eq!(func.region, "us-central1");
assert_eq!(func.memory_mb, 256);
}
#[test]
fn test_gcp_gcloud_deploy_command() {
let func = X86GcpFunction::new("myFunc", "handlerFunc");
let cmd = func.gcloud_deploy_command();
assert!(cmd.contains("gcloud functions deploy"));
assert!(cmd.contains("--entry-point=handlerFunc"));
}
#[test]
fn test_gcp_ingress_settings() {
assert_eq!(X86GcpIngressSettings::AllowAll.flag(), "all");
assert_eq!(X86GcpIngressSettings::AllowInternalOnly.flag(), "internal-only");
}
#[test]
fn test_cf_worker_new() {
let worker = X86CfWorker::new("my-worker");
assert_eq!(worker.name, "my-worker");
assert_eq!(worker.main_module, "src/index.ts");
}
#[test]
fn test_cf_worker_add_kv_binding() {
let mut worker = X86CfWorker::new("my-worker");
worker.add_kv_binding("MY_KV", "abc123");
assert_eq!(worker.bindings.len(), 1);
}
#[test]
fn test_cf_worker_add_do_binding() {
let mut worker = X86CfWorker::new("my-worker");
worker.add_do_binding("COUNTER", "CounterClass");
assert_eq!(worker.bindings.len(), 1);
}
#[test]
fn test_cf_worker_add_r2_binding() {
let mut worker = X86CfWorker::new("my-worker");
worker.add_r2_binding("BUCKET", "my-bucket");
assert_eq!(worker.bindings.len(), 1);
}
#[test]
fn test_cf_worker_generate_wrangler_toml() {
let mut worker = X86CfWorker::new("my-worker");
worker.add_kv_binding("NS", "ns-id");
let toml = worker.generate_wrangler_toml();
assert!(toml.contains("name = \"my-worker\""));
assert!(toml.contains("kv_namespaces"));
}
#[test]
fn test_cf_usage_model() {
assert_eq!(X86CfUsageModel::Bundled.as_str(), "bundled");
assert_eq!(X86CfUsageModel::Unbound.as_str(), "unbound");
}
#[test]
fn test_wasm_edge_new() {
let wasm = X86WasmEdgeFunction::new("edge-func");
assert_eq!(wasm.target_triple, "wasm32-wasi");
assert_eq!(wasm.optimization_level, "O3");
}
#[test]
fn test_wasm_compile_command() {
let wasm = X86WasmEdgeFunction::new("edge-func");
let cmd = wasm.compile_command("source.c");
assert!(cmd.contains("--target=wasm32-wasi"));
assert!(cmd.contains("-O3"));
assert!(cmd.contains("source.c"));
}
#[test]
fn test_serverless_platform_as_str() {
assert_eq!(X86ServerlessPlatform::AWSLambda.as_str(), "aws_lambda");
assert_eq!(X86ServerlessPlatform::CloudflareWorkers.as_str(), "cloudflare_workers");
}
#[test]
fn test_serverless_platform_runtime() {
assert_eq!(X86ServerlessPlatform::AWSLambda.runtime_identifier(), "provided.al2");
}
#[test]
fn test_terraform_new_aws_compute() {
let tf = X86TerraformConfig::new_aws_compute();
assert_eq!(tf.required_providers.len(), 1);
assert_eq!(tf.required_providers[0].name, "aws");
}
#[test]
fn test_terraform_generate_main_tf() {
let tf = X86TerraformConfig::new_aws_compute();
let main = tf.generate_main_tf();
assert!(main.contains("terraform {"));
assert!(main.contains("required_providers"));
assert!(main.contains("variable \"instance_type\""));
}
#[test]
fn test_terraform_generate_user_data() {
let tf = X86TerraformConfig::new_aws_compute();
let script = tf.generate_user_data_script();
assert!(script.contains("#!/bin/bash"));
assert!(script.contains("clang-18"));
assert!(script.contains("x86-64-v3"));
}
#[test]
fn test_terraform_backend_type_as_str() {
assert_eq!(X86TerraformBackendType::S3.as_str(), "s3");
assert_eq!(X86TerraformBackendType::GCS.as_str(), "gcs");
}
#[test]
fn test_pulumi_new() {
let pc = X86PulumiConfig::new("my-project");
assert_eq!(pc.project_name, "my-project");
assert_eq!(pc.runtime, "nodejs");
}
#[test]
fn test_pulumi_generate_yaml() {
let pc = X86PulumiConfig::new("my-project");
let yaml = pc.generate_pulumi_yaml();
assert!(yaml.contains("name: my-project"));
assert!(yaml.contains("runtime: nodejs"));
}
#[test]
fn test_pulumi_generate_stack_yaml() {
let pc = X86PulumiConfig::new("my-project");
let yaml = pc.generate_pulumi_stack_yaml();
assert!(yaml.contains("config:"));
assert!(yaml.contains("aws:region"));
}
#[test]
fn test_pulumi_generate_typescript_template() {
let pc = X86PulumiConfig::new("my-project");
let ts = pc.generate_typescript_template();
assert!(ts.contains("pulumi"));
assert!(ts.contains("aws.ec2.Instance"));
}
#[test]
fn test_ansible_playbook_new() {
let pb = X86AnsiblePlaybook::new("Install Compiler", "all");
assert_eq!(pb.name, "Install Compiler");
assert_eq!(pb.hosts, "all");
assert!(pb.r#become);
}
#[test]
fn test_ansible_compiler_install_playbook() {
let pb = X86AnsiblePlaybook::compiler_install_playbook();
assert!(pb.tasks.len() >= 5);
}
#[test]
fn test_ansible_generate_yaml() {
let pb = X86AnsiblePlaybook::compiler_install_playbook();
let yaml = pb.generate_yaml();
assert!(yaml.contains("---"));
assert!(yaml.contains("name: Install Clang"));
assert!(yaml.contains("hosts: all"));
assert!(yaml.contains("apt:"));
assert!(yaml.contains("tasks:"));
}
#[test]
fn test_infra_as_code_new() {
let iac = X86InfraAsCode::new();
assert!(iac.enabled);
assert!(iac.terraform.is_some());
assert!(iac.ansible.is_some());
}
#[test]
fn test_infra_as_code_full() {
let iac = X86InfraAsCode::full();
assert!(iac.pulumi.is_some());
assert!(iac.cloudformation);
assert!(iac.cdk);
}
#[test]
fn test_infra_as_code_describe() {
let iac = X86InfraAsCode::new();
let desc = iac.describe();
assert!(desc.contains("X86InfraAsCode"));
}
#[test]
fn test_otel_new() {
let otel = X86OpenTelemetryConfig::new("my-service");
assert!(otel.enabled);
assert_eq!(otel.service_name, "my-service");
assert_eq!(otel.sample_rate, 1.0);
}
#[test]
fn test_otel_generate_cpp_setup() {
let otel = X86OpenTelemetryConfig::new("my-service");
let cpp = otel.generate_cpp_setup();
assert!(cpp.contains("setup_telemetry()"));
assert!(cpp.contains("OtlpGrpcExporter"));
assert!(cpp.contains("my-service"));
}
#[test]
fn test_otel_generate_cpp_includes() {
let otel = X86OpenTelemetryConfig::new("my-service");
let inc = otel.generate_cpp_includes();
assert!(inc.contains("opentelemetry/exporters/otlp"));
}
#[test]
fn test_otel_exporter_default_endpoint() {
assert_eq!(
X86OtelExporterType::OtlpGrpc.default_endpoint(),
"http://localhost:4317"
);
assert_eq!(
X86OtelExporterType::Jaeger.default_endpoint(),
"http://localhost:14268/api/traces"
);
}
#[test]
fn test_otel_compression_as_str() {
assert_eq!(X86OtelCompression::Gzip.as_str(), "gzip");
assert_eq!(X86OtelCompression::Zstd.as_str(), "zstd");
}
#[test]
fn test_tracing_propagator_headers() {
let headers = X86OtelPropagator::TraceContext.header_keys();
assert!(headers.contains(&"traceparent"));
assert!(headers.contains(&"tracestate"));
let b3_headers = X86OtelPropagator::B3Multi.header_keys();
assert!(b3_headers.contains(&"X-B3-TraceId"));
assert!(b3_headers.contains(&"X-B3-SpanId"));
}
#[test]
fn test_tracing_propagator_inject() {
let header = X86OtelPropagator::TraceContext.inject_header_format(
"00000000000000000000000000000001",
"0000000000000002",
);
assert!(header.contains("00-"));
assert!(header.contains("-01"));
let b3 = X86OtelPropagator::B3.inject_header_format(
"00000000000000000000000000000001",
"0000000000000002",
);
assert!(b3.contains("-1"));
}
#[test]
fn test_distributed_tracing_inject_headers() {
let headers = X86DistributedTracingPropagator::W3CTraceContext
.inject_headers_template("abc123", "def456", true);
assert!(headers.contains("traceparent:"));
assert!(headers.contains("01"));
let headers_b3 = X86DistributedTracingPropagator::B3
.inject_headers_template("abc123", "def456", false);
assert!(headers_b3.contains("b3:"));
assert!(headers_b3.contains("-0"));
}
#[test]
fn test_logging_new() {
let log = X86StructuredLogging::new();
assert!(log.enabled);
assert!(matches!(log.format, X86LogFormat::Json));
}
#[test]
fn test_logging_format_json() {
let log = X86StructuredLogging::new();
let mut extra = HashMap::new();
extra.insert("key".into(), "value".into());
let output = log.format_log(X86LogLevel::Info, "hello world", &extra);
assert!(output.contains("\"level\":\"INFO\""));
assert!(output.contains("\"message\":\"hello world\""));
assert!(output.contains("\"key\":\"value\""));
}
#[test]
fn test_logging_format_logfmt() {
let mut log = X86StructuredLogging::new();
log.format = X86LogFormat::Logfmt;
let mut extra = HashMap::new();
extra.insert("key".into(), "value".into());
let output = log.format_log(X86LogLevel::Warn, "warning message", &extra);
assert!(output.contains("level=warn"));
assert!(output.contains("key=\"value\""));
}
#[test]
fn test_logging_format_text() {
let mut log = X86StructuredLogging::new();
log.format = X86LogFormat::Text;
let output = log.format_log(X86LogLevel::Error, "error!", &HashMap::new());
assert!(output.contains("[ERROR]"));
}
#[test]
fn test_log_level_as_str() {
assert_eq!(X86LogLevel::Debug.as_str(), "DEBUG");
assert_eq!(X86LogLevel::Info.as_str(), "INFO");
assert_eq!(X86LogLevel::Fatal.as_str(), "FATAL");
}
#[test]
fn test_log_level_from_str() {
assert_eq!(X86LogLevel::from_str("INFO"), Some(X86LogLevel::Info));
assert_eq!(X86LogLevel::from_str("warning"), Some(X86LogLevel::Warn));
assert_eq!(X86LogLevel::from_str("CRITICAL"), Some(X86LogLevel::Fatal));
assert_eq!(X86LogLevel::from_str("unknown"), None);
}
#[test]
fn test_metrics_new() {
let metrics = X86MetricsConfig::new("x86_compiler");
assert!(metrics.prometheus_enabled);
assert_eq!(metrics.namespace, "x86_compiler");
}
#[test]
fn test_metrics_generate_counter() {
let metrics = X86MetricsConfig::new("x86_compiler");
let counter = &metrics.counters[0];
let output = metrics.generate_prometheus_metric(counter, 42);
assert!(output.contains("x86_compiler_compilations_total"));
assert!(output.contains("42"));
}
#[test]
fn test_metrics_generate_gauge() {
let metrics = X86MetricsConfig::new("x86_compiler");
let gauge = &metrics.gauges[0];
let output = metrics.generate_prometheus_gauge(gauge, 5.0);
assert!(output.contains("x86_compiler_active_compilations"));
assert!(output.contains("5"));
}
#[test]
fn test_metrics_generate_endpoint() {
let metrics = X86MetricsConfig::new("x86_compiler");
let ep = metrics.generate_metrics_endpoint();
assert!(ep.contains("x86_compiler_compilations_total"));
assert!(ep.contains("x86_compiler_compilation_duration_seconds_bucket"));
}
#[test]
fn test_health_check_new() {
let hc = X86HealthCheck::new(8080);
assert!(hc.enabled);
assert_eq!(hc.port, 8080);
assert_eq!(hc.liveness_path, "/healthz");
assert_eq!(hc.readiness_path, "/readyz");
}
#[test]
fn test_health_check_generate_handler() {
let hc = X86HealthCheck::new(8080);
let cpp = hc.generate_health_handler_cpp();
assert!(cpp.contains("health_check_response"));
assert!(cpp.contains("/healthz"));
assert!(cpp.contains("/readyz"));
}
#[test]
fn test_health_check_format_content_type() {
assert_eq!(X86HealthCheckFormat::Json.content_type(), "application/json");
assert_eq!(X86HealthCheckFormat::Plain.content_type(), "text/plain");
}
#[test]
fn test_observability_new() {
let obs = X86Observability::new("test-service");
assert!(obs.enabled);
assert!(obs.otel.enabled);
assert!(obs.metrics.enabled);
}
#[test]
fn test_observability_full() {
let obs = X86Observability::full("test-service");
assert!(obs.enabled);
}
#[test]
fn test_observability_describe() {
let obs = X86Observability::new("test-service");
let desc = obs.describe();
assert!(desc.contains("X86Observability"));
}
#[test]
fn test_secrets_env_var_default() {
let config = X86SecretsConfig::env_var_default();
assert!(matches!(config.backend, X86SecretsBackend::EnvironmentVariable));
assert_eq!(config.cache_ttl_secs, 300);
}
#[test]
fn test_secrets_vault_default() {
let config = X86SecretsConfig::vault_default("https://vault:8200", "token123");
assert_eq!(config.vault_addr.as_deref(), Some("https://vault:8200"));
assert_eq!(config.vault_token.as_deref(), Some("token123"));
}
#[test]
fn test_secrets_aws_sm() {
let config = X86SecretsConfig::aws_secrets_manager("us-west-2");
assert_eq!(config.aws_region.as_deref(), Some("us-west-2"));
}
#[test]
fn test_secrets_add_secret() {
let mut config = X86SecretsConfig::env_var_default();
config.add_secret("DB_PASSWORD", "prod/db/password");
assert_eq!(config.secret_names.len(), 1);
}
#[test]
fn test_secrets_generate_env_file() {
let mut config = X86SecretsConfig::env_var_default();
config.add_secret("DB_PASSWORD", "prod/db/pass");
let env_file = config.generate_env_file();
assert!(env_file.contains("DB_PASSWORD"));
}
#[test]
fn test_secrets_backend_as_str() {
assert_eq!(X86SecretsBackend::AWSSecretsManager.as_str(), "aws-secrets-manager");
assert_eq!(X86SecretsBackend::HashiCorpVault.as_str(), "vault");
}
#[test]
fn test_secrets_rotation_policy() {
assert_eq!(X86SecretsRotationPolicy::Daily.as_seconds(), 86400);
assert_eq!(X86SecretsRotationPolicy::Weekly.as_seconds(), 604800);
assert_eq!(X86SecretsRotationPolicy::Custom(100).as_seconds(), 100);
}
#[test]
fn test_iam_new() {
let iam = X86IamConfig::new(X86CloudProvider::AWS);
assert_eq!(iam.duration_seconds, 3600);
}
#[test]
fn test_iam_aws_lambda_execution() {
let iam = X86IamConfig::aws_lambda_execution();
assert!(iam.policy_arns.len() >= 2);
assert!(iam.policy_arns[0].contains("AWSLambdaBasicExecutionRole"));
}
#[test]
fn test_iam_aws_ecs_task_execution() {
let iam = X86IamConfig::aws_ecs_task_execution();
assert!(iam.policy_arns.len() >= 2);
}
#[test]
fn test_iam_generate_trust_policy() {
let iam = X86IamConfig::new(X86CloudProvider::AWS);
let policy = iam.generate_trust_policy();
assert!(policy.contains("AssumeRole"));
assert!(policy.contains("ecs-tasks.amazonaws.com"));
}
#[test]
fn test_iam_sts_assume_command() {
let mut iam = X86IamConfig::new(X86CloudProvider::AWS);
iam.role_arn = Some("arn:aws:iam::123456789012:role/test-role".into());
let cmd = iam.sts_assume_command();
assert!(cmd.contains("aws sts assume-role"));
assert!(cmd.contains("test-role"));
}
#[test]
fn test_tls_secure_default() {
let tls = X86TlsConfig::secure_default();
assert!(tls.enabled);
assert!(matches!(tls.min_version, X86TlsVersion::TLSv12));
assert!(matches!(tls.max_version, X86TlsVersion::TLSv13));
assert!(tls.verify_peer);
assert!(tls.verify_hostname);
}
#[test]
fn test_tls_mtls_default() {
let tls = X86TlsConfig::mtls_default("cert.pem", "key.pem", "ca.pem");
assert!(tls.client_cert_required);
assert_eq!(tls.cert_file.as_deref(), Some("cert.pem"));
assert_eq!(tls.ca_file.as_deref(), Some("ca.pem"));
}
#[test]
fn test_tls_generate_openssl_command() {
let mut tls = X86TlsConfig::secure_default();
tls.cert_file = Some("cert.pem".into());
tls.key_file = Some("key.pem".into());
let cmd = tls.generate_openssl_command();
assert!(cmd.contains("openssl s_server"));
assert!(cmd.contains("cert.pem"));
}
#[test]
fn test_tls_to_env_vars() {
let mut tls = X86TlsConfig::secure_default();
tls.cert_file = Some("cert.pem".into());
tls.key_file = Some("key.pem".into());
let vars = tls.to_env_vars();
assert_eq!(vars.len(), 2);
}
#[test]
fn test_tls_version_as_str() {
assert_eq!(X86TlsVersion::TLSv12.as_str(), "TLSv1.2");
assert_eq!(X86TlsVersion::TLSv13.as_str(), "TLSv1.3");
}
#[test]
fn test_signed_url_aws_s3() {
let config = X86SignedUrlConfig::aws_s3_presigned("my-bucket", "dir/file.txt", 3600);
assert_eq!(config.bucket.as_deref(), Some("my-bucket"));
assert_eq!(config.expiration_secs, 3600);
}
#[test]
fn test_signed_url_gcp_storage() {
let config = X86SignedUrlConfig::gcp_storage_signed("my-bucket", "file.txt", 7200);
assert!(matches!(config.url_signer, X86UrlSigner::GCPStorageSignedUrl));
}
#[test]
fn test_signed_url_generate_command() {
let config = X86SignedUrlConfig::aws_s3_presigned("my-bucket", "file.txt", 3600);
let cmd = config.generate_command();
assert!(cmd.contains("aws s3 presign"));
assert!(cmd.contains("my-bucket/file.txt"));
}
#[test]
fn test_signing_algorithm_as_str() {
assert_eq!(X86SigningAlgorithm::HMACSHA256.as_str(), "HMAC-SHA256");
assert_eq!(X86SigningAlgorithm::RSA2048SHA256.as_str(), "RSA2048-SHA256");
}
#[test]
fn test_webhook_verification_new() {
let wv = X86WebhookVerification::new(X86WebhookProvider::GitHub, "my-secret");
assert!(wv.enabled);
assert_eq!(wv.signature_header, "X-Hub-Signature-256");
}
#[test]
fn test_webhook_provider_signature_header() {
assert_eq!(X86WebhookProvider::GitHub.signature_header(), "X-Hub-Signature-256");
assert_eq!(X86WebhookProvider::Stripe.signature_header(), "Stripe-Signature");
assert_eq!(X86WebhookProvider::Slack.signature_header(), "X-Slack-Signature");
}
#[test]
fn test_webhook_provider_timestamp_header() {
assert_eq!(X86WebhookProvider::GitHub.timestamp_header(), Some("X-Request-Timestamp"));
assert_eq!(X86WebhookProvider::AWS.timestamp_header(), None);
}
#[test]
fn test_webhook_generate_verifier() {
let wv = X86WebhookVerification::new(X86WebhookProvider::GitHub, "secret");
let cpp = wv.generate_cpp_verifier();
assert!(cpp.contains("verify_webhook_signature"));
assert!(cpp.contains("HMAC"));
assert!(cpp.contains("EVP_sha256"));
}
#[test]
fn test_cloud_security_new() {
let sec = X86CloudSecurity::new();
assert!(sec.enabled);
assert!(sec.encryption_at_rest);
assert!(sec.encryption_in_transit);
assert!(sec.audit_logging);
}
#[test]
fn test_cloud_security_production() {
let sec = X86CloudSecurity::production();
assert!(sec.tls.enabled);
assert!(sec.compliance_frameworks.len() >= 2);
}
#[test]
fn test_cloud_security_describe() {
let sec = X86CloudSecurity::new();
let desc = sec.describe();
assert!(desc.contains("X86CloudSecurity"));
assert!(desc.contains("TLS:"));
}
#[test]
fn test_compliance_framework_as_str() {
assert_eq!(X86ComplianceFramework::SOC2.as_str(), "SOC2");
assert_eq!(X86ComplianceFramework::HIPAA.as_str(), "HIPAA");
assert_eq!(X86ComplianceFramework::GDPR.as_str(), "GDPR");
}
#[test]
fn test_cors_config_default_permissive() {
let cors = X86CorsConfig::default_permissive();
assert!(cors.allow_origin.contains(&"*".to_string()));
assert!(cors.allow_methods.contains(&"GET".to_string()));
}
#[test]
fn test_cloud_driver_new() {
let driver = X86CloudDriver::new(X86Cloud::default());
assert!(!driver.verbose);
assert!(!driver.dry_run);
}
#[test]
fn test_cloud_driver_add_source() {
let mut driver = X86CloudDriver::new(X86Cloud::default());
driver.add_source("main.cpp");
driver.add_source("util.cpp");
assert_eq!(driver.source_files.len(), 2);
}
#[test]
fn test_cloud_driver_compile_flags() {
let driver = X86CloudDriver::new(X86Cloud::default());
let flags = driver.compile_flags();
assert!(flags.contains(&"-target".to_string()));
assert!(flags.contains(&"x86_64-unknown-linux-gnu".to_string()));
assert!(flags.contains(&"-DCLOUD_X86_ENABLED=1".to_string()));
}
#[test]
fn test_cloud_driver_linkage_flags() {
let driver = X86CloudDriver::new(X86Cloud::default());
let flags = driver.linkage_flags();
assert!(flags.contains(&"-lstdc++".to_string()));
assert!(flags.contains(&"-lpthread".to_string()));
}
#[test]
fn test_cloud_driver_compile() {
let mut driver = X86CloudDriver::new(X86Cloud::default());
driver.add_source("test.cpp");
let result = driver.compile();
assert!(result.success);
assert_eq!(result.files_compiled, 1);
}
#[test]
fn test_cloud_driver_compile_dry_run() {
let mut driver = X86CloudDriver::new(X86Cloud::default());
driver.dry_run = true;
let result = driver.compile();
assert!(result.success);
assert_eq!(result.files_compiled, 0);
}
#[test]
fn test_cloud_driver_describe() {
let driver = X86CloudDriver::new(X86Cloud::default());
let desc = driver.describe();
assert!(desc.contains("X86CloudDriver"));
}
#[test]
fn test_cloud_driver_default() {
let driver = X86CloudDriver::default();
assert!(!driver.verbose);
}
#[test]
fn test_cloud_result_new() {
let result = X86CloudCompileResult::new();
assert!(!result.success);
assert!(result.errors.is_empty());
}
#[test]
fn test_cloud_result_is_clean() {
let result = X86CloudCompileResult {
success: true,
files_compiled: 5,
output: "a.out".into(),
flags_used: vec![],
source_files: vec!["main.cpp".into()],
dockerfile_generated: None,
k8s_manifests_generated: None,
ci_config_generated: None,
tf_config_generated: None,
errors: vec![],
warnings: vec![],
compile_time_ms: 1500,
};
assert!(result.is_clean());
}
#[test]
fn test_cloud_result_summary() {
let result = X86CloudCompileResult::new();
let summary = result.summary();
assert!(summary.contains("success="));
}
#[test]
fn test_cloud_pipeline_new() {
let pipeline = X86CloudPipeline::new(X86Cloud::default());
assert_eq!(pipeline.results.len(), 0);
}
#[test]
fn test_cloud_pipeline_run() {
let mut pipeline = X86CloudPipeline::new(X86Cloud::default());
pipeline.run();
assert_eq!(pipeline.results.len(), 1);
assert!(pipeline.artifacts.count() > 0);
}
#[test]
fn test_cloud_pipeline_generate_all() {
let mut pipeline = X86CloudPipeline::new(X86Cloud::default());
pipeline.run();
let output = pipeline.generate_all();
assert!(output.contains("X86 Cloud Pipeline"));
}
#[test]
fn test_cloud_pipeline_describe() {
let mut pipeline = X86CloudPipeline::new(X86Cloud::default());
pipeline.run();
let desc = pipeline.describe();
assert!(desc.contains("X86CloudPipeline"));
}
#[test]
fn test_mount_type_as_str() {
assert_eq!(X86MountType::Cache.as_str(), "cache");
assert_eq!(X86MountType::Secret.as_str(), "secret");
assert_eq!(X86MountType::SSH.as_str(), "ssh");
}
#[test]
fn test_build_mount_cache() {
let mount = X86BuildMount::cache("/root/.cache");
assert!(matches!(mount.mount_type, X86MountType::Cache));
assert_eq!(mount.target, "/root/.cache");
}
#[test]
fn test_build_mount_secret() {
let mount = X86BuildMount::secret("mysecret", "/run/secrets/mysecret");
assert!(mount.read_only);
}
#[test]
fn test_build_mount_generate() {
let mount = X86BuildMount::cache("/root/.cache");
let r#gen = mount.generate();
assert!(r#gen.contains("--mount=type=cache"));
assert!(r#gen.contains("/root/.cache"));
}
#[test]
fn test_output_type_buildx() {
assert_eq!(X86BuildOutputType::Docker.buildx_type(), "type=docker");
assert_eq!(X86BuildOutputType::OCI.buildx_type(), "type=oci,dest=image.tar");
assert_eq!(X86BuildOutputType::Registry.buildx_type(), "type=image,push=true");
}
#[test]
fn test_lambda_tracing_mode() {
assert_eq!(X86AwsLambdaTracingMode::Active.as_str(), "Active");
assert_eq!(X86AwsLambdaTracingMode::PassThrough.as_str(), "PassThrough");
}
#[test]
fn test_all_k8s_resource_api_versions() {
let kinds = vec![
X86K8sResourceKind::Pod,
X86K8sResourceKind::Deployment,
X86K8sResourceKind::ConfigMap,
X86K8sResourceKind::Service,
X86K8sResourceKind::Ingress,
];
for kind in &kinds {
let api = kind.api_version();
assert!(!api.is_empty());
let k = kind.kind_str();
assert!(!k.is_empty());
}
}
#[test]
fn test_all_gcp_event_types() {
let events = vec![
X86GcpEventType::Storage,
X86GcpEventType::PubSub,
X86GcpEventType::HTTP,
X86GcpEventType::Firestore,
];
for event in &events {
let s = event.event_type_str();
assert!(!s.is_empty());
}
}
#[test]
fn test_all_azure_trigger_types() {
let triggers = vec![
X86AzureTriggerType::Http,
X86AzureTriggerType::Timer,
X86AzureTriggerType::Queue,
X86AzureTriggerType::CosmosDB,
];
for trigger in &triggers {
assert!(!trigger.binding_type().is_empty());
}
}
#[test]
fn test_all_azure_output_bindings() {
let bindings = vec![
X86AzureOutputBinding::Http,
X86AzureOutputBinding::Queue,
X86AzureOutputBinding::Blob,
];
for b in &bindings {
assert!(!b.binding_type().is_empty());
}
}
#[test]
fn test_all_cache_types() {
let cache_types = vec![
X86CacheType::Ccache,
X86CacheType::Sccache,
X86CacheType::BuildDirectory,
X86CacheType::DockerLayerCache,
];
for ct in &cache_types {
assert!(!ct.tool_name().is_empty());
}
}
#[test]
fn test_k8s_restart_policy() {
assert_eq!(X86K8sRestartPolicy::Always.as_str(), "Always");
assert_eq!(X86K8sRestartPolicy::OnFailure.as_str(), "OnFailure");
assert_eq!(X86K8sRestartPolicy::Never.as_str(), "Never");
}
#[test]
fn test_k8s_protocol() {
assert_eq!(X86K8sProtocol::TCP.as_str(), "TCP");
assert_eq!(X86K8sProtocol::UDP.as_str(), "UDP");
assert_eq!(X86K8sProtocol::SCTP.as_str(), "SCTP");
}
#[test]
fn test_k8s_toleration_operator() {
assert_eq!(X86K8sTolerationOperator::Equal.as_str(), "Equal");
assert_eq!(X86K8sTolerationOperator::Exists.as_str(), "Exists");
}
#[test]
fn test_k8s_taint_effect() {
assert_eq!(X86K8sTaintEffect::NoSchedule.as_str(), "NoSchedule");
assert_eq!(X86K8sTaintEffect::NoExecute.as_str(), "NoExecute");
}
#[test]
fn test_k8s_node_selector_operator() {
assert_eq!(X86K8sNodeSelectorOperator::In.as_str(), "In");
assert_eq!(X86K8sNodeSelectorOperator::NotIn.as_str(), "NotIn");
assert_eq!(X86K8sNodeSelectorOperator::Exists.as_str(), "Exists");
}
#[test]
fn test_k8s_seccomp_profile_type() {
assert_eq!(X86K8sSeccompProfileType::RuntimeDefault.as_str(), "RuntimeDefault");
}
}