check for concreteness in specialized types
Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
parent
6aa4f6b8b3
commit
201ac391b4
@ -60,6 +60,21 @@ var listCmd = &cobra.Command{
|
|||||||
isConcrete := (inp.IsConcreteR() == nil)
|
isConcrete := (inp.IsConcreteR() == nil)
|
||||||
_, hasDefault := inp.Default()
|
_, hasDefault := inp.Default()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case env.Context().Secrets.Contains(inp):
|
||||||
|
if _, err := env.Context().Secrets.FromValue(inp); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case env.Context().FS.Contains(inp):
|
||||||
|
if _, err := env.Context().FS.FromValue(inp); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case env.Context().Services.Contains(inp):
|
||||||
|
if _, err := env.Context().Services.FromValue(inp); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !viper.GetBool("all") {
|
if !viper.GetBool("all") {
|
||||||
// skip input that is not overridable
|
// skip input that is not overridable
|
||||||
if !hasDefault && isConcrete {
|
if !hasDefault && isConcrete {
|
||||||
|
@ -140,7 +140,23 @@ func checkInputs(ctx context.Context, env *environment.Environment) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, i := range inputs {
|
for _, i := range inputs {
|
||||||
if i.IsConcreteR(cue.Optional(true)) != nil {
|
isConcrete := (i.IsConcreteR(cue.Optional(true)) == nil)
|
||||||
|
switch {
|
||||||
|
case env.Context().Secrets.Contains(i):
|
||||||
|
if _, err := env.Context().Secrets.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case env.Context().FS.Contains(i):
|
||||||
|
if _, err := env.Context().FS.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case env.Context().Services.Contains(i):
|
||||||
|
if _, err := env.Context().Services.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isConcrete {
|
||||||
notConcreteInputs = append(notConcreteInputs, i)
|
notConcreteInputs = append(notConcreteInputs, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,7 @@ func (v *Value) IsConcrete() bool {
|
|||||||
// Recursive concreteness check.
|
// Recursive concreteness check.
|
||||||
func (v *Value) IsConcreteR(opts ...cue.Option) error {
|
func (v *Value) IsConcreteR(opts ...cue.Option) error {
|
||||||
o := []cue.Option{
|
o := []cue.Option{
|
||||||
|
cue.All(),
|
||||||
cue.Concrete(true),
|
cue.Concrete(true),
|
||||||
cue.Hidden(true),
|
cue.Hidden(true),
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,6 @@ const (
|
|||||||
StateCompleted = State("completed")
|
StateCompleted = State("completed")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
fsIDPath = cue.MakePath(
|
|
||||||
cue.Hid("_fs", "alpha.dagger.io/dagger"),
|
|
||||||
cue.Str("id"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// An execution pipeline
|
// An execution pipeline
|
||||||
type Pipeline struct {
|
type Pipeline struct {
|
||||||
code *compiler.Value
|
code *compiler.Value
|
||||||
@ -102,90 +95,40 @@ func IsComponent(v *compiler.Value) bool {
|
|||||||
return v.Lookup("#up").Exists()
|
return v.Lookup("#up").Exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
func isFS(v *compiler.Value) bool {
|
func (p *Pipeline) ops() ([]*compiler.Value, error) {
|
||||||
return v.LookupPath(fsIDPath).Exists()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ops(code *compiler.Value) ([]*compiler.Value, error) {
|
|
||||||
ops := []*compiler.Value{}
|
ops := []*compiler.Value{}
|
||||||
|
|
||||||
// dagger.#FS forward compat
|
// dagger.#FS forward compat
|
||||||
// FIXME: remove this
|
// FIXME: remove this
|
||||||
if isFS(code) {
|
if p.pctx.FS.Contains(p.code) {
|
||||||
ops = append(ops, code)
|
ops = append(ops, p.code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. attachment array
|
// 1. attachment array
|
||||||
if IsComponent(code) {
|
if IsComponent(p.code) {
|
||||||
xops, err := code.Lookup("#up").List()
|
xops, err := p.code.Lookup("#up").List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// 'from' has an executable attached
|
// 'from' has an executable attached
|
||||||
ops = append(ops, xops...)
|
ops = append(ops, xops...)
|
||||||
// 2. individual op
|
// 2. individual op
|
||||||
} else if _, err := code.Lookup("do").String(); err == nil {
|
} else if _, err := p.code.Lookup("do").String(); err == nil {
|
||||||
ops = append(ops, code)
|
ops = append(ops, p.code)
|
||||||
// 3. op array
|
// 3. op array
|
||||||
} else if xops, err := code.List(); err == nil {
|
} else if xops, err := p.code.List(); err == nil {
|
||||||
ops = append(ops, xops...)
|
ops = append(ops, xops...)
|
||||||
} else {
|
} else {
|
||||||
// 4. error
|
// 4. error
|
||||||
source, err := code.Source()
|
source, err := p.code.Source()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("not executable: %s (%s)", source, code.Path().String())
|
return nil, fmt.Errorf("not executable: %s (%s)", source, p.code.Path().String())
|
||||||
}
|
}
|
||||||
return ops, nil
|
return ops, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Analyze(fn func(*compiler.Value) error, code *compiler.Value) error {
|
|
||||||
ops, err := ops(code)
|
|
||||||
if err != nil {
|
|
||||||
// Ignore CUE errors when analyzing. This might be because the value is
|
|
||||||
// not concrete since static analysis runs before pipelines are executed.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for _, op := range ops {
|
|
||||||
if err := analyzeOp(fn, op); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func analyzeOp(fn func(*compiler.Value) error, op *compiler.Value) error {
|
|
||||||
// dagger.#FS forward compat
|
|
||||||
// FIXME: remove this
|
|
||||||
if isFS(op) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := fn(op); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
do, err := op.Lookup("do").String()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
switch do {
|
|
||||||
case "load", "copy":
|
|
||||||
return Analyze(fn, op.Lookup("from"))
|
|
||||||
case "exec":
|
|
||||||
fields, err := op.Lookup("mount").Fields()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, mnt := range fields {
|
|
||||||
if from := mnt.Value.Lookup("from"); from.Exists() {
|
|
||||||
return Analyze(fn, from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pipeline) Run(ctx context.Context) error {
|
func (p *Pipeline) Run(ctx context.Context) error {
|
||||||
lg := log.
|
lg := log.
|
||||||
Ctx(ctx).
|
Ctx(ctx).
|
||||||
@ -230,7 +173,7 @@ func (p *Pipeline) Run(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pipeline) run(ctx context.Context) error {
|
func (p *Pipeline) run(ctx context.Context) error {
|
||||||
ops, err := ops(p.code)
|
ops, err := p.ops()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -269,7 +212,7 @@ func (p *Pipeline) run(ctx context.Context) error {
|
|||||||
func (p *Pipeline) doOp(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
func (p *Pipeline) doOp(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||||
// dagger.#FS forward compat
|
// dagger.#FS forward compat
|
||||||
// FIXME: remove this
|
// FIXME: remove this
|
||||||
if isFS(op) {
|
if p.pctx.FS.Contains(op) {
|
||||||
fs, err := p.pctx.FS.FromValue(op)
|
fs, err := p.pctx.FS.FromValue(op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return st, nil
|
return st, nil
|
||||||
|
@ -54,6 +54,10 @@ func (c *fsContext) New(result bkgw.Reference) *FS {
|
|||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fsContext) Contains(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(fsIDPath).Exists()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *fsContext) FromValue(v *compiler.Value) (*FS, error) {
|
func (c *fsContext) FromValue(v *compiler.Value) (*FS, error) {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
@ -55,6 +55,10 @@ func (c *secretContext) New(plaintext string) *Secret {
|
|||||||
return secret
|
return secret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *secretContext) Contains(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(secretIDPath).Exists()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *secretContext) FromValue(v *compiler.Value) (*Secret, error) {
|
func (c *secretContext) FromValue(v *compiler.Value) (*Secret, error) {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
@ -62,6 +62,10 @@ func (c *serviceContext) New(unix, npipe string) *Service {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *serviceContext) Contains(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(serviceIDPath).Exists()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *serviceContext) FromValue(v *compiler.Value) (*Service, error) {
|
func (c *serviceContext) FromValue(v *compiler.Value) (*Service, error) {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
Reference in New Issue
Block a user