vantage_cmd/models/
mod.rs1use vantage_table::table::Table;
10use vantage_types::EmptyEntity;
11use vantage_vista::{ReferenceKind, Vista};
12
13use crate::cmd::Cmd;
14use crate::vista::spec::CmdVistaSpec;
15
16const IAM_USERS: &str = include_str!("../../vistas/iam.users.yaml");
17const IAM_GROUPS: &str = include_str!("../../vistas/iam.groups.yaml");
18const IAM_ROLES: &str = include_str!("../../vistas/iam.roles.yaml");
19const IAM_POLICIES: &str = include_str!("../../vistas/iam.policies.yaml");
20const IAM_USER_GROUPS: &str = include_str!("../../vistas/iam.user_groups.yaml");
21const IAM_ACCESS_KEYS: &str = include_str!("../../vistas/iam.access_keys.yaml");
22const IAM_USER_POLICIES: &str = include_str!("../../vistas/iam.user_policies.yaml");
23const LOG_GROUPS: &str = include_str!("../../vistas/log.groups.yaml");
24const LOG_STREAMS: &str = include_str!("../../vistas/log.streams.yaml");
25const LOG_EVENTS: &str = include_str!("../../vistas/log.events.yaml");
26const ECS_CLUSTERS: &str = include_str!("../../vistas/ecs.clusters.yaml");
27const ECS_SERVICES: &str = include_str!("../../vistas/ecs.services.yaml");
28const ECS_TASKS: &str = include_str!("../../vistas/ecs.tasks.yaml");
29const ECS_TASK_DEFINITIONS: &str = include_str!("../../vistas/ecs.task_definitions.yaml");
30const S3_BUCKETS: &str = include_str!("../../vistas/s3.buckets.yaml");
31const S3_OBJECTS: &str = include_str!("../../vistas/s3.objects.yaml");
32const LAMBDA_FUNCTIONS: &str = include_str!("../../vistas/lambda.functions.yaml");
33const LAMBDA_ALIASES: &str = include_str!("../../vistas/lambda.aliases.yaml");
34const LAMBDA_VERSIONS: &str = include_str!("../../vistas/lambda.versions.yaml");
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum FactoryMode {
40 List,
41 Single,
42}
43
44#[derive(Clone)]
46pub struct CmdModelFactory {
47 cmd: Cmd,
48}
49
50impl CmdModelFactory {
51 pub fn new(cmd: Cmd) -> Self {
52 Self { cmd }
53 }
54
55 pub fn known_names() -> &'static [&'static str] {
57 &[
58 "iam.user",
59 "iam.users",
60 "iam.group",
61 "iam.groups",
62 "iam.role",
63 "iam.roles",
64 "iam.policy",
65 "iam.policies",
66 "log.group",
67 "log.groups",
68 "ecs.cluster",
69 "ecs.clusters",
70 "ecs.task_definition",
71 "ecs.task_definitions",
72 "s3.bucket",
73 "s3.buckets",
74 "lambda.function",
75 "lambda.functions",
76 ]
77 }
78
79 fn yaml_for(name: &str) -> Option<&'static str> {
83 Some(match name {
84 "iam.user" | "iam.users" => IAM_USERS,
85 "iam.group" | "iam.groups" => IAM_GROUPS,
86 "iam.role" | "iam.roles" => IAM_ROLES,
87 "iam.policy" | "iam.policies" => IAM_POLICIES,
88 "iam.user_groups" => IAM_USER_GROUPS,
91 "iam.access_keys" => IAM_ACCESS_KEYS,
92 "iam.user_policies" => IAM_USER_POLICIES,
93 "log.group" | "log.groups" => LOG_GROUPS,
94 "log.stream" | "log.streams" => LOG_STREAMS,
95 "log.event" | "log.events" => LOG_EVENTS,
96 "ecs.cluster" | "ecs.clusters" => ECS_CLUSTERS,
97 "ecs.service" | "ecs.services" => ECS_SERVICES,
98 "ecs.task" | "ecs.tasks" => ECS_TASKS,
99 "ecs.task_definition" | "ecs.task_definitions" => ECS_TASK_DEFINITIONS,
100 "s3.bucket" | "s3.buckets" => S3_BUCKETS,
101 "s3.object" | "s3.objects" => S3_OBJECTS,
102 "lambda.function" | "lambda.functions" => LAMBDA_FUNCTIONS,
103 "lambda.alias" | "lambda.aliases" => LAMBDA_ALIASES,
104 "lambda.version" | "lambda.versions" => LAMBDA_VERSIONS,
105 _ => return None,
106 })
107 }
108
109 fn is_singular(name: &str) -> bool {
110 matches!(
111 name,
112 "iam.user"
113 | "iam.group"
114 | "iam.role"
115 | "iam.policy"
116 | "log.group"
117 | "log.stream"
118 | "log.event"
119 | "ecs.cluster"
120 | "ecs.service"
121 | "ecs.task"
122 | "ecs.task_definition"
123 | "s3.bucket"
124 | "s3.object"
125 | "lambda.function"
126 | "lambda.alias"
127 | "lambda.version"
128 )
129 }
130
131 pub fn for_name(&self, name: &str) -> Option<(Vista, FactoryMode)> {
137 let table = Self::build_table(self.cmd.clone(), name)?;
138 let vista = self.cmd.vista_factory().from_table(table).ok()?;
139 let mode = if Self::is_singular(name) {
140 FactoryMode::Single
141 } else {
142 FactoryMode::List
143 };
144 Some((vista, mode))
145 }
146
147 fn build_table(cmd: Cmd, name: &str) -> Option<Table<Cmd, EmptyEntity>> {
153 let yaml = Self::yaml_for(name)?;
154 let spec: CmdVistaSpec = serde_yaml_ng::from_str(yaml).ok()?;
155 let mut table = cmd.vista_factory().build_columns_table(&spec).ok()?;
156
157 for (rel_name, ref_spec) in &spec.references {
158 let target = ref_spec.table.clone();
159 let fk = ref_spec
160 .foreign_key
161 .clone()
162 .unwrap_or_else(|| rel_name.clone());
163 let build_target = move |cmd: Cmd| {
166 Self::build_table(cmd, &target)
167 .expect("bundled vista reference target must resolve")
168 };
169 table = match ref_spec.kind {
170 ReferenceKind::HasMany => table.with_many(rel_name, &fk, build_target),
171 ReferenceKind::HasOne => table.with_one(rel_name, &fk, build_target),
172 };
173 }
174
175 Some(table)
176 }
177}