mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
this changes the behavior of hot containers: 1) we are no longer populating a hot container with all of the env vars from the first request to start up that hot container. this will only populate the container with any vars that are defined on the app or route. 2) when env vars are changed on the route or app, we will now start up a new hot container that contains those changes. 3) fixes a bug where we could have a collision if the image and path name created one, e.g. `/yo/foo` & `oze/yo:latest` collides with `/yo/fo` and `ooze/yo:latest` (if all other fields are held constant), since we're name spacing with app name in theory it would happen to the same user (though we were relying on a comma delimiter there, not great). now we use NULL bytes which should be hard to get in through a json api ;) i added a sha1 to keep the size of the (soon to be very large) map down, i don't expect collisions but, well, it's a hash function. a small note that we could add a few things to the hot container that will not change on a request basis, such as `app_name`, `format` and `route` but it's a bit pedantic. ultimately, it's confusing imo that we have a different set of vars in the env and in the request itself for hot, which is unavoidable unless we choose to omit setting env vars entirely, but it seems to be what the people want (lmk, people, if otherwise).
108 lines
2.8 KiB
Go
108 lines
2.8 KiB
Go
package runner
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/docker/cli/cli/config/configfile"
|
|
"github.com/fnproject/fn/api/runner/drivers"
|
|
"github.com/fnproject/fn/api/runner/protocol"
|
|
"github.com/fnproject/fn/api/runner/task"
|
|
docker "github.com/fsouza/go-dockerclient"
|
|
)
|
|
|
|
var registries dockerRegistries
|
|
|
|
func init() {
|
|
|
|
// Attempt to fetch it from an environment variable
|
|
regsettings := os.Getenv("DOCKER_AUTH")
|
|
|
|
if regsettings == "" {
|
|
u, err := user.Current()
|
|
if err == nil {
|
|
var config configfile.ConfigFile
|
|
cfile, err := os.Open(filepath.Join(u.HomeDir, ".docker", "config.json"))
|
|
if err != nil {
|
|
return
|
|
}
|
|
err = config.LoadFromReader(cfile)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var regs []dockerRegistry
|
|
for _, auth := range config.AuthConfigs {
|
|
regs = append(regs, dockerRegistry{
|
|
Username: auth.Username,
|
|
Password: auth.Password,
|
|
Name: auth.ServerAddress,
|
|
})
|
|
}
|
|
|
|
registries = dockerRegistries(regs)
|
|
}
|
|
} else {
|
|
// If we have settings, unmarshal them
|
|
json.Unmarshal([]byte(regsettings), ®istries)
|
|
}
|
|
|
|
}
|
|
|
|
type containerTask struct {
|
|
ctx context.Context
|
|
cfg *task.Config
|
|
canRun chan bool
|
|
}
|
|
|
|
func (t *containerTask) Command() string { return "" }
|
|
|
|
func (t *containerTask) EnvVars() map[string]string {
|
|
if protocol.IsStreamable(protocol.Protocol(t.cfg.Format)) {
|
|
return t.cfg.BaseEnv
|
|
}
|
|
return t.cfg.Env
|
|
}
|
|
func (t *containerTask) Input() io.Reader {
|
|
return t.cfg.Stdin
|
|
}
|
|
|
|
func (t *containerTask) Labels() map[string]string {
|
|
return map[string]string{
|
|
"LogName": t.cfg.AppName,
|
|
}
|
|
}
|
|
|
|
func (t *containerTask) Id() string { return t.cfg.ID }
|
|
func (t *containerTask) Route() string { return "" }
|
|
func (t *containerTask) Image() string { return t.cfg.Image }
|
|
func (t *containerTask) Timeout() time.Duration { return t.cfg.Timeout }
|
|
func (t *containerTask) IdleTimeout() time.Duration { return t.cfg.IdleTimeout }
|
|
func (t *containerTask) Logger() (io.Writer, io.Writer) { return t.cfg.Stdout, t.cfg.Stderr }
|
|
func (t *containerTask) Volumes() [][2]string { return [][2]string{} }
|
|
func (t *containerTask) WorkDir() string { return "" }
|
|
func (t *containerTask) Close() {}
|
|
func (t *containerTask) WriteStat(drivers.Stat) {}
|
|
|
|
// Implementing the docker.AuthConfiguration interface. Pulling in
|
|
// the docker repo password from environment variables
|
|
func (t *containerTask) DockerAuth() (docker.AuthConfiguration, error) {
|
|
reg, _, _ := drivers.ParseImage(t.Image())
|
|
authconfig := docker.AuthConfiguration{}
|
|
|
|
if customAuth := registries.Find(reg); customAuth != nil {
|
|
authconfig = docker.AuthConfiguration{
|
|
Password: customAuth.Password,
|
|
ServerAddress: customAuth.Name,
|
|
Username: customAuth.Username,
|
|
}
|
|
}
|
|
|
|
return authconfig, nil
|
|
}
|