breakout tmpl from configgen; stage variations/platform feat
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
device:
|
device:
|
||||||
hostname: xyz1-ex-edge-r201
|
hostname: xyz1-ex-core-r101
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
device:
|
device:
|
||||||
hostname: xyz1-ex-edge-r202
|
hostname: xyz1-ex-core-r102
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
device:
|
device:
|
||||||
hostname: xyz2-ex-edge-r201
|
hostname: xyz2-ex-core-r101
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
device:
|
device:
|
||||||
hostname: xyz2-ex-edge-r202
|
hostname: xyz2-ex-core-r202
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
device:
|
device:
|
||||||
hostname: xyz1-ex-edge-r101
|
hostname: xyz1-ex-edge-r101
|
||||||
|
live: true
|
||||||
|
|||||||
29
demo/tmpl/ex-edge-r/policy-options.tera
Normal file
29
demo/tmpl/ex-edge-r/policy-options.tera
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
policy-options {
|
||||||
|
policy-statement EXPORT-POLICY {
|
||||||
|
term ADVERTISE {
|
||||||
|
from protocol bgp;
|
||||||
|
then {
|
||||||
|
community add LOCAL-REGION;
|
||||||
|
accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policy-statement IMPORT-POLICY {
|
||||||
|
term ACCEPT-ALL {
|
||||||
|
then accept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
policy-statement SHIFTED {
|
||||||
|
term DEPRIORITIZE {
|
||||||
|
from {
|
||||||
|
protocol bgp;
|
||||||
|
}
|
||||||
|
then {
|
||||||
|
community add SHIFTED-OUT;
|
||||||
|
next policy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
community LOCAL-REGION members 64500:200;
|
||||||
|
community SHIFTED-OUT members [ 64500:200 64500:200 64500:200 ];
|
||||||
|
}
|
||||||
@@ -1,3 +1,14 @@
|
|||||||
protocols {
|
protocols {
|
||||||
{{ protocol }};
|
bgp {
|
||||||
|
group UPSTREAM {
|
||||||
|
type external;
|
||||||
|
peer-as 64500;
|
||||||
|
import IMPORT-POLICY;
|
||||||
|
{%- if live %}
|
||||||
|
export EXPORT-POLICY;
|
||||||
|
{%- else %}
|
||||||
|
export [ SHIFTED EXPORT-POLICY ];
|
||||||
|
{%- endif %}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,9 @@ files:
|
|||||||
- system
|
- system
|
||||||
- interfaces
|
- interfaces
|
||||||
- protocols
|
- protocols
|
||||||
|
- policy-options
|
||||||
|
platform: junos
|
||||||
|
variations:
|
||||||
|
- live
|
||||||
|
- shifted
|
||||||
|
- init
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
system {
|
system {
|
||||||
hostname {{ hostname }};
|
/* location "{{ location }}" zone {{ zone }} */
|
||||||
location "{{ location }}";
|
host-name {{ hostname }};
|
||||||
zone {{ zone }};
|
system {
|
||||||
users {
|
login {
|
||||||
{{ username }};
|
{%- if init %}
|
||||||
|
user bootstrap {
|
||||||
|
uid 2000;
|
||||||
|
class super-user;
|
||||||
|
}
|
||||||
|
{%- endif %}
|
||||||
|
user {{ username }} {
|
||||||
|
uid 2001;
|
||||||
|
class super-user;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/main.rs
16
src/main.rs
@@ -1,13 +1,14 @@
|
|||||||
mod cli;
|
mod cli;
|
||||||
mod log;
|
mod log;
|
||||||
mod specs;
|
mod render;
|
||||||
mod tmpls;
|
mod spec;
|
||||||
|
mod tmpl;
|
||||||
|
|
||||||
use log::LogLevel;
|
use log::LogLevel;
|
||||||
|
use render::RenderedConfig;
|
||||||
use std::fs::{self, File, OpenOptions, create_dir_all, write};
|
use std::fs::{self, File, OpenOptions, create_dir_all, write};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use tmpls::RenderedConfig;
|
|
||||||
use yaml_serde;
|
use yaml_serde;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -16,11 +17,14 @@ fn main() {
|
|||||||
|
|
||||||
dbug!(dbg, "{:#?}", &args);
|
dbug!(dbg, "{:#?}", &args);
|
||||||
|
|
||||||
let specifications: Vec<specs::Specification> =
|
let specifications: Vec<spec::Specification> =
|
||||||
specs::compile(&args.devices, &args.env.spec_path, dbg);
|
spec::compile(&args.devices, &args.env.spec_path, dbg);
|
||||||
|
|
||||||
for spec in specifications {
|
for spec in specifications {
|
||||||
let result = RenderedConfig::from_spec(&spec, dbg).ok().unwrap();
|
let result = RenderedConfig::from_spec(&spec, dbg).unwrap_or_else(|e| {
|
||||||
|
eprintln!("{}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
output_rendered_configs(result, &args.env.out_path, dbg)
|
output_rendered_configs(result, &args.env.out_path, dbg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
use crate::specs::Specification;
|
use crate::spec::Specification;
|
||||||
|
use crate::tmpl;
|
||||||
use crate::{LogLevel, info, verb};
|
use crate::{LogLevel, info, verb};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
use yaml_serde;
|
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
|
||||||
struct TemplateConfig {
|
|
||||||
files: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RenderedConfig {
|
pub struct RenderedConfig {
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
@@ -43,19 +38,16 @@ impl RenderedConfig {
|
|||||||
|
|
||||||
let base_dir = std::path::Path::new("./tmpl").join(spec.get_layer());
|
let base_dir = std::path::Path::new("./tmpl").join(spec.get_layer());
|
||||||
|
|
||||||
// Read structure.yaml
|
|
||||||
let structure_path = base_dir.join("structure.yaml");
|
let structure_path = base_dir.join("structure.yaml");
|
||||||
let structure_data = fs::read_to_string(&structure_path)
|
let structure = tmpl::Structure::from_file(&structure_path)
|
||||||
.map_err(|e| format!("Failed to read {}: {}", structure_path.display(), e))?;
|
.map_err(|e| format!("Failed to parse {}: {}", structure_path.display(), e))?;
|
||||||
|
|
||||||
let config_meta: TemplateConfig = yaml_serde::from_str(&structure_data)?;
|
|
||||||
|
|
||||||
let mut tera = Tera::default();
|
let mut tera = Tera::default();
|
||||||
let mut configs = Vec::new();
|
let mut configs = Vec::new();
|
||||||
|
|
||||||
info!(dbg, "Rendering {}", hostname);
|
info!(dbg, "Rendering {}", hostname);
|
||||||
|
|
||||||
let template_data: Vec<(String, String)> = config_meta
|
let template_data: Vec<(String, String)> = structure
|
||||||
.files
|
.files
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|name| {
|
.filter_map(|name| {
|
||||||
@@ -72,7 +64,7 @@ impl RenderedConfig {
|
|||||||
|
|
||||||
tera.add_raw_templates(template_data)?;
|
tera.add_raw_templates(template_data)?;
|
||||||
|
|
||||||
for template_name in &config_meta.files {
|
for template_name in &structure.files {
|
||||||
verb!(dbg, " | {}", &template_name);
|
verb!(dbg, " | {}", &template_name);
|
||||||
if !tera.get_template_names().any(|n| n == template_name) {
|
if !tera.get_template_names().any(|n| n == template_name) {
|
||||||
continue;
|
continue;
|
||||||
19
src/tmpl.rs
Normal file
19
src/tmpl.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use yaml_serde;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Structure {
|
||||||
|
pub files: Vec<String>,
|
||||||
|
#[allow(dead_code)] //todo
|
||||||
|
pub platform: String,
|
||||||
|
#[allow(dead_code)] //todo
|
||||||
|
pub variations: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Structure {
|
||||||
|
pub fn from_file(path: &std::path::Path) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let data =
|
||||||
|
std::fs::read_to_string(path).map_err(|e| format!("{}: {}", path.display(), e))?;
|
||||||
|
Ok(yaml_serde::from_str(&data)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user