1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
use crate::commands;
use crate::error::Result;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "lmrc")]
#[command(version, about = "LMRC Stack - Infrastructure project scaffolding tool", long_about = None)]
pub struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// Create a new LMRC Stack project (minimal workspace, add components with 'lmrc add')
New {
/// Project name
name: String,
/// Path where project will be created (defaults to current directory)
#[arg(short, long)]
path: Option<String>,
},
/// Add components to an existing project
Add {
#[command(subcommand)]
component: AddCommands,
},
/// Generate a template configuration file
Config {
/// Output path for config file
#[arg(short, long, default_value = "lmrc.toml")]
output: String,
},
/// Validate an existing configuration file
Validate {
/// Path to configuration file
#[arg(default_value = "lmrc.toml")]
config: String,
},
/// Setup infrastructure and services
Setup {
#[command(subcommand)]
target: SetupCommands,
},
/// Bootstrap a generated project (initialize Git, upload CI/CD variables, push to GitLab)
#[deprecated(note = "Use 'lmrc setup' commands instead")]
Bootstrap,
/// Check development environment for required tools and dependencies
Doctor {
/// Attempt to auto-fix issues (experimental)
#[arg(long)]
fix: bool,
},
/// Local development commands
Dev {
#[command(subcommand)]
action: DevCommands,
},
/// Destroy infrastructure and clean up all resources
Destroy {
/// Skip confirmation prompt
#[arg(long)]
confirm: bool,
/// Project name or config file path
#[arg(short, long)]
project: Option<String>,
},
}
#[derive(Subcommand)]
enum DevCommands {
/// Start local development environment (docker-compose + build)
Start,
/// Stop local development environment
Stop,
/// Show development environment status
Status,
/// View logs from services
Logs {
/// Specific service name (optional)
service: Option<String>,
},
}
#[derive(Subcommand)]
enum AddCommands {
/// Add an application to the project
App {
/// Application name
name: String,
/// Application type (api, basic, gateway, migrator)
#[arg(short = 't', long)]
app_type: Option<String>,
},
/// Add infrastructure pipeline
Pipeline,
/// Add GitLab CI/CD configuration
Ci,
/// Add documentation
Docs,
}
#[derive(Subcommand)]
enum SetupCommands {
/// Initialize git repository
Git,
/// Configure GitLab remote and push code
Remote,
/// Upload CI/CD secrets to GitLab
Secrets,
/// Provision servers on cloud provider
Servers,
/// Configure networking and firewall rules
Network,
/// Install and configure Kubernetes (K3s)
Kubernetes,
/// Setup PostgreSQL database
Database,
/// Setup RabbitMQ message queue
Queue,
/// Configure DNS records (Cloudflare)
Dns,
/// Setup ingress controller (Traefik)
Ingress,
/// Setup complete infrastructure (servers + network + kubernetes + database + queue + dns + ingress)
Infra,
/// Setup everything (git + remote + secrets + infra)
All,
}
impl Cli {
pub async fn execute(self) -> Result<()> {
match self.command {
Commands::New { name, path } => {
commands::new::execute(name, path).await
}
Commands::Add { component } => {
match component {
AddCommands::App { name, app_type } => {
commands::add::app(name, app_type).await
}
AddCommands::Pipeline => commands::add::pipeline().await,
AddCommands::Ci => commands::add::ci().await,
AddCommands::Docs => commands::add::docs().await,
}
}
Commands::Config { output } => commands::config::execute(output).await,
Commands::Validate { config } => commands::validate::execute(config).await,
Commands::Setup { target } => {
match target {
SetupCommands::Git => commands::setup::git().await,
SetupCommands::Remote => commands::setup::remote().await,
SetupCommands::Secrets => commands::setup::secrets().await,
SetupCommands::Servers => commands::setup::servers().await,
SetupCommands::Network => commands::setup::network().await,
SetupCommands::Kubernetes => commands::setup::kubernetes().await,
SetupCommands::Database => commands::setup::database().await,
SetupCommands::Queue => commands::setup::queue().await,
SetupCommands::Dns => commands::setup::dns().await,
SetupCommands::Ingress => commands::setup::ingress().await,
SetupCommands::Infra => commands::setup::infra().await,
SetupCommands::All => commands::setup::all().await,
}
}
#[allow(deprecated)]
Commands::Bootstrap => commands::bootstrap::execute().await,
Commands::Doctor { fix } => commands::doctor::doctor(fix).await,
Commands::Dev { action } => {
match action {
DevCommands::Start => commands::dev::start().await,
DevCommands::Stop => commands::dev::stop().await,
DevCommands::Status => commands::dev::status().await,
DevCommands::Logs { service } => commands::dev::logs(service).await,
}
}
Commands::Destroy { confirm, project } => {
commands::destroy::execute(confirm, project).await
}
}
}
}