diff --git a/cmd/dagger/cmd/compute.go b/cmd/dagger/cmd/compute.go index f6624b4f..9f2d32e4 100644 --- a/cmd/dagger/cmd/compute.go +++ b/cmd/dagger/cmd/compute.go @@ -130,6 +130,25 @@ var computeCmd = &cobra.Command{ } } + if f := viper.GetString("input-file"); f != "" { + lg := lg.With().Str("path", f).Logger() + + parts := strings.SplitN(f, "=", 2) + k, v := parts[0], parts[1] + + content, err := os.ReadFile(v) + if err != nil { + lg.Fatal().Err(err).Msg("failed to read file") + } + + if len(content) > 0 { + err = st.SetInput(k, dagger.FileInput(v)) + if err != nil { + lg.Fatal().Err(err).Msg("failed to set input string") + } + } + } + deployment := common.DeploymentUp(ctx, st) v := compiler.NewValue() @@ -150,6 +169,7 @@ var computeCmd = &cobra.Command{ func init() { computeCmd.Flags().StringSlice("input-string", []string{}, "TARGET=STRING") computeCmd.Flags().StringSlice("input-dir", []string{}, "TARGET=PATH") + computeCmd.Flags().String("input-file", "", "TARGET=PATH") computeCmd.Flags().StringSlice("input-git", []string{}, "TARGET=REMOTE#REF") computeCmd.Flags().String("input-json", "", "JSON") computeCmd.Flags().String("input-yaml", "", "YAML") diff --git a/dagger/compiler/value.go b/dagger/compiler/value.go index 7560b4a4..964cce8d 100644 --- a/dagger/compiler/value.go +++ b/dagger/compiler/value.go @@ -108,6 +108,11 @@ func (v *Value) Exists() bool { return v.val.Exists() } +// Proxy function to the underlying cue.Value +func (v *Value) Bytes() ([]byte, error) { + return v.val.Bytes() +} + // Proxy function to the underlying cue.Value func (v *Value) String() (string, error) { return v.val.String() diff --git a/dagger/input.go b/dagger/input.go index c27db8c4..563cb017 100644 --- a/dagger/input.go +++ b/dagger/input.go @@ -3,8 +3,11 @@ package dagger import ( "encoding/json" "fmt" + "io/ioutil" "path/filepath" + "cuelang.org/go/cue" + "dagger.io/go/dagger/compiler" ) @@ -29,6 +32,7 @@ const ( InputTypeText InputType = "text" InputTypeJSON InputType = "json" InputTypeYAML InputType = "yaml" + InputTypeFile InputType = "file" InputTypeEmpty InputType = "" ) @@ -41,6 +45,7 @@ type Input struct { Text *textInput `json:"text,omitempty"` JSON *jsonInput `json:"json,omitempty"` YAML *yamlInput `json:"yaml,omitempty"` + File *fileInput `json:"file,omitempty"` } func (i Input) Compile() (*compiler.Value, error) { @@ -57,6 +62,8 @@ func (i Input) Compile() (*compiler.Value, error) { return i.JSON.Compile() case InputTypeYAML: return i.YAML.Compile() + case InputTypeFile: + return i.File.Compile() case "": return nil, fmt.Errorf("input has not been set") default: @@ -211,3 +218,28 @@ type yamlInput struct { func (i yamlInput) Compile() (*compiler.Value, error) { return compiler.DecodeYAML("", []byte(i.Data)) } + +func FileInput(data string) Input { + return Input{ + Type: InputTypeFile, + File: &fileInput{ + Path: data, + }, + } +} + +type fileInput struct { + Path string `json:"data,omitempty"` +} + +func (i fileInput) Compile() (*compiler.Value, error) { + data, err := ioutil.ReadFile(i.Path) + if err != nil { + return nil, err + } + value := compiler.NewValue() + if err := value.FillPath(cue.MakePath(), data); err != nil { + return nil, err + } + return value, nil +} diff --git a/dagger/pipeline.go b/dagger/pipeline.go index db824eb8..212ffc63 100644 --- a/dagger/pipeline.go +++ b/dagger/pipeline.go @@ -798,7 +798,21 @@ func (p *Pipeline) DockerBuild(ctx context.Context, op *compiler.Value, st llb.S } func (p *Pipeline) WriteFile(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) { - content, err := op.Lookup("content").String() + var content []byte + var err error + + switch kind := op.Lookup("content").Kind(); kind { + case cue.BytesKind: + content, err = op.Lookup("content").Bytes() + case cue.StringKind: + var str string + str, err = op.Lookup("content").String() + if err == nil { + content = []byte(str) + } + default: + err = fmt.Errorf("unhandled data type in WriteFile: %s", kind) + } if err != nil { return st, err } @@ -814,7 +828,7 @@ func (p *Pipeline) WriteFile(ctx context.Context, op *compiler.Value, st llb.Sta } return st.File( - llb.Mkfile(dest, fs.FileMode(mode), []byte(content)), + llb.Mkfile(dest, fs.FileMode(mode), content), llb.WithCustomName(p.vertexNamef("WriteFile %s", dest)), ), nil } diff --git a/stdlib/dagger/dagger.cue b/stdlib/dagger/dagger.cue index b6c141df..8fa8571c 100644 --- a/stdlib/dagger/dagger.cue +++ b/stdlib/dagger/dagger.cue @@ -15,4 +15,6 @@ import ( // Secret value // FIXME: currently aliased as a string to mark secrets // this requires proper support. -#Secret: string +#Secret: { + string | bytes +} diff --git a/stdlib/dagger/op/op.cue b/stdlib/dagger/op/op.cue index d48943a3..6bdcc8a4 100644 --- a/stdlib/dagger/op/op.cue +++ b/stdlib/dagger/op/op.cue @@ -87,7 +87,7 @@ package op #WriteFile: { do: "write-file" - content: string + content: string | bytes dest: string mode: int | *0o644 }