mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-09 00:16:46 +00:00
Add user support for custom containers
Custom containers in the compose file can have a directory mounted to store state for things like a database. This requires a specific user since influxdb/postgresql and other containers create folders and update permissions on start-up. Tested with influxdb on Ubuntu with userid 1000, which failed before the change. Adds a grace period in the e2e tests. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
This commit is contained in:
parent
9c04b8dfd7
commit
2533c065bf
3
Makefile
3
Makefile
@ -62,4 +62,5 @@ test-e2e:
|
|||||||
sleep 3
|
sleep 3
|
||||||
/usr/local/bin/faas-cli list
|
/usr/local/bin/faas-cli list
|
||||||
sleep 3
|
sleep 3
|
||||||
/usr/local/bin/faas-cli logs figlet --follow=false | grep Forking
|
journalctl -t openfaas-fn:figlet --no-pager
|
||||||
|
/usr/local/bin/faas-cli logs figlet --since 15m --follow=false | grep Forking
|
||||||
|
@ -34,6 +34,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
// Image is the container image registry reference, in an OCI format.
|
||||||
Image string
|
Image string
|
||||||
Env []string
|
Env []string
|
||||||
Name string
|
Name string
|
||||||
@ -42,6 +43,10 @@ type Service struct {
|
|||||||
Args []string
|
Args []string
|
||||||
DependsOn []string
|
DependsOn []string
|
||||||
Ports []ServicePort
|
Ports []ServicePort
|
||||||
|
|
||||||
|
// User in the docker-compose.yaml spec can set as follows:
|
||||||
|
// a user-id, username, userid:groupid or user:group
|
||||||
|
User string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServicePort struct {
|
type ServicePort struct {
|
||||||
@ -161,12 +166,17 @@ func (s *Supervisor) Start(svcs []Service) error {
|
|||||||
Options: []string{"rbind", "ro"},
|
Options: []string{"rbind", "ro"},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if len(svc.User) > 0 {
|
||||||
|
log.Printf("Running %s with user: %q", svc.Name, svc.User)
|
||||||
|
}
|
||||||
|
|
||||||
newContainer, err := s.client.NewContainer(
|
newContainer, err := s.client.NewContainer(
|
||||||
ctx,
|
ctx,
|
||||||
svc.Name,
|
svc.Name,
|
||||||
containerd.WithImage(image),
|
containerd.WithImage(image),
|
||||||
containerd.WithNewSnapshot(svc.Name+"-snapshot", image),
|
containerd.WithNewSnapshot(svc.Name+"-snapshot", image),
|
||||||
containerd.WithNewSpec(oci.WithImageConfig(image),
|
containerd.WithNewSpec(oci.WithImageConfig(image),
|
||||||
|
withUserOrDefault(svc.User),
|
||||||
oci.WithCapabilities(svc.Caps),
|
oci.WithCapabilities(svc.Caps),
|
||||||
oci.WithMounts(mounts),
|
oci.WithMounts(mounts),
|
||||||
withOCIArgs(svc.Args),
|
withOCIArgs(svc.Args),
|
||||||
@ -201,21 +211,21 @@ func (s *Supervisor) Start(svcs []Service) error {
|
|||||||
|
|
||||||
log.Printf("%s has IP: %s\n", newContainer.ID(), ip.String())
|
log.Printf("%s has IP: %s\n", newContainer.ID(), ip.String())
|
||||||
|
|
||||||
hosts, _ := ioutil.ReadFile("hosts")
|
hosts, err := ioutil.ReadFile("hosts")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to read hosts file: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
hosts = []byte(string(hosts) + fmt.Sprintf(`
|
hosts = []byte(string(hosts) + fmt.Sprintf(`
|
||||||
%s %s
|
%s %s
|
||||||
`, ip, svc.Name))
|
`, ip, svc.Name))
|
||||||
writeErr := ioutil.WriteFile("hosts", hosts, workingDirectoryPermission)
|
|
||||||
|
|
||||||
if writeErr != nil {
|
if err := ioutil.WriteFile("hosts", hosts, workingDirectoryPermission); err != nil {
|
||||||
log.Printf("Error writing file %s %s\n", "hosts", writeErr)
|
log.Printf("Error writing file: %s %s\n", "hosts", err)
|
||||||
}
|
}
|
||||||
// os.Chown("hosts", 101, 101)
|
|
||||||
|
|
||||||
_, err = task.Wait(ctx)
|
if _, err := task.Wait(ctx); err != nil {
|
||||||
if err != nil {
|
log.Printf("Task wait error: %s\n", err)
|
||||||
log.Printf("Wait err: %s\n", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +233,7 @@ func (s *Supervisor) Start(svcs []Service) error {
|
|||||||
// log.Println("Exited: ", exitStatusC)
|
// log.Println("Exited: ", exitStatusC)
|
||||||
|
|
||||||
if err = task.Start(ctx); err != nil {
|
if err = task.Start(ctx); err != nil {
|
||||||
log.Printf("Task err: %s\n", err)
|
log.Printf("Task start error: %s\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,6 +263,16 @@ func (s *Supervisor) Remove(svcs []Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withUserOrDefault(userstr string) oci.SpecOpts {
|
||||||
|
if len(userstr) > 0 {
|
||||||
|
return oci.WithUser(userstr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *oci.Spec) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func withOCIArgs(args []string) oci.SpecOpts {
|
func withOCIArgs(args []string) oci.SpecOpts {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
return oci.WithProcessArgs(args...)
|
return oci.WithProcessArgs(args...)
|
||||||
@ -305,6 +325,7 @@ func ParseCompose(config *compose.Config) ([]Service, error) {
|
|||||||
Env: env,
|
Env: env,
|
||||||
Mounts: mounts,
|
Mounts: mounts,
|
||||||
DependsOn: s.DependsOn,
|
DependsOn: s.DependsOn,
|
||||||
|
User: s.User,
|
||||||
Ports: convertPorts(s.Ports),
|
Ports: convertPorts(s.Ports),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user