llb: add constraints to async llb

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
v0.9
Tonis Tiigi 2021-06-22 21:34:43 -07:00
parent b4935eb79a
commit e0124e192c
8 changed files with 117 additions and 81 deletions

View File

@ -10,7 +10,7 @@ import (
)
type asyncState struct {
f func(context.Context, State) (State, error)
f func(context.Context, State, *Constraints) (State, error)
prev State
target State
set bool
@ -23,7 +23,7 @@ func (as *asyncState) Output() Output {
}
func (as *asyncState) Vertex(ctx context.Context, c *Constraints) Vertex {
err := as.Do(ctx)
err := as.Do(ctx, c)
if err != nil {
return &errVertex{err}
}
@ -38,7 +38,7 @@ func (as *asyncState) Vertex(ctx context.Context, c *Constraints) Vertex {
}
func (as *asyncState) ToInput(ctx context.Context, c *Constraints) (*pb.Input, error) {
err := as.Do(ctx)
err := as.Do(ctx, c)
if err != nil {
return nil, err
}
@ -52,12 +52,12 @@ func (as *asyncState) ToInput(ctx context.Context, c *Constraints) (*pb.Input, e
return nil, nil
}
func (as *asyncState) Do(ctx context.Context) error {
func (as *asyncState) Do(ctx context.Context, c *Constraints) error {
_, err := as.g.Do(ctx, "", func(ctx context.Context) (interface{}, error) {
if as.set {
return as.target, as.err
}
res, err := as.f(ctx, as.prev)
res, err := as.f(ctx, as.prev, c)
if err != nil {
select {
case <-ctx.Done():

View File

@ -14,7 +14,7 @@ func TestAsyncNonBlocking(t *testing.T) {
wait := make(chan struct{})
ran := make(chan struct{})
st := Image("alpine").Dir("/foo").Async(func(ctx context.Context, st State) (State, error) {
st := Image("alpine").Dir("/foo").Async(func(ctx context.Context, st State, c *Constraints) (State, error) {
close(ran)
<-wait // make sure callback doesn't block the chain
return st.Run(Shlex("cmd1")).Dir("sub"), nil

View File

@ -99,14 +99,14 @@ func (e *ExecOp) Validate(ctx context.Context, c *Constraints) error {
if e.isValidated {
return nil
}
args, err := getArgs(e.base)(ctx)
args, err := getArgs(e.base)(ctx, c)
if err != nil {
return err
}
if len(args) == 0 {
return errors.Errorf("arguments are required")
}
cwd, err := getDir(e.base)(ctx)
cwd, err := getDir(e.base)(ctx, c)
if err != nil {
return err
}
@ -136,7 +136,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
return e.mounts[i].target < e.mounts[j].target
})
env, err := getEnv(e.base)(ctx)
env, err := getEnv(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
@ -165,22 +165,22 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
}
}
args, err := getArgs(e.base)(ctx)
args, err := getArgs(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
cwd, err := getDir(e.base)(ctx)
cwd, err := getDir(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
user, err := getUser(e.base)(ctx)
user, err := getUser(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
hostname, err := getHostname(e.base)(ctx)
hostname, err := getHostname(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
@ -192,7 +192,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
User: user,
Hostname: hostname,
}
extraHosts, err := getExtraHosts(e.base)(ctx)
extraHosts, err := getExtraHosts(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
@ -204,12 +204,12 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
meta.ExtraHosts = hosts
}
network, err := getNetwork(e.base)(ctx)
network, err := getNetwork(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
security, err := getSecurity(e.base)(ctx)
security, err := getSecurity(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}
@ -263,7 +263,7 @@ func (e *ExecOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
}
if e.constraints.Platform == nil {
p, err := getPlatform(e.base)(ctx)
p, err := getPlatform(e.base)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}

View File

@ -676,7 +676,7 @@ func (f *FileOp) Marshal(ctx context.Context, c *Constraints) (digest.Digest, []
pfo := &pb.FileOp{}
if f.constraints.Platform == nil {
p, err := getPlatform(*f.action.state)(ctx)
p, err := getPlatform(*f.action.state)(ctx, c)
if err != nil {
return "", nil, nil, nil, err
}

View File

@ -39,8 +39,8 @@ func addEnvf(key, value string, replace bool, v ...interface{}) StateOption {
value = fmt.Sprintf(value, v...)
}
return func(s State) State {
return s.withValue(keyEnv, func(ctx context.Context) (interface{}, error) {
env, err := getEnv(s)(ctx)
return s.withValue(keyEnv, func(ctx context.Context, c *Constraints) (interface{}, error) {
env, err := getEnv(s)(ctx, c)
if err != nil {
return nil, err
}
@ -62,9 +62,9 @@ func dirf(value string, replace bool, v ...interface{}) StateOption {
value = fmt.Sprintf(value, v...)
}
return func(s State) State {
return s.withValue(keyDir, func(ctx context.Context) (interface{}, error) {
return s.withValue(keyDir, func(ctx context.Context, c *Constraints) (interface{}, error) {
if !path.IsAbs(value) {
prev, err := getDir(s)(ctx)
prev, err := getDir(s)(ctx, c)
if err != nil {
return nil, err
}
@ -92,9 +92,9 @@ func Reset(other State) StateOption {
}
}
func getEnv(s State) func(context.Context) (EnvList, error) {
return func(ctx context.Context) (EnvList, error) {
v, err := s.getValue(keyEnv)(ctx)
func getEnv(s State) func(context.Context, *Constraints) (EnvList, error) {
return func(ctx context.Context, c *Constraints) (EnvList, error) {
v, err := s.getValue(keyEnv)(ctx, c)
if err != nil {
return nil, err
}
@ -105,9 +105,9 @@ func getEnv(s State) func(context.Context) (EnvList, error) {
}
}
func getDir(s State) func(context.Context) (string, error) {
return func(ctx context.Context) (string, error) {
v, err := s.getValue(keyDir)(ctx)
func getDir(s State) func(context.Context, *Constraints) (string, error) {
return func(ctx context.Context, c *Constraints) (string, error) {
v, err := s.getValue(keyDir)(ctx, c)
if err != nil {
return "", err
}
@ -118,9 +118,9 @@ func getDir(s State) func(context.Context) (string, error) {
}
}
func getArgs(s State) func(context.Context) ([]string, error) {
return func(ctx context.Context) ([]string, error) {
v, err := s.getValue(keyArgs)(ctx)
func getArgs(s State) func(context.Context, *Constraints) ([]string, error) {
return func(ctx context.Context, c *Constraints) ([]string, error) {
v, err := s.getValue(keyArgs)(ctx, c)
if err != nil {
return nil, err
}
@ -131,9 +131,9 @@ func getArgs(s State) func(context.Context) ([]string, error) {
}
}
func getUser(s State) func(context.Context) (string, error) {
return func(ctx context.Context) (string, error) {
v, err := s.getValue(keyUser)(ctx)
func getUser(s State) func(context.Context, *Constraints) (string, error) {
return func(ctx context.Context, c *Constraints) (string, error) {
v, err := s.getValue(keyUser)(ctx, c)
if err != nil {
return "", err
}
@ -150,9 +150,9 @@ func Hostname(str string) StateOption {
}
}
func getHostname(s State) func(context.Context) (string, error) {
return func(ctx context.Context) (string, error) {
v, err := s.getValue(keyHostname)(ctx)
func getHostname(s State) func(context.Context, *Constraints) (string, error) {
return func(ctx context.Context, c *Constraints) (string, error) {
v, err := s.getValue(keyHostname)(ctx, c)
if err != nil {
return "", err
}
@ -188,9 +188,9 @@ func platform(p specs.Platform) StateOption {
}
}
func getPlatform(s State) func(context.Context) (*specs.Platform, error) {
return func(ctx context.Context) (*specs.Platform, error) {
v, err := s.getValue(keyPlatform)(ctx)
func getPlatform(s State) func(context.Context, *Constraints) (*specs.Platform, error) {
return func(ctx context.Context, c *Constraints) (*specs.Platform, error) {
v, err := s.getValue(keyPlatform)(ctx, c)
if err != nil {
return nil, err
}
@ -204,8 +204,8 @@ func getPlatform(s State) func(context.Context) (*specs.Platform, error) {
func extraHost(host string, ip net.IP) StateOption {
return func(s State) State {
return s.withValue(keyExtraHost, func(ctx context.Context) (interface{}, error) {
v, err := getExtraHosts(s)(ctx)
return s.withValue(keyExtraHost, func(ctx context.Context, c *Constraints) (interface{}, error) {
v, err := getExtraHosts(s)(ctx, c)
if err != nil {
return nil, err
}
@ -214,9 +214,9 @@ func extraHost(host string, ip net.IP) StateOption {
}
}
func getExtraHosts(s State) func(context.Context) ([]HostIP, error) {
return func(ctx context.Context) ([]HostIP, error) {
v, err := s.getValue(keyExtraHost)(ctx)
func getExtraHosts(s State) func(context.Context, *Constraints) ([]HostIP, error) {
return func(ctx context.Context, c *Constraints) ([]HostIP, error) {
v, err := s.getValue(keyExtraHost)(ctx, c)
if err != nil {
return nil, err
}
@ -237,9 +237,9 @@ func Network(v pb.NetMode) StateOption {
return s.WithValue(keyNetwork, v)
}
}
func getNetwork(s State) func(context.Context) (pb.NetMode, error) {
return func(ctx context.Context) (pb.NetMode, error) {
v, err := s.getValue(keyNetwork)(ctx)
func getNetwork(s State) func(context.Context, *Constraints) (pb.NetMode, error) {
return func(ctx context.Context, c *Constraints) (pb.NetMode, error) {
v, err := s.getValue(keyNetwork)(ctx, c)
if err != nil {
return 0, err
}
@ -256,9 +256,9 @@ func Security(v pb.SecurityMode) StateOption {
return s.WithValue(keySecurity, v)
}
}
func getSecurity(s State) func(context.Context) (pb.SecurityMode, error) {
return func(ctx context.Context) (pb.SecurityMode, error) {
v, err := s.getValue(keySecurity)(ctx)
func getSecurity(s State) func(context.Context, *Constraints) (pb.SecurityMode, error) {
return func(ctx context.Context, c *Constraints) (pb.SecurityMode, error) {
v, err := s.getValue(keySecurity)(ctx, c)
if err != nil {
return 0, err
}

View File

@ -121,7 +121,7 @@ func Image(ref string, opts ...ImageOption) State {
src.err = err
} else if info.metaResolver != nil {
if _, ok := r.(reference.Digested); ok || !info.resolveDigest {
return NewState(src.Output()).Async(func(ctx context.Context, st State) (State, error) {
return NewState(src.Output()).Async(func(ctx context.Context, st State, c *Constraints) (State, error) {
_, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{
Platform: info.Constraints.Platform,
ResolveMode: info.resolveMode.String(),
@ -132,7 +132,7 @@ func Image(ref string, opts ...ImageOption) State {
return st.WithImageConfig(dt)
})
}
return Scratch().Async(func(ctx context.Context, _ State) (State, error) {
return Scratch().Async(func(ctx context.Context, _ State, c *Constraints) (State, error) {
dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
Platform: info.Constraints.Platform,
ResolveMode: info.resolveMode.String(),

View File

@ -41,7 +41,7 @@ type State struct {
out Output
prev *State
key interface{}
value func(context.Context) (interface{}, error)
value func(context.Context, *Constraints) (interface{}, error)
opts []ConstraintsOpt
async *asyncState
}
@ -58,12 +58,12 @@ func (s State) ensurePlatform() State {
}
func (s State) WithValue(k, v interface{}) State {
return s.withValue(k, func(context.Context) (interface{}, error) {
return s.withValue(k, func(context.Context, *Constraints) (interface{}, error) {
return v, nil
})
}
func (s State) withValue(k interface{}, v func(context.Context) (interface{}, error)) State {
func (s State) withValue(k interface{}, v func(context.Context, *Constraints) (interface{}, error)) State {
return State{
out: s.Output(),
prev: &s, // doesn't need to be original pointer
@ -72,21 +72,25 @@ func (s State) withValue(k interface{}, v func(context.Context) (interface{}, er
}
}
func (s State) Value(ctx context.Context, k interface{}) (interface{}, error) {
return s.getValue(k)(ctx)
func (s State) Value(ctx context.Context, k interface{}, co ...ConstraintsOpt) (interface{}, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return s.getValue(k)(ctx, c)
}
func (s State) getValue(k interface{}) func(context.Context) (interface{}, error) {
func (s State) getValue(k interface{}) func(context.Context, *Constraints) (interface{}, error) {
if s.key == k {
return s.value
}
if s.async != nil {
return func(ctx context.Context) (interface{}, error) {
err := s.async.Do(ctx)
return func(ctx context.Context, c *Constraints) (interface{}, error) {
err := s.async.Do(ctx, c)
if err != nil {
return nil, err
}
return s.async.target.getValue(k)(ctx)
return s.async.target.getValue(k)(ctx, c)
}
}
if s.prev == nil {
@ -95,7 +99,7 @@ func (s State) getValue(k interface{}) func(context.Context) (interface{}, error
return s.prev.getValue(k)
}
func (s State) Async(f func(context.Context, State) (State, error)) State {
func (s State) Async(f func(context.Context, State, *Constraints) (State, error)) State {
s2 := State{
async: &asyncState{f: f, prev: s},
}
@ -286,8 +290,12 @@ func (s State) Dirf(str string, v ...interface{}) State {
return Dirf(str, v...)(s)
}
func (s State) GetEnv(ctx context.Context, key string) (string, bool, error) {
env, err := getEnv(s)(ctx)
func (s State) GetEnv(ctx context.Context, key string, co ...ConstraintsOpt) (string, bool, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
env, err := getEnv(s)(ctx, c)
if err != nil {
return "", false, err
}
@ -295,20 +303,32 @@ func (s State) GetEnv(ctx context.Context, key string) (string, bool, error) {
return v, ok, nil
}
func (s State) Env(ctx context.Context) ([]string, error) {
env, err := getEnv(s)(ctx)
func (s State) Env(ctx context.Context, co ...ConstraintsOpt) ([]string, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
env, err := getEnv(s)(ctx, c)
if err != nil {
return nil, err
}
return env.ToArray(), nil
}
func (s State) GetDir(ctx context.Context) (string, error) {
return getDir(s)(ctx)
func (s State) GetDir(ctx context.Context, co ...ConstraintsOpt) (string, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getDir(s)(ctx, c)
}
func (s State) GetArgs(ctx context.Context) ([]string, error) {
return getArgs(s)(ctx)
func (s State) GetArgs(ctx context.Context, co ...ConstraintsOpt) ([]string, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getArgs(s)(ctx, c)
}
func (s State) Reset(s2 State) State {
@ -323,31 +343,47 @@ func (s State) Hostname(v string) State {
return Hostname(v)(s)
}
func (s State) GetHostname(ctx context.Context) (string, error) {
return getHostname(s)(ctx)
func (s State) GetHostname(ctx context.Context, co ...ConstraintsOpt) (string, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getHostname(s)(ctx, c)
}
func (s State) Platform(p specs.Platform) State {
return platform(p)(s)
}
func (s State) GetPlatform(ctx context.Context) (*specs.Platform, error) {
return getPlatform(s)(ctx)
func (s State) GetPlatform(ctx context.Context, co ...ConstraintsOpt) (*specs.Platform, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getPlatform(s)(ctx, c)
}
func (s State) Network(n pb.NetMode) State {
return Network(n)(s)
}
func (s State) GetNetwork(ctx context.Context) (pb.NetMode, error) {
return getNetwork(s)(ctx)
func (s State) GetNetwork(ctx context.Context, co ...ConstraintsOpt) (pb.NetMode, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getNetwork(s)(ctx, c)
}
func (s State) Security(n pb.SecurityMode) State {
return Security(n)(s)
}
func (s State) GetSecurity(ctx context.Context) (pb.SecurityMode, error) {
return getSecurity(s)(ctx)
func (s State) GetSecurity(ctx context.Context, co ...ConstraintsOpt) (pb.SecurityMode, error) {
c := &Constraints{}
for _, f := range co {
f.SetConstraintsOption(c)
}
return getSecurity(s)(ctx, c)
}
func (s State) With(so ...StateOption) State {
@ -564,6 +600,6 @@ func Require(filters ...string) ConstraintsOpt {
})
}
func nilValue(context.Context) (interface{}, error) {
func nilValue(context.Context, *Constraints) (interface{}, error) {
return nil, nil
}

View File

@ -89,7 +89,7 @@ func goFromGit(repo, tag string) llb.StateOption {
Dirf("/go/src/%s", repo).
Run(llb.Shlexf("git checkout -q %s", tag)).Root()
return func(s llb.State) llb.State {
return s.With(copyFrom(src, "/go", "/")).Reset(s).Async(func(ctx context.Context, s llb.State) (llb.State, error) {
return s.With(copyFrom(src, "/go", "/")).Reset(s).Async(func(ctx context.Context, s llb.State, c *llb.Constraints) (llb.State, error) {
// TODO: add s.With(s2.DirValue) or s.With(llb.Dir(s2)) or s.Reset(s2, llb.DirMask)?
dir, err := src.GetDir(ctx)
if err != nil {