Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
S
Ship Cat container manager
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
wizards
Ship Cat container manager
Commits
90a71da1
Commit
90a71da1
authored
1 year ago
by
Martin Mareš
Browse files
Options
Downloads
Patches
Plain Diff
Improve handling of paths
Variables ending in _path contain a Path, those ending in _dir are strings.
parent
e0b1ed0f
No related branches found
No related tags found
No related merge requests found
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
etc/shipcat.toml
+3
-0
3 additions, 0 deletions
etc/shipcat.toml
shipcat/config.py
+20
-8
20 additions, 8 deletions
shipcat/config.py
shipcat/main.py
+24
-20
24 additions, 20 deletions
shipcat/main.py
with
47 additions
and
28 deletions
etc/shipcat.toml
+
3
−
0
View file @
90a71da1
...
@@ -3,5 +3,8 @@
...
@@ -3,5 +3,8 @@
# Where to find container configuration files
# Where to find container configuration files
container_config_dir
=
"/etc/shipcat/containers"
container_config_dir
=
"/etc/shipcat/containers"
# Where to find container roots (can be overridden by container's config)
container_root_dir
=
"/aux/containers"
# Overall verbosity
# Overall verbosity
verbosity
=
0
verbosity
=
0
This diff is collapsed.
Click to expand it.
shipcat/config.py
+
20
−
8
View file @
90a71da1
...
@@ -16,7 +16,8 @@ class ConfigError(RuntimeError):
...
@@ -16,7 +16,8 @@ class ConfigError(RuntimeError):
class
GlobalConfig
:
class
GlobalConfig
:
container_config_dir
:
Path
container_config_path
:
Path
container_root_path
:
Path
verbosity
:
int
verbosity
:
int
@classmethod
@classmethod
...
@@ -39,16 +40,19 @@ class GlobalConfig:
...
@@ -39,16 +40,19 @@ class GlobalConfig:
def
parse
(
self
,
walker
:
Walker
)
->
None
:
def
parse
(
self
,
walker
:
Walker
)
->
None
:
with
walker
.
enter_object
()
as
w
:
with
walker
.
enter_object
()
as
w
:
self
.
container_config_dir
=
Path
(
w
[
'
container_config_dir
'
].
as_str
())
self
.
container_config_path
=
Path
(
w
[
'
container_config_dir
'
].
as_str
())
self
.
container_root_path
=
Path
(
w
[
'
container_root_dir
'
].
as_str
())
self
.
verbosity
=
w
[
'
verbosity
'
].
as_int
(
0
)
self
.
verbosity
=
w
[
'
verbosity
'
].
as_int
(
0
)
class
ContainerConfig
:
class
ContainerConfig
:
container
:
str
name
:
str
root_dir
:
str
root_path
:
Path
data_path
:
Path
image
:
str
image
:
str
allowed_users
:
Set
[
int
]
allowed_users
:
Set
[
int
]
allowed_groups
:
Set
[
int
]
allowed_groups
:
Set
[
int
]
global_config
:
GlobalConfig
# Automatically generated
# Automatically generated
pid_file
:
str
pid_file
:
str
...
@@ -59,7 +63,7 @@ class ContainerConfig:
...
@@ -59,7 +63,7 @@ class ContainerConfig:
if
not
re
.
fullmatch
(
r
'
[0-9A-Za-z_-]+
'
,
name
):
if
not
re
.
fullmatch
(
r
'
[0-9A-Za-z_-]+
'
,
name
):
raise
ConfigError
(
f
'
Invalid container name
{
name
}
'
)
raise
ConfigError
(
f
'
Invalid container name
{
name
}
'
)
path
=
global_config
.
container_config_
dir
/
(
name
+
'
.toml
'
)
path
=
global_config
.
container_config_
path
/
(
name
+
'
.toml
'
)
try
:
try
:
with
open
(
path
,
'
rb
'
)
as
f
:
with
open
(
path
,
'
rb
'
)
as
f
:
root
=
tomllib
.
load
(
f
)
root
=
tomllib
.
load
(
f
)
...
@@ -69,7 +73,8 @@ class ContainerConfig:
...
@@ -69,7 +73,8 @@ class ContainerConfig:
raise
ConfigError
(
f
'
Cannot parse container configuration
{
path
}
:
{
e
}
'
)
raise
ConfigError
(
f
'
Cannot parse container configuration
{
path
}
:
{
e
}
'
)
cc
=
ContainerConfig
()
cc
=
ContainerConfig
()
cc
.
container
=
name
cc
.
name
=
name
cc
.
global_config
=
global_config
try
:
try
:
cc
.
parse
(
Walker
(
root
))
cc
.
parse
(
Walker
(
root
))
except
WalkerError
as
e
:
except
WalkerError
as
e
:
...
@@ -79,6 +84,13 @@ class ContainerConfig:
...
@@ -79,6 +84,13 @@ class ContainerConfig:
def
parse
(
self
,
walker
:
Walker
)
->
None
:
def
parse
(
self
,
walker
:
Walker
)
->
None
:
with
walker
.
enter_object
()
as
w
:
with
walker
.
enter_object
()
as
w
:
rd
=
w
[
'
root_dir
'
]
if
rd
.
is_present
():
self
.
root_path
=
Path
(
rd
.
as_str
())
else
:
self
.
root_path
=
self
.
global_config
.
container_root_path
/
self
.
name
self
.
data_path
=
self
.
root_path
/
'
data
'
self
.
root_dir
=
w
[
'
root_dir
'
].
as_str
()
self
.
root_dir
=
w
[
'
root_dir
'
].
as_str
()
self
.
image
=
w
[
'
image
'
].
as_str
()
self
.
image
=
w
[
'
image
'
].
as_str
()
...
@@ -100,5 +112,5 @@ class ContainerConfig:
...
@@ -100,5 +112,5 @@ class ContainerConfig:
wu
.
raise_error
(
f
'
Unknown group
{
name
}
'
)
wu
.
raise_error
(
f
'
Unknown group
{
name
}
'
)
self
.
allowed_groups
.
add
(
grp
.
gr_gid
)
self
.
allowed_groups
.
add
(
grp
.
gr_gid
)
self
.
pid_file
=
f
'
/run/shc/
{
self
.
container
}
.pid
'
self
.
pid_file
=
f
'
/run/shc/
{
self
.
name
}
.pid
'
self
.
user_name
=
self
.
container
self
.
user_name
=
self
.
name
This diff is collapsed.
Click to expand it.
shipcat/main.py
+
24
−
20
View file @
90a71da1
...
@@ -145,7 +145,7 @@ def cmd_init(args: argparse.Namespace) -> None:
...
@@ -145,7 +145,7 @@ def cmd_init(args: argparse.Namespace) -> None:
progress
(
f
'
Using user
{
cc
.
user_name
}
, uid
{
uid
}
, subuids
{
sur
.
first
}
+
{
sur
.
count
}
, subgids
{
sgr
.
first
}
+
{
sgr
.
count
}
\n
'
)
progress
(
f
'
Using user
{
cc
.
user_name
}
, uid
{
uid
}
, subuids
{
sur
.
first
}
+
{
sur
.
count
}
, subgids
{
sgr
.
first
}
+
{
sgr
.
count
}
\n
'
)
root_path
=
Path
(
cc
.
root_
dir
)
root_path
=
cc
.
root_
path
progress
(
f
'
Container directory
{
root_path
}
:
'
)
progress
(
f
'
Container directory
{
root_path
}
:
'
)
if
root_path
.
is_dir
():
if
root_path
.
is_dir
():
progress
(
'
already exists
\n
'
)
progress
(
'
already exists
\n
'
)
...
@@ -154,7 +154,7 @@ def cmd_init(args: argparse.Namespace) -> None:
...
@@ -154,7 +154,7 @@ def cmd_init(args: argparse.Namespace) -> None:
os
.
chown
(
root_path
,
0
,
sgr
.
first
)
os
.
chown
(
root_path
,
0
,
sgr
.
first
)
progress
(
'
created
\n
'
)
progress
(
'
created
\n
'
)
data_path
=
root_path
/
'
data
'
data_path
=
cc
.
data_path
progress
(
f
'
Data directory
{
data_path
}
:
'
)
progress
(
f
'
Data directory
{
data_path
}
:
'
)
if
data_path
.
is_dir
():
if
data_path
.
is_dir
():
progress
(
'
already exists
\n
'
)
progress
(
'
already exists
\n
'
)
...
@@ -173,35 +173,36 @@ def cmd_init(args: argparse.Namespace) -> None:
...
@@ -173,35 +173,36 @@ def cmd_init(args: argparse.Namespace) -> None:
def
service_action
(
cc
:
ContainerConfig
,
action
:
str
)
->
None
:
def
service_action
(
cc
:
ContainerConfig
,
action
:
str
)
->
None
:
run_command
(
run_command
(
[
'
systemctl
'
,
action
,
f
'
shc@
{
cc
.
container
}
.service
'
]
[
'
systemctl
'
,
action
,
f
'
shc@
{
cc
.
name
}
.service
'
]
)
)
def
cmd_create
(
args
:
argparse
.
Namespace
)
->
None
:
def
cmd_create
(
args
:
argparse
.
Namespace
)
->
None
:
name
=
args
.
name
cc
=
setup_container
(
args
,
False
)
cc
=
setup_container
(
args
,
False
)
data_dir
=
Path
(
cc
.
root_dir
)
/
'
data
'
ip
=
socket
.
gethostbyname
(
name
)
run_command
(
run_command
(
[
'
podman
'
,
'
pull
'
,
cc
.
image
]
[
'
podman
'
,
'
pull
'
,
cc
.
image
]
)
)
service_action
(
cc
,
'
stop
'
)
service_action
(
cc
,
'
stop
'
)
create_container
(
cc
)
def
create_container
(
cc
:
ContainerConfig
)
->
None
:
ip
=
socket
.
gethostbyname
(
cc
.
name
)
run_command
(
run_command
(
[
'
podman
'
,
'
rm
'
,
'
-if
'
,
name
]
[
'
podman
'
,
'
rm
'
,
'
-if
'
,
cc
.
name
]
)
)
run_command
(
run_command
(
[
[
'
podman
'
,
'
create
'
,
'
podman
'
,
'
create
'
,
'
--name
'
,
name
,
'
--name
'
,
cc
.
name
,
'
--conmon-pidfile
'
,
cc
.
pid_file
,
'
--conmon-pidfile
'
,
cc
.
pid_file
,
'
--log-driver
'
,
'
journald
'
,
'
--log-driver
'
,
'
journald
'
,
'
--hostname
'
,
name
,
'
--hostname
'
,
cc
.
name
,
'
--volume
'
,
f
'
{
data_
dir
}
:/data
'
,
'
--volume
'
,
f
'
{
cc
.
data_
path
}
:/data
'
,
'
--network
'
,
'
static
'
,
'
--network
'
,
'
static
'
,
'
--ip
'
,
ip
,
'
--ip
'
,
ip
,
'
--subuidname
'
,
cc
.
user_name
,
'
--subuidname
'
,
cc
.
user_name
,
...
@@ -240,7 +241,7 @@ def cmd_shell(args: argparse.Namespace) -> None:
...
@@ -240,7 +241,7 @@ def cmd_shell(args: argparse.Namespace) -> None:
cc
=
setup_container
(
args
,
False
)
cc
=
setup_container
(
args
,
False
)
run_command
(
run_command
(
[
'
podman
'
,
'
exec
'
,
'
-it
'
,
cc
.
container
,
'
/bin/bash
'
]
[
'
podman
'
,
'
exec
'
,
'
-it
'
,
cc
.
name
,
'
/bin/bash
'
]
)
)
...
@@ -252,7 +253,7 @@ def cmd_exec(args: argparse.Namespace) -> None:
...
@@ -252,7 +253,7 @@ def cmd_exec(args: argparse.Namespace) -> None:
cmd
.
append
(
'
--tty
'
)
cmd
.
append
(
'
--tty
'
)
if
args
.
user
is
not
None
:
if
args
.
user
is
not
None
:
cmd
.
extend
([
'
--user
'
,
args
.
user
])
cmd
.
extend
([
'
--user
'
,
args
.
user
])
cmd
.
append
(
cc
.
container
)
cmd
.
append
(
cc
.
name
)
cmd
.
extend
(
args
.
arg
)
cmd
.
extend
(
args
.
arg
)
run_command
(
cmd
)
run_command
(
cmd
)
...
@@ -282,33 +283,36 @@ def cmd_rsync(args: argparse.Namespace) -> None:
...
@@ -282,33 +283,36 @@ def cmd_rsync(args: argparse.Namespace) -> None:
cmd
=
[
'
podman
'
,
'
exec
'
,
'
-i
'
]
cmd
=
[
'
podman
'
,
'
exec
'
,
'
-i
'
]
if
user
is
not
None
:
if
user
is
not
None
:
cmd
.
extend
([
'
--user
'
,
user
])
cmd
.
extend
([
'
--user
'
,
user
])
cmd
.
append
(
cc
.
container
)
cmd
.
append
(
cc
.
name
)
cmd
.
extend
(
rsync
)
cmd
.
extend
(
rsync
)
run_command
(
cmd
)
run_command
(
cmd
)
def
cmd_list
(
args
:
argparse
.
Namespace
)
->
None
:
def
cmd_list
(
args
:
argparse
.
Namespace
)
->
None
:
for
conf
in
Path
(
config
.
container_config_
dir
)
.
iterdir
():
for
conf
in
config
.
container_config_
path
.
iterdir
():
if
conf
.
suffix
==
'
.toml
'
:
if
conf
.
suffix
==
'
.toml
'
:
cc
=
ContainerConfig
.
load
(
config
,
conf
.
stem
)
cc
=
ContainerConfig
.
load
(
config
,
conf
.
stem
)
if
args
.
all
or
check_rights
(
cc
,
args
.
as_user
,
args
.
as_groups
):
if
args
.
all
or
check_rights
(
cc
,
args
.
as_user
,
args
.
as_groups
):
print
(
cc
.
container
)
print
(
cc
.
name
)
def
main_service_start
():
def
main_service_start
():
# Service helper for service start, called by root
# Service helper for service start, called by root
if
len
(
sys
.
argv
)
!=
2
:
if
len
(
sys
.
argv
)
!=
2
:
die
(
"
Expected arguments:
container
"
)
die
(
"
Expected arguments:
name
"
)
config
=
load_config
()
config
=
load_config
()
cc
=
ContainerConfig
.
load
(
config
,
sys
.
argv
[
1
])
cc
=
ContainerConfig
.
load
(
config
,
sys
.
argv
[
1
])
pid_file
=
f
'
/run/shc/
{
cc
.
container
}
.pid
'
# Just to be sure
run_command
([
'
podman
'
,
'
stop
'
,
'
--ignore
'
,
cc
.
name
])
pid_file
=
f
'
/run/shc/
{
cc
.
name
}
.pid
'
Path
(
pid_file
).
unlink
(
missing_ok
=
True
)
Path
(
pid_file
).
unlink
(
missing_ok
=
True
)
run_command
([
'
podman
'
,
'
start
'
,
cc
.
container
])
run_command
([
'
podman
'
,
'
start
'
,
cc
.
name
])
def
main_service_stop
():
def
main_service_stop
():
...
@@ -320,7 +324,7 @@ def main_service_stop():
...
@@ -320,7 +324,7 @@ def main_service_stop():
config
=
load_config
()
config
=
load_config
()
cc
=
ContainerConfig
.
load
(
config
,
sys
.
argv
[
1
])
cc
=
ContainerConfig
.
load
(
config
,
sys
.
argv
[
1
])
run_command
([
'
podman
'
,
'
stop
'
,
'
--ignore
'
,
cc
.
container
])
run_command
([
'
podman
'
,
'
stop
'
,
'
--ignore
'
,
cc
.
name
])
def
parse_int_list
(
s
:
str
)
->
List
[
int
]:
def
parse_int_list
(
s
:
str
)
->
List
[
int
]:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment