Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Terraform Gloo VirtualService instead of using kubectl #78

Merged
merged 1 commit into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 63 additions & 25 deletions cli/src/providers/gloo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Castable for ApiProvider {
}
}

let template_name = "yaml_template";
let template_name = "hcl_template";
let mut reg = Box::new(Handlebars::new());
reg.register_template_string(template_name, VIRTUALSERVICE_TEMPLATE)
.unwrap();
Expand All @@ -86,13 +86,13 @@ impl Castable for ApiProvider {
.collect(),
};
let data = to_json(data);
let rendered_yaml = reg
let rendered_hcl = reg
.render(template_name, &data)
.expect("couldn't render yaml template");
.expect("couldn't render hcl template");
let yaml = Artifact {
content_type: ContentType::KubeYaml("kube-yaml"),
content: rendered_yaml,
write_path: "net/kube.yaml".into(),
content_type: ContentType::HCL("HCL"),
content: rendered_hcl,
write_path: "net/plan.tf".into(),
};
Ok(vec![yaml])
}
Expand Down Expand Up @@ -172,23 +172,61 @@ struct RouteData {
}

// TODO add another domain to the list for the user's public domain
static VIRTUALSERVICE_TEMPLATE: &str = r#"apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
name: {{project_name}}
namespace: asml-gloo-{{project_name}}
spec:
virtualHost:
domains:
- '{{project_name}}.asml.local'
{{#if has_routes}}routes:
{{#each routes}}- matchers:
- exact: {{this.path}}
routeAction:
single:
upstream:
name: asml-{{../project_name}}-{{to_service_name}}-asml-{{to_service_name}}-{{to_function_name}}-5543
namespace: asml-gloo-{{../project_name}}
{{/each}}
{{/if}}
// static VIRTUALSERVICE_TEMPLATE: &str = r#"apiVersion: gateway.solo.io/v1
// kind: VirtualService
// metadata:
// name: {{project_name}}
// namespace: asml-gloo-{{project_name}}
// spec:
// virtualHost:
// domains:
// - '{{project_name}}.asml.local'
// {{#if has_routes}}routes:
// {{#each routes}}- matchers:
// - exact: {{this.path}}
// routeAction:
// single:
// upstream:
// name: asml-{{../project_name}}-{{to_service_name}}-asml-{{to_service_name}}-{{to_function_name}}-5543
// namespace: asml-gloo-{{../project_name}}
// {{/each}}
// {{/if}}
// "#;
static VIRTUALSERVICE_TEMPLATE: &str = r#"# Begin Gloo VirtualService
resource kubernetes_manifest gloo_virtualservice {
provider = kubernetes.{{project_name}}
manifest = {
apiVersion = "gateway.solo.io/v1"
kind = "VirtualService"

metadata = {
name = "{{project_name}}"
namespace = "asml-gloo-{{project_name}}"
}

spec = {
virtualHost = {
domains = ["*"]
{{#if has_routes}}routes = [
{{#each routes}}{
matchers = [
{
exact = "{{this.path}}"
}
]
routeAction = {
single = {
upstream = {
name = "asml-{{../project_name}}-{{to_service_name}}-asml-{{to_service_name}}-{{to_function_name}}-5543"
namespace = "asml-gloo-{{../project_name}}"
}
}
}
},
{{/each}}]{{/if}}
}
}
}
}

"#;
75 changes: 55 additions & 20 deletions cli/src/providers/k8s_hyper_alpine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl Provider for KubernetesProvider {
}
}

// TODO kube context name as provider option
impl Castable for KubernetesProvider {
fn cast(&self, ctx: Rc<Context>, _selector: Option<&str>) -> Result<Vec<Artifact>, CastError> {
let service_subprovider = KubernetesService {
Expand All @@ -44,11 +45,7 @@ impl Castable for KubernetesProvider {
// TODO in future we want to support other API Gateway providers -- for now, just Gloo :)
let api_provider = gloo::ApiProvider::new();

let api_artifacts = api_provider.cast(ctx.clone(), None).unwrap();
let api_kube = api_artifacts
.iter()
.find(|a| a.content_type == ContentType::KubeYaml("kube-yaml"))
.unwrap();
let mut api_artifacts = api_provider.cast(ctx.clone(), None).unwrap();
let service_artifacts = ctx
.services
.iter()
Expand All @@ -70,12 +67,18 @@ impl Castable for KubernetesProvider {
.map(|a| a.content.clone())
.reduce(|accum, s| format!("{}{}", &accum, &s))
.unwrap();

let base_tmpl = KubernetesBaseTemplate {
project_name: ctx.project.name.clone(),
};
let hcl = Artifact {
content_type: ContentType::HCL("HCL"),
content: service_hcl,
content: format!("{}{}", base_tmpl.render(), service_hcl),
write_path: "net/plan.tf".to_string(),
};
let mut out = vec![hcl, api_kube.clone()];

let mut out = vec![hcl];
out.append(&mut api_artifacts);
out.append(
&mut service_artifacts
.iter()
Expand Down Expand Up @@ -290,15 +293,6 @@ impl Castable for KubernetesFunction {
}
.render();

// let mut file = std::fs::File::create(format!(
// "./net/services/{}/{}/Dockerfile",
// service.clone(),
// function.name.clone()
// ))
// .expect("could not create runtime Dockerfile");
// file.write_all(dockerfile_content.as_bytes())
// .expect("could not write runtime Dockerfile");

let hcl = Artifact {
content_type: ContentType::HCL("HCL"),
content: hcl_content,
Expand All @@ -324,6 +318,30 @@ impl Castable for KubernetesFunction {
}
}

#[derive(Serialize)]
struct KubernetesBaseTemplate {
project_name: String,
}

impl Template for KubernetesBaseTemplate {
fn render(&self) -> String {
let mut reg = Box::new(Handlebars::new());
reg.register_template_string("hcl_template", Self::tmpl())
.unwrap();
reg.render("hcl_template", &self).unwrap()
}

fn tmpl() -> &'static str {
r#"# AssemblyLift K8S Provider Begin
provider kubernetes {
alias = "{{project_name}}"
config_path = pathexpand("~/.kube/config")
}

"#
}
}

#[derive(Serialize)]
pub struct ServiceTemplate {
pub service_name: String,
Expand Down Expand Up @@ -378,6 +396,19 @@ resource kubernetes_namespace {{service_name}} {
name = "asml-${local.project_name}-{{service_name}}"
}
}

// resource kubernetes_secret {{service_name}} {
// provider = kubernetes.{{service_name}}
// metadata {
// name = "regcred"
// namespace = "asml-${local.project_name}-{{service_name}}"
// }
// data = {
// ".dockerconfigjson" = file("~/.docker/config.json")
// }
// type = "kubernetes.io/dockerconfigjson"
// }

"#
}
}
Expand All @@ -404,8 +435,7 @@ impl Template for FunctionTemplate {
}

fn tmpl() -> &'static str {
r#"
# Begin function `{{function_name}}` (in `{{service_name}}`)
r#"# Begin function `{{function_name}}` (in `{{service_name}}`)

locals {
{{service_name}}_{{function_name}}_image_name = "asml-${local.project_name}-{{service_name}}-{{function_name}}"
Expand Down Expand Up @@ -453,7 +483,7 @@ resource docker_registry_image {{service_name}}_{{function_name}} {

resource kubernetes_deployment {{function_name}} {
provider = kubernetes.{{service_name}}
depends_on = [docker_registry_image.{{service_name}}_{{function_name}}]
depends_on = [docker_registry_image.{{service_name}}_{{function_name}}, kubernetes_namespace.{{service_name}}]
metadata {
name = "{{function_name}}"
namespace = "asml-${local.project_name}-{{service_name}}"
Expand Down Expand Up @@ -482,6 +512,9 @@ resource kubernetes_deployment {{function_name}} {
}

spec {
image_pull_secrets {
name = "regcred"
}
container {
image = docker_registry_image.{{service_name}}_{{function_name}}.name
name = "asml-{{service_name}}-{{function_name}}"
Expand All @@ -504,7 +537,8 @@ resource kubernetes_deployment {{function_name}} {
}

resource kubernetes_service {{service_name}}_{{function_name}} {
provider = kubernetes.{{service_name}}
provider = kubernetes.{{service_name}}
depends_on = [kubernetes_namespace.{{service_name}}]

metadata {
name = "asml-{{service_name}}-{{function_name}}"
Expand All @@ -523,6 +557,7 @@ resource kubernetes_service {{service_name}}_{{function_name}} {
}
}
}

"#
}
}
Expand Down
2 changes: 1 addition & 1 deletion cli/src/providers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod k8s_hyper_alpine;

pub type ProviderMap = StringMap<Mutex<Box<dyn Provider + Send + Sync>>>;

pub static SERVICE_PROVIDERS: Lazy<ProviderMap> = Lazy::new(|| {
pub static PROVIDERS: Lazy<ProviderMap> = Lazy::new(|| {
let mut map = ProviderMap::new();
map.insert(
String::from("aws-lambda"),
Expand Down
4 changes: 2 additions & 2 deletions cli/src/tools/glooctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ impl Tool for GlooCtl {

fn fetch_url(&self) -> &str {
#[cfg(target_os = "linux")]
return "https://github.com/solo-io/gloo/releases/download/v1.12.0-beta7/glooctl-linux-amd64";
return "https://github.com/solo-io/gloo/releases/download/v1.11.13/glooctl-linux-amd64";
#[cfg(target_os = "macos")]
return "https://github.com/solo-io/gloo/releases/download/v1.12.0-beta7/glooctl-darwin-amd64";
return "https://github.com/solo-io/gloo/releases/download/v1.11.13/glooctl-darwin-amd64";
}
}

Expand Down
29 changes: 10 additions & 19 deletions cli/src/transpiler/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use itertools::Itertools;
use serde::Serialize;

use crate::projectfs::Project as ProjectFs;
use crate::providers::SERVICE_PROVIDERS;
use crate::providers::PROVIDERS;
use crate::transpiler::{Artifact, Castable, CastError, ContentType, StringMap, Template, toml};

pub struct Context {
Expand Down Expand Up @@ -182,36 +182,27 @@ impl Castable for Context {
let mut out: Vec<Artifact> = Vec::new();
let providers: Vec<Rc<Provider>> = ctx.services.iter().map(|s| s.provider.clone()).collect();
for p in providers {
let provider = SERVICE_PROVIDERS
let provider = PROVIDERS
.get(&*p.name.clone())
.expect("could not find provider");
provider
.lock()
.unwrap()
.set_options(p.options.clone())
.expect("could not set provider options");

let artifacts = provider
.lock()
.unwrap()
.cast(ctx.clone(), None)
.unwrap();
let hcl = artifacts
.iter()
.find(|a| a.content_type == ContentType::HCL("HCL"))
.unwrap();
let kube_yaml = artifacts
.iter()
.find(|a| a.content_type == ContentType::KubeYaml("kube-yaml"))
.unwrap();
hcl_content.push_str(&hcl.content.clone());
kube_content.push_str(&kube_yaml.content.clone());
out.append(
&mut artifacts
.iter()
.filter(|a| a.content_type == ContentType::Dockerfile("Dockerfile"))
.map(|a| a.clone())
.collect::<Vec<Artifact>>(),
);
for a in artifacts {
match a.content_type {
ContentType::HCL(_) => hcl_content.push_str(&*a.content.clone()),
ContentType::KubeYaml(_) => kube_content.push_str(&*a.content.clone()),
ContentType::Dockerfile(_) => out.push(a.clone()),
}
}
}

let hcl = Artifact {
Expand Down