Skip to content

Commit 693a43a

Browse files
authored
Extra repos support (#49)
1 parent b317d11 commit 693a43a

File tree

9 files changed

+237
-135
lines changed

9 files changed

+237
-135
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rooz"
3-
version = "0.68.0"
3+
version = "0.69.0"
44
edition = "2021"
55

66
[dependencies]

src/age_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'a> WorkspaceApi<'a> {
6161
Some(entrypoint.iter().map(String::as_str).collect()),
6262
)
6363
.await?;
64-
self.api.container.remove(&container_id, true).await?;
64+
self.api.container.kill(&container_id).await?;
6565

6666
let identity_file = age::IdentityFile::from_buffer(data.as_bytes())?;
6767
match identity_file.into_identities().first().unwrap() {

src/api/container.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::{
88
use base64::{engine::general_purpose, Engine as _};
99
use bollard::{
1010
container::{
11-
Config, CreateContainerOptions, ListContainersOptions, LogOutput::Console, LogsOptions,
12-
RemoveContainerOptions, StartContainerOptions, StopContainerOptions,
11+
Config, CreateContainerOptions, InspectContainerOptions, KillContainerOptions,
12+
ListContainersOptions, LogOutput::Console, LogsOptions, RemoveContainerOptions,
13+
StartContainerOptions, StopContainerOptions,
1314
},
1415
errors::Error,
1516
models::HostConfig,
@@ -54,6 +55,20 @@ impl<'a> ContainerApi<'a> {
5455
pub async fn remove(&self, container_id: &str, force: bool) -> Result<(), AnyError> {
5556
let force_display = if force { " (force)" } else { "" };
5657

58+
if force {
59+
if let ContainerInspectResponse {
60+
state: Some(state), ..
61+
} = self
62+
.client
63+
.inspect_container(container_id, None::<InspectContainerOptions>)
64+
.await?
65+
{
66+
if let Some(true) = state.running {
67+
self.kill(container_id).await?;
68+
}
69+
}
70+
}
71+
5772
self.client
5873
.remove_container(
5974
&container_id,
@@ -68,6 +83,17 @@ impl<'a> ContainerApi<'a> {
6883
Ok(())
6984
}
7085

86+
pub async fn kill(&self, container_id: &str) -> Result<(), AnyError> {
87+
match self
88+
.client
89+
.kill_container(&container_id, None::<KillContainerOptions<String>>)
90+
.await
91+
{
92+
Ok(_) => Ok(()),
93+
Err(e) => Err(Box::new(e)),
94+
}
95+
}
96+
7197
pub async fn stop(&self, container_id: &str) -> Result<(), AnyError> {
7298
self.client
7399
.stop_container(&container_id, Some(StopContainerOptions { t: 30 }))
@@ -224,10 +250,14 @@ impl<'a> ContainerApi<'a> {
224250
}
225251

226252
pub async fn start(&self, container_id: &str) -> Result<(), AnyError> {
227-
Ok(self
253+
match self
228254
.client
229255
.start_container(&container_id, None::<StartContainerOptions<String>>)
230-
.await?)
256+
.await.map_err(|e|Box::new(e))
257+
{
258+
Ok(_) => Ok(()),
259+
Err(e) => Err(Box::new(e)),
260+
}
231261
}
232262

233263
pub async fn logs_to_stdout(&self, container_name: &str) -> Result<(), AnyError> {

src/api/exec.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ impl<'a> ExecApi<'a> {
3939
mut input,
4040
} = self.client.start_exec(exec_id, None).await?
4141
{
42+
let exec_state = self.client.inspect_exec(&exec_id).await?;
43+
if let Some(exit_code) = exec_state.exit_code {
44+
if exit_code != 0 {
45+
panic!("Exec terminated with exit code: {}.", exit_code);
46+
}
47+
};
4248
let (s, mut r) = oneshot::channel::<bool>();
4349
let handle = spawn(async move {
4450
if interactive {
@@ -61,20 +67,15 @@ impl<'a> ExecApi<'a> {
6167
});
6268

6369
if interactive {
64-
match self
65-
.client
70+
self.client
6671
.resize_exec(
6772
exec_id,
6873
ResizeExecOptions {
6974
height: tty_size.1,
7075
width: tty_size.0,
7176
},
7277
)
73-
.await
74-
{
75-
Ok(_) => (),
76-
Err(err) => println!("Resize exec: {:?}", err),
77-
};
78+
.await?;
7879
};
7980

8081
// set stdout in raw mode so we can do tty stuff
@@ -214,7 +215,7 @@ impl<'a> ExecApi<'a> {
214215

215216
let ensure_user_output = self
216217
.output(
217-
"ensure_user",
218+
"ensure-user",
218219
container_id,
219220
Some(constants::ROOT_UID),
220221
Some(ensure_user_cmd.iter().map(String::as_str).collect()),

src/cmd/new.rs

+76-64
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::{
22
api::WorkspaceApi,
33
cli::{WorkParams, WorkspacePersistence},
44
constants,
5+
git::{CloneSpec, RootRepoCloneResult},
56
labels::{self, Labels},
67
model::{
78
config::{FinalCfg, RoozCfg},
@@ -52,6 +53,13 @@ impl<'a> WorkspaceApi<'a> {
5253
..Default::default()
5354
};
5455

56+
let clone_spec = CloneSpec {
57+
image: constants::DEFAULT_IMAGE.into(),
58+
uid: orig_uid.to_string(),
59+
workspace_key: workspace_key.to_string(),
60+
working_dir: work_dir.to_string(),
61+
};
62+
5563
match &RoozCfg::git_ssh_url(spec, &cli_config) {
5664
None => {
5765
let mut cfg_builder = RoozCfg::default().from_cli_env(spec.clone());
@@ -90,82 +98,86 @@ impl<'a> WorkspaceApi<'a> {
9098
};
9199

92100
let ws = self.create(&work_spec).await?;
101+
if !cfg.extra_repos.is_empty() {
102+
self.git
103+
.clone_extra_repos(clone_spec, cfg.extra_repos)
104+
.await?;
105+
}
93106
return Ok(EnterSpec {
94107
workspace: ws,
95108
git_spec: None,
96109
config: cfg_builder,
97110
});
98111
}
99-
Some(url) => {
100-
match self
101-
.git
102-
.clone_repo(
103-
constants::DEFAULT_IMAGE,
104-
&orig_uid,
105-
url,
106-
&workspace_key,
107-
&work_dir,
108-
)
109-
.await?
110-
{
111-
(repo_config, git_spec) => {
112-
let mut cfg_builder = RoozCfg::default().from_cli_env(spec.clone());
113-
114-
match repo_config {
115-
Some(c) => {
116-
log::debug!("Config file applied.");
117-
cfg_builder = cfg_builder.from_config(c.clone());
118-
}
119-
None => {
120-
log::debug!("No valid config file found in the repository.");
121-
}
122-
}
123112

124-
if let Some(c) = &cli_config {
113+
Some(url) => match self.git.clone_root_repo(&url, &clone_spec).await? {
114+
RootRepoCloneResult {
115+
config: repo_config,
116+
dir: clone_dir,
117+
} => {
118+
let mut cfg_builder = RoozCfg::default().from_cli_env(spec.clone());
119+
120+
match &repo_config {
121+
Some(c) => {
122+
log::debug!("Config file applied.");
125123
cfg_builder = cfg_builder.from_config(c.clone());
126124
}
127-
cfg_builder = cfg_builder.from_cli(spec.clone(), None);
128-
let cfg = FinalCfg::from(&cfg_builder);
129-
130-
self.api.image.ensure(&cfg.image, spec.pull_image).await?;
131-
let network = self
132-
.ensure_sidecars(
133-
&cfg.sidecars,
134-
&labels,
135-
&workspace_key,
136-
force,
137-
spec.pull_image,
138-
&work_dir,
139-
)
125+
None => {
126+
log::debug!("No valid config file found in the repository.");
127+
}
128+
}
129+
130+
if let Some(c) = &cli_config {
131+
cfg_builder = cfg_builder.from_config(c.clone());
132+
}
133+
cfg_builder = cfg_builder.from_cli(spec.clone(), None);
134+
let cfg = FinalCfg::from(&cfg_builder);
135+
136+
self.api.image.ensure(&cfg.image, spec.pull_image).await?;
137+
let network = self
138+
.ensure_sidecars(
139+
&cfg.sidecars,
140+
&labels,
141+
&workspace_key,
142+
force,
143+
spec.pull_image,
144+
&work_dir,
145+
)
146+
.await?;
147+
let work_labels = labels
148+
.clone()
149+
.with_container(Some(constants::DEFAULT_CONTAINER_NAME))
150+
.with_config(cfg.clone());
151+
152+
let work_spec = WorkSpec {
153+
image: &cfg.image,
154+
user: &cfg.user,
155+
caches: Some(cfg.caches),
156+
env_vars: Some(cfg.env),
157+
ports: Some(cfg.ports),
158+
container_working_dir: &clone_dir,
159+
network: network.as_deref(),
160+
labels: (&work_labels).into(),
161+
privileged: cfg.privileged,
162+
..work_spec
163+
};
164+
165+
let ws = self.create(&work_spec).await?;
166+
if !cfg.extra_repos.is_empty() {
167+
self.git
168+
.clone_extra_repos(clone_spec, cfg.extra_repos)
140169
.await?;
141-
let work_labels = labels
142-
.clone()
143-
.with_container(Some(constants::DEFAULT_CONTAINER_NAME))
144-
.with_config(cfg.clone());
145-
146-
let work_spec = WorkSpec {
147-
image: &cfg.image,
148-
user: &cfg.user,
149-
caches: Some(cfg.caches),
150-
env_vars: Some(cfg.env),
151-
ports: Some(cfg.ports),
152-
container_working_dir: &git_spec.dir,
153-
network: network.as_deref(),
154-
labels: (&work_labels).into(),
155-
privileged: cfg.privileged,
156-
..work_spec
157-
};
158-
159-
let ws = self.create(&work_spec).await?;
160-
161-
return Ok(EnterSpec {
162-
workspace: ws,
163-
git_spec: Some(git_spec),
164-
config: cfg_builder,
165-
});
166170
}
171+
return Ok(EnterSpec {
172+
workspace: ws,
173+
git_spec: Some(RootRepoCloneResult {
174+
config: repo_config.clone(),
175+
dir: clone_dir,
176+
}),
177+
config: cfg_builder,
178+
});
167179
}
168-
}
180+
},
169181
};
170182
}
171183

0 commit comments

Comments
 (0)