Merge pull request #1168 from aluzzardi/dagger-secret-service
Migrate dagger.#Secret and dagger.#Stream to new format
This commit is contained in:
commit
2a946385fa
@ -217,7 +217,7 @@ func (c *Client) logSolveStatus(ctx context.Context, pctx *plancontext.Context,
|
|||||||
secureSprintf := func(format string, a ...interface{}) string {
|
secureSprintf := func(format string, a ...interface{}) string {
|
||||||
s := fmt.Sprintf(format, a...)
|
s := fmt.Sprintf(format, a...)
|
||||||
for _, secret := range secrets {
|
for _, secret := range secrets {
|
||||||
s = strings.ReplaceAll(s, secret.PlainText, "***")
|
s = strings.ReplaceAll(s, secret.PlainText(), "***")
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.dagger.io/dagger/client"
|
"go.dagger.io/dagger/client"
|
||||||
"go.dagger.io/dagger/compiler"
|
"go.dagger.io/dagger/compiler"
|
||||||
|
"go.dagger.io/dagger/plancontext"
|
||||||
"go.dagger.io/dagger/state"
|
"go.dagger.io/dagger/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,12 +86,17 @@ func CurrentEnvironmentState(ctx context.Context, project *state.Project) *state
|
|||||||
|
|
||||||
// FormatValue returns the String representation of the cue value
|
// FormatValue returns the String representation of the cue value
|
||||||
func FormatValue(val *compiler.Value) string {
|
func FormatValue(val *compiler.Value) string {
|
||||||
if val.HasAttr("artifact") {
|
switch {
|
||||||
|
case val.HasAttr("artifact"):
|
||||||
return "dagger.#Artifact"
|
return "dagger.#Artifact"
|
||||||
}
|
case plancontext.IsSecretValue(val):
|
||||||
if val.HasAttr("secret") {
|
|
||||||
return "dagger.#Secret"
|
return "dagger.#Secret"
|
||||||
|
case plancontext.IsFSValue(val):
|
||||||
|
return "dagger.#FS"
|
||||||
|
case plancontext.IsServiceValue(val):
|
||||||
|
return "dagger.#Service"
|
||||||
}
|
}
|
||||||
|
|
||||||
if val.IsConcreteR() != nil {
|
if val.IsConcreteR() != nil {
|
||||||
return val.IncompleteKind().String()
|
return val.IncompleteKind().String()
|
||||||
}
|
}
|
||||||
|
@ -346,7 +346,7 @@ func walkStdlib(ctx context.Context, output, format string) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgName := fmt.Sprintf("alpha.dagger.io/%s", p)
|
pkgName := fmt.Sprintf("%s/%s", stdlib.ModuleName, p)
|
||||||
lg.Info().Str("package", pkgName).Str("format", format).Msg("generating doc")
|
lg.Info().Str("package", pkgName).Str("format", format).Msg("generating doc")
|
||||||
val, err := loadCode(pkgName)
|
val, err := loadCode(pkgName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"go.dagger.io/dagger/cmd/dagger/logger"
|
"go.dagger.io/dagger/cmd/dagger/logger"
|
||||||
"go.dagger.io/dagger/compiler"
|
"go.dagger.io/dagger/compiler"
|
||||||
"go.dagger.io/dagger/environment"
|
"go.dagger.io/dagger/environment"
|
||||||
|
"go.dagger.io/dagger/plancontext"
|
||||||
"go.dagger.io/dagger/solver"
|
"go.dagger.io/dagger/solver"
|
||||||
"go.dagger.io/dagger/state"
|
"go.dagger.io/dagger/state"
|
||||||
|
|
||||||
@ -60,6 +61,21 @@ var listCmd = &cobra.Command{
|
|||||||
isConcrete := (inp.IsConcreteR() == nil)
|
isConcrete := (inp.IsConcreteR() == nil)
|
||||||
_, hasDefault := inp.Default()
|
_, hasDefault := inp.Default()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case plancontext.IsSecretValue(inp):
|
||||||
|
if _, err := env.Context().Secrets.FromValue(inp); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case plancontext.IsFSValue(inp):
|
||||||
|
if _, err := env.Context().FS.FromValue(inp); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case plancontext.IsServiceValue(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 {
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"go.dagger.io/dagger/compiler"
|
"go.dagger.io/dagger/compiler"
|
||||||
"go.dagger.io/dagger/environment"
|
"go.dagger.io/dagger/environment"
|
||||||
"go.dagger.io/dagger/plan"
|
"go.dagger.io/dagger/plan"
|
||||||
|
"go.dagger.io/dagger/plancontext"
|
||||||
"go.dagger.io/dagger/solver"
|
"go.dagger.io/dagger/solver"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
@ -140,7 +141,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 plancontext.IsSecretValue(i):
|
||||||
|
if _, err := env.Context().Secrets.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case plancontext.IsFSValue(i):
|
||||||
|
if _, err := env.Context().FS.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
case plancontext.IsServiceValue(i):
|
||||||
|
if _, err := env.Context().Services.FromValue(i); err != nil {
|
||||||
|
isConcrete = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isConcrete {
|
||||||
notConcreteInputs = append(notConcreteInputs, i)
|
notConcreteInputs = append(notConcreteInputs, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,6 @@ func NewValue() *Value {
|
|||||||
return DefaultCompiler.NewValue()
|
return DefaultCompiler.NewValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewValueWithContent(x interface{}, selectors ...cue.Selector) (*Value, error) {
|
|
||||||
return DefaultCompiler.NewValueWithContent(x, selectors...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME can be refactored away now?
|
// FIXME can be refactored away now?
|
||||||
func Wrap(v cue.Value) *Value {
|
func Wrap(v cue.Value) *Value {
|
||||||
return DefaultCompiler.Wrap(v)
|
return DefaultCompiler.Wrap(v)
|
||||||
@ -84,14 +80,6 @@ func (c *Compiler) NewValue() *Value {
|
|||||||
return empty
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Compiler) NewValueWithContent(x interface{}, selectors ...cue.Selector) (*Value, error) {
|
|
||||||
v := c.NewValue()
|
|
||||||
if err := v.FillPath(cue.MakePath(selectors...), x); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return v, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Compiler) Compile(name string, src string) (*Value, error) {
|
func (c *Compiler) Compile(name string, src string) (*Value, error) {
|
||||||
c.lock()
|
c.lock()
|
||||||
defer c.unlock()
|
defer c.unlock()
|
||||||
|
@ -156,7 +156,11 @@ 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{cue.Concrete(true)}
|
o := []cue.Option{
|
||||||
|
cue.All(),
|
||||||
|
cue.Concrete(true),
|
||||||
|
cue.Hidden(true),
|
||||||
|
}
|
||||||
o = append(o, opts...)
|
o = append(o, opts...)
|
||||||
return v.val.Validate(o...)
|
return v.val.Validate(o...)
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ Create an ArgoCD application
|
|||||||
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*config.server* | `string` |ArgoCD server |
|
|*config.server* | `string` |ArgoCD server |
|
||||||
|*config.project* | `*"default" \| string` |ArgoCD project |
|
|*config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*name* | `string` |App name |
|
|*name* | `string` |App name |
|
||||||
|*repo* | `string` |Repository url (git or helm) |
|
|*repo* | `string` |Repository url (git or helm) |
|
||||||
|*path* | `string` |Folder to deploy |
|
|*path* | `string` |Folder to deploy |
|
||||||
@ -29,7 +29,7 @@ Create an ArgoCD application
|
|||||||
|*image.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*image.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*image.config.server* | `string` |ArgoCD server |
|
|*image.config.server* | `string` |ArgoCD server |
|
||||||
|*image.config.project* | `*"default" \| string` |ArgoCD project |
|
|*image.config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*image.config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*image.config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*namespace* | `*"default" \| string` |Destination namespace |
|
|*namespace* | `*"default" \| string` |Destination namespace |
|
||||||
|*env.APP_NAME* | `string` |- |
|
|*env.APP_NAME* | `string` |- |
|
||||||
|*env.APP_REPO* | `string` |- |
|
|*env.APP_REPO* | `string` |- |
|
||||||
@ -52,7 +52,7 @@ Re-usable CLI component
|
|||||||
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*config.server* | `string` |ArgoCD server |
|
|*config.server* | `string` |ArgoCD server |
|
||||||
|*config.project* | `*"default" \| string` |ArgoCD project |
|
|*config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|
|
||||||
### argocd.#CLI Outputs
|
### argocd.#CLI Outputs
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ ArgoCD configuration
|
|||||||
|*version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*server* | `string` |ArgoCD server |
|
|*server* | `string` |ArgoCD server |
|
||||||
|*project* | `*"default" \| string` |ArgoCD project |
|
|*project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|
|
||||||
### argocd.#Config Outputs
|
### argocd.#Config Outputs
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ Get application's status
|
|||||||
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*config.server* | `string` |ArgoCD server |
|
|*config.server* | `string` |ArgoCD server |
|
||||||
|*config.project* | `*"default" \| string` |ArgoCD project |
|
|*config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*name* | `string` |ArgoCD application |
|
|*name* | `string` |ArgoCD application |
|
||||||
|
|
||||||
### argocd.#Status Outputs
|
### argocd.#Status Outputs
|
||||||
@ -111,18 +111,18 @@ Sync an application to its targer state
|
|||||||
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*config.server* | `string` |ArgoCD server |
|
|*config.server* | `string` |ArgoCD server |
|
||||||
|*config.project* | `*"default" \| string` |ArgoCD project |
|
|*config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*application* | `string` |ArgoCD application |
|
|*application* | `string` |ArgoCD application |
|
||||||
|*wait* | `*false \| bool` |Wait the application to sync correctly |
|
|*wait* | `*false \| bool` |Wait the application to sync correctly |
|
||||||
|*ctr.image.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*ctr.image.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*ctr.image.config.server* | `string` |ArgoCD server |
|
|*ctr.image.config.server* | `string` |ArgoCD server |
|
||||||
|*ctr.image.config.project* | `*"default" \| string` |ArgoCD project |
|
|*ctr.image.config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*ctr.image.config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*ctr.image.config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*ctr.env.APPLICATION* | `string` |- |
|
|*ctr.env.APPLICATION* | `string` |- |
|
||||||
|*status.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
|*status.config.version* | `*"v2.0.5" \| string` |ArgoCD CLI binary version |
|
||||||
|*status.config.server* | `string` |ArgoCD server |
|
|*status.config.server* | `string` |ArgoCD server |
|
||||||
|*status.config.project* | `*"default" \| string` |ArgoCD project |
|
|*status.config.project* | `*"default" \| string` |ArgoCD project |
|
||||||
|*status.config.token* | `dagger.#Secret` |ArgoCD authentication token |
|
|*status.config.token* | `*null \| {}` |ArgoCD authentication token |
|
||||||
|*status.name* | `string` |ArgoCD application |
|
|*status.name* | `string` |ArgoCD application |
|
||||||
|
|
||||||
### argocd.#Sync Outputs
|
### argocd.#Sync Outputs
|
||||||
|
@ -56,6 +56,18 @@ _No input._
|
|||||||
|
|
||||||
_No output._
|
_No output._
|
||||||
|
|
||||||
|
## dagger.#Service
|
||||||
|
|
||||||
|
A reference to a network service endpoint, for example: - A TCP or UDP port - A unix or npipe socket - An HTTPS endpoint
|
||||||
|
|
||||||
|
### dagger.#Service Inputs
|
||||||
|
|
||||||
|
_No input._
|
||||||
|
|
||||||
|
### dagger.#Service Outputs
|
||||||
|
|
||||||
|
_No output._
|
||||||
|
|
||||||
## dagger.#Stream
|
## dagger.#Stream
|
||||||
|
|
||||||
Dagger stream. Can be mounted as a UNIX socket.
|
Dagger stream. Can be mounted as a UNIX socket.
|
||||||
|
@ -19,7 +19,7 @@ Commit & push to git repository
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
| ------------- |:-------------: |:-------------: |
|
| ------------- |:-------------: |:-------------: |
|
||||||
|*repository.remote* | `string` |Repository remote URL |
|
|*repository.remote* | `string` |Repository remote URL |
|
||||||
|*repository.authToken* | `dagger.#Secret` |Authentication token (PAT or password) |
|
|*repository.authToken* | `*null \| {}` |Authentication token (PAT or password) |
|
||||||
|*repository.branch* | `string` |Git branch |
|
|*repository.branch* | `string` |Git branch |
|
||||||
|*name* | `string` |Username |
|
|*name* | `string` |Username |
|
||||||
|*email* | `string` |Email |
|
|*email* | `string` |Email |
|
||||||
@ -69,8 +69,8 @@ A git repository
|
|||||||
|*remote* | `string` |Git remote link |
|
|*remote* | `string` |Git remote link |
|
||||||
|*ref* | `string` |Git ref: can be a commit, tag or branch. Example: "main" |
|
|*ref* | `string` |Git ref: can be a commit, tag or branch. Example: "main" |
|
||||||
|*subdir* | `*null \| string` |(optional) Subdirectory |
|
|*subdir* | `*null \| string` |(optional) Subdirectory |
|
||||||
|*authToken* | `dagger.#Secret` |(optional) Add Personal Access Token |
|
|*authToken* | `*null \| {}` |(optional) Add Personal Access Token |
|
||||||
|*authHeader* | `dagger.#Secret` |(optional) Add OAuth Token |
|
|*authHeader* | `*null \| {}` |(optional) Add OAuth Token |
|
||||||
|
|
||||||
### git.#Repository Outputs
|
### git.#Repository Outputs
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ Apply Kubernetes resources
|
|||||||
|*url* | `*null \| string` |Kubernetes manifest url to deploy remote configuration |
|
|*url* | `*null \| string` |Kubernetes manifest url to deploy remote configuration |
|
||||||
|*namespace* | `*"default" \| string` |Kubernetes Namespace to deploy to |
|
|*namespace* | `*"default" \| string` |Kubernetes Namespace to deploy to |
|
||||||
|*version* | `*"v1.19.9" \| string` |Version of kubectl client |
|
|*version* | `*"v1.19.9" \| string` |Version of kubectl client |
|
||||||
|*kubeconfig* | `dagger.#Secret` |Kube config file |
|
|*kubeconfig* | `(string\|struct)` |Kube config file |
|
||||||
|
|
||||||
### kubernetes.#Resources Outputs
|
### kubernetes.#Resources Outputs
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ Install a Helm chart
|
|||||||
|*timeout* | `*"5m" \| string` |time to wait for any individual Kubernetes operation (like Jobs for hooks) |
|
|*timeout* | `*"5m" \| string` |time to wait for any individual Kubernetes operation (like Jobs for hooks) |
|
||||||
|*wait* | `*true \| bool` |if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as timeout |
|
|*wait* | `*true \| bool` |if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment, StatefulSet, or ReplicaSet are in a ready state before marking the release as successful. It will wait for as long as timeout |
|
||||||
|*atomic* | `*true \| bool` |if set, installation process purges chart on fail. The wait option will be set automatically if atomic is used |
|
|*atomic* | `*true \| bool` |if set, installation process purges chart on fail. The wait option will be set automatically if atomic is used |
|
||||||
|*kubeconfig* | `dagger.#Secret` |Kube config file |
|
|*kubeconfig* | `(string\|struct)` |Kube config file |
|
||||||
|*version* | `*"3.5.2" \| string` |Helm version |
|
|*version* | `*"3.5.2" \| string` |Helm version |
|
||||||
|*kubectlVersion* | `*"v1.19.9" \| string` |Kubectl version |
|
|*kubectlVersion* | `*"v1.19.9" \| string` |Kubectl version |
|
||||||
|
|
||||||
|
@ -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 plancontext.IsFSValue(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,17 +212,12 @@ 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 plancontext.IsFSValue(op) {
|
||||||
id, err := op.LookupPath(fsIDPath).String()
|
fs, err := p.pctx.FS.FromValue(op)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return st, err
|
return st, nil
|
||||||
}
|
}
|
||||||
|
return fs.Result().ToState()
|
||||||
fs := p.pctx.FS.Get(plancontext.ContextKey(id))
|
|
||||||
if fs == nil {
|
|
||||||
return st, fmt.Errorf("fs %q not found", id)
|
|
||||||
}
|
|
||||||
return fs.Result.ToState()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do, err := op.Lookup("do").String()
|
do, err := op.Lookup("do").String()
|
||||||
@ -595,30 +533,26 @@ func (p *Pipeline) mount(ctx context.Context, dest string, mnt *compiler.Value)
|
|||||||
|
|
||||||
// eg. mount: "/foo": secret: mysecret
|
// eg. mount: "/foo": secret: mysecret
|
||||||
if secret := mnt.Lookup("secret"); secret.Exists() {
|
if secret := mnt.Lookup("secret"); secret.Exists() {
|
||||||
id, err := getSecretID(secret)
|
s, err := p.pctx.Secrets.FromValue(secret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return llb.AddSecret(dest,
|
return llb.AddSecret(dest,
|
||||||
llb.SecretID(id),
|
llb.SecretID(s.ID()),
|
||||||
llb.SecretFileOpt(0, 0, 0400), // uid, gid, mask)
|
llb.SecretFileOpt(0, 0, 0400), // uid, gid, mask)
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// eg. mount: "/var/run/docker.sock": stream: mystream
|
// eg. mount: "/var/run/docker.sock": stream: mystream
|
||||||
if stream := mnt.Lookup("stream"); stream.Exists() {
|
if stream := mnt.Lookup("stream"); stream.Exists() {
|
||||||
if !stream.HasAttr("stream") {
|
s, err := p.pctx.Services.FromValue(stream)
|
||||||
return nil, fmt.Errorf("invalid stream %q: not a stream", stream.Path().String())
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := stream.Lookup("id").String()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("invalid stream %q: %w", stream.Path().String(), err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return llb.AddSSHSocket(
|
return llb.AddSSHSocket(
|
||||||
llb.SSHID(id),
|
llb.SSHID(s.ID()),
|
||||||
llb.SSHSocketTarget(dest),
|
llb.SSHSocketTarget(dest),
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
@ -761,15 +695,11 @@ func parseStringOrSecret(pctx *plancontext.Context, v *compiler.Value) (string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, it's a secret
|
// If we get here, it's a secret
|
||||||
id, err := getSecretID(v)
|
secret, err := pctx.Secrets.FromValue(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
secret := pctx.Secrets.Get(plancontext.ContextKey(id))
|
return secret.PlainText(), nil
|
||||||
if secret == nil {
|
|
||||||
return "", fmt.Errorf("secret %s not found", id)
|
|
||||||
}
|
|
||||||
return secret.PlainText, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pipeline) Load(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
func (p *Pipeline) Load(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||||
@ -973,21 +903,6 @@ func (p *Pipeline) SaveImage(ctx context.Context, op *compiler.Value, st llb.Sta
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSecretID(secretField *compiler.Value) (string, error) {
|
|
||||||
if !secretField.HasAttr("secret") {
|
|
||||||
return "", fmt.Errorf("invalid secret %q: not a secret", secretField.Path().String())
|
|
||||||
}
|
|
||||||
idValue := secretField.Lookup("id")
|
|
||||||
if !idValue.Exists() {
|
|
||||||
return "", fmt.Errorf("invalid secret %q: no id field", secretField.Path().String())
|
|
||||||
}
|
|
||||||
id, err := idValue.String()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("invalid secret id: %w", err)
|
|
||||||
}
|
|
||||||
return id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pipeline) FetchGit(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
func (p *Pipeline) FetchGit(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||||
remote, err := op.Lookup("remote").String()
|
remote, err := op.Lookup("remote").String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1017,18 +932,18 @@ func (p *Pipeline) FetchGit(ctx context.Context, op *compiler.Value, st llb.Stat
|
|||||||
}
|
}
|
||||||
// Secret
|
// Secret
|
||||||
if authToken := op.Lookup("authToken"); authToken.Exists() {
|
if authToken := op.Lookup("authToken"); authToken.Exists() {
|
||||||
id, err := getSecretID(authToken)
|
authTokenSecret, err := p.pctx.Secrets.FromValue(authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return st, err
|
return st, err
|
||||||
}
|
}
|
||||||
gitOpts = append(gitOpts, llb.AuthTokenSecret(id))
|
gitOpts = append(gitOpts, llb.AuthTokenSecret(authTokenSecret.ID()))
|
||||||
}
|
}
|
||||||
if authHeader := op.Lookup("authHeader"); authHeader.Exists() {
|
if authHeader := op.Lookup("authHeader"); authHeader.Exists() {
|
||||||
id, err := getSecretID(authHeader)
|
authHeaderSecret, err := p.pctx.Secrets.FromValue(authHeader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return st, err
|
return st, err
|
||||||
}
|
}
|
||||||
gitOpts = append(gitOpts, llb.AuthHeaderSecret(id))
|
gitOpts = append(gitOpts, llb.AuthHeaderSecret(authHeaderSecret.ID()))
|
||||||
}
|
}
|
||||||
|
|
||||||
gitOpts = append(gitOpts, llb.WithCustomName(p.vertexNamef("FetchGit %s@%s", remoteRedacted, ref)))
|
gitOpts = append(gitOpts, llb.WithCustomName(p.vertexNamef("FetchGit %s@%s", remoteRedacted, ref)))
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gofrs/flock"
|
"github.com/gofrs/flock"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"go.dagger.io/dagger/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -15,7 +16,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func isUniverse(repoName string) bool {
|
func isUniverse(repoName string) bool {
|
||||||
return strings.HasPrefix(strings.ToLower(repoName), "alpha.dagger.io")
|
return strings.HasPrefix(strings.ToLower(repoName), stdlib.ModuleName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Install(ctx context.Context, workspace, repoName, versionConstraint string) (*Require, error) {
|
func Install(ctx context.Context, workspace, repoName, versionConstraint string) (*Require, error) {
|
||||||
|
@ -7,6 +7,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"go.dagger.io/dagger/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Require struct {
|
type Require struct {
|
||||||
@ -25,7 +27,7 @@ func newRequire(repoName, versionConstraint string) (*Require, error) {
|
|||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(repoName, "github.com"):
|
case strings.HasPrefix(repoName, "github.com"):
|
||||||
return parseGithubRepoName(repoName, versionConstraint)
|
return parseGithubRepoName(repoName, versionConstraint)
|
||||||
case strings.HasPrefix(repoName, "alpha.dagger.io"):
|
case strings.HasPrefix(repoName, stdlib.ModuleName):
|
||||||
return parseDaggerRepoName(repoName, versionConstraint)
|
return parseDaggerRepoName(repoName, versionConstraint)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("repo name does not match suported providers")
|
return nil, fmt.Errorf("repo name does not match suported providers")
|
||||||
@ -52,7 +54,7 @@ func parseGithubRepoName(repoName, versionConstraint string) (*Require, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var daggerRepoNameRegex = regexp.MustCompile(`alpha.dagger.io([a-zA-Z0-9/_.-]*)@?([0-9a-zA-Z.-]*)`)
|
var daggerRepoNameRegex = regexp.MustCompile(stdlib.ModuleName + `([a-zA-Z0-9/_.-]*)@?([0-9a-zA-Z.-]*)`)
|
||||||
|
|
||||||
func parseDaggerRepoName(repoName, versionConstraint string) (*Require, error) {
|
func parseDaggerRepoName(repoName, versionConstraint string) (*Require, error) {
|
||||||
repoMatches := daggerRepoNameRegex.FindStringSubmatch(repoName)
|
repoMatches := daggerRepoNameRegex.FindStringSubmatch(repoName)
|
||||||
@ -62,7 +64,7 @@ func parseDaggerRepoName(repoName, versionConstraint string) (*Require, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Require{
|
return &Require{
|
||||||
repo: "alpha.dagger.io",
|
repo: stdlib.ModuleName,
|
||||||
path: repoMatches[1],
|
path: repoMatches[1],
|
||||||
version: repoMatches[2],
|
version: repoMatches[2],
|
||||||
versionConstraint: versionConstraint,
|
versionConstraint: versionConstraint,
|
||||||
|
@ -67,10 +67,7 @@ func (p *Plan) registerLocalDirs() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
p.context.LocalDirs.Add(dir)
|
||||||
p.context.LocalDirs.Register(&plancontext.LocalDir{
|
|
||||||
Path: dir,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -68,13 +68,10 @@ func (c importTask) Run(ctx context.Context, pctx *plancontext.Context, s solver
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id := pctx.FS.Register(&plancontext.FS{
|
fs := pctx.FS.New(result)
|
||||||
Result: result,
|
out := compiler.NewValue()
|
||||||
})
|
if err := out.FillPath(cue.ParsePath("fs"), fs.MarshalCUE()); err != nil {
|
||||||
|
return nil, err
|
||||||
return compiler.NewValueWithContent(id,
|
}
|
||||||
cue.Str("fs"),
|
return out, nil
|
||||||
cue.Hid("_fs", "alpha.dagger.io/dagger"),
|
|
||||||
cue.Str("id"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,10 @@ func (c secretEnvTask) Run(ctx context.Context, pctx *plancontext.Context, _ sol
|
|||||||
if env == "" {
|
if env == "" {
|
||||||
return nil, fmt.Errorf("environment variable %q not set", secretEnv.Envvar)
|
return nil, fmt.Errorf("environment variable %q not set", secretEnv.Envvar)
|
||||||
}
|
}
|
||||||
id := pctx.Secrets.Register(&plancontext.Secret{
|
secret := pctx.Secrets.New(env)
|
||||||
PlainText: env,
|
out := compiler.NewValue()
|
||||||
})
|
if err := out.FillPath(cue.ParsePath("contents"), secret.MarshalCUE()); err != nil {
|
||||||
|
return nil, err
|
||||||
return compiler.NewValueWithContent(id,
|
}
|
||||||
cue.Str("contents"),
|
return out, nil
|
||||||
cue.Str("id"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -31,16 +31,15 @@ func (c secretFileTask) Run(ctx context.Context, pctx *plancontext.Context, _ so
|
|||||||
|
|
||||||
lg.Debug().Str("path", secretFile.Path).Msg("loading secret")
|
lg.Debug().Str("path", secretFile.Path).Msg("loading secret")
|
||||||
|
|
||||||
data, err := os.ReadFile(secretFile.Path)
|
plaintext, err := os.ReadFile(secretFile.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
id := pctx.Secrets.Register(&plancontext.Secret{
|
|
||||||
PlainText: string(data),
|
|
||||||
})
|
|
||||||
|
|
||||||
return compiler.NewValueWithContent(id,
|
secret := pctx.Secrets.New(string(plaintext))
|
||||||
cue.Str("contents"),
|
out := compiler.NewValue()
|
||||||
cue.Str("id"),
|
if err := out.FillPath(cue.ParsePath("contents"), secret.MarshalCUE()); err != nil {
|
||||||
)
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,10 @@ package plancontext
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContextKey string
|
|
||||||
|
|
||||||
// Context holds the execution context for a plan.
|
// Context holds the execution context for a plan.
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// ctx := plancontext.New()
|
|
||||||
// id := ctx.Secrets.Register("mysecret")
|
|
||||||
// secret := ctx.Secrets.Get(id)
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Platform *platformContext
|
Platform *platformContext
|
||||||
FS *fsContext
|
FS *fsContext
|
||||||
@ -28,25 +20,26 @@ func New() *Context {
|
|||||||
platform: defaultPlatform,
|
platform: defaultPlatform,
|
||||||
},
|
},
|
||||||
FS: &fsContext{
|
FS: &fsContext{
|
||||||
store: make(map[ContextKey]*FS),
|
store: make(map[string]*FS),
|
||||||
},
|
},
|
||||||
LocalDirs: &localDirContext{
|
LocalDirs: &localDirContext{
|
||||||
store: make(map[ContextKey]*LocalDir),
|
store: []string{},
|
||||||
},
|
},
|
||||||
Secrets: &secretContext{
|
Secrets: &secretContext{
|
||||||
store: make(map[ContextKey]*Secret),
|
store: make(map[string]*Secret),
|
||||||
},
|
},
|
||||||
Services: &serviceContext{
|
Services: &serviceContext{
|
||||||
store: make(map[ContextKey]*Service),
|
store: make(map[string]*Service),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashID(v interface{}) ContextKey {
|
func hashID(values ...string) string {
|
||||||
data, err := json.Marshal(v)
|
hash := sha256.New()
|
||||||
if err != nil {
|
for _, v := range values {
|
||||||
|
if _, err := hash.Write([]byte(v)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
hash := sha256.Sum256(data)
|
}
|
||||||
return ContextKey(fmt.Sprintf("%x", hash))
|
return fmt.Sprintf("%x", hash)
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,8 @@ import (
|
|||||||
func TestContext(t *testing.T) {
|
func TestContext(t *testing.T) {
|
||||||
ctx := New()
|
ctx := New()
|
||||||
|
|
||||||
id := ctx.Secrets.Register(&Secret{
|
secret := ctx.Secrets.New("test")
|
||||||
PlainText: "test",
|
get, err := ctx.Secrets.FromValue(secret.MarshalCUE())
|
||||||
})
|
require.NoError(t, err)
|
||||||
secret := ctx.Secrets.Get(id)
|
require.Equal(t, "test", get.PlainText())
|
||||||
require.NotNil(t, secret)
|
|
||||||
require.Equal(t, "test", secret.PlainText)
|
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,76 @@
|
|||||||
package plancontext
|
package plancontext
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"cuelang.org/go/cue"
|
||||||
|
"github.com/google/uuid"
|
||||||
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
|
"go.dagger.io/dagger/compiler"
|
||||||
|
"go.dagger.io/dagger/stdlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fsIDPath = cue.MakePath(
|
||||||
|
cue.Hid("_fs", stdlib.PackageName),
|
||||||
|
cue.Str("id"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsFSValue(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(fsIDPath).Exists()
|
||||||
|
}
|
||||||
|
|
||||||
type FS struct {
|
type FS struct {
|
||||||
Result bkgw.Reference
|
id string
|
||||||
|
result bkgw.Reference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FS) Result() bkgw.Reference {
|
||||||
|
return fs.result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *FS) MarshalCUE() *compiler.Value {
|
||||||
|
v := compiler.NewValue()
|
||||||
|
if err := v.FillPath(fsIDPath, fs.id); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
type fsContext struct {
|
type fsContext struct {
|
||||||
l sync.RWMutex
|
l sync.RWMutex
|
||||||
store map[ContextKey]*FS
|
store map[string]*FS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fsContext) Register(fs *FS) ContextKey {
|
func (c *fsContext) New(result bkgw.Reference) *FS {
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
id := hashID(fs)
|
fs := &FS{
|
||||||
c.store[id] = fs
|
// FIXME: get a hash from result instead
|
||||||
return id
|
id: uuid.New().String(),
|
||||||
|
result: result,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.store[fs.id] = fs
|
||||||
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *fsContext) Get(id ContextKey) *FS {
|
func (c *fsContext) FromValue(v *compiler.Value) (*FS, error) {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
return c.store[id]
|
id, err := v.LookupPath(fsIDPath).String()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid FS %q: %w", v.Path(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fs, ok := c.store[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("fs %q not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs, nil
|
||||||
}
|
}
|
||||||
|
@ -5,41 +5,16 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LocalDir struct {
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|
||||||
type localDirContext struct {
|
type localDirContext struct {
|
||||||
l sync.RWMutex
|
l sync.RWMutex
|
||||||
store map[ContextKey]*LocalDir
|
store []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localDirContext) Register(directory *LocalDir) ContextKey {
|
func (c *localDirContext) Add(dir string) {
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
id := hashID(directory)
|
c.store = append(c.store, dir)
|
||||||
c.store[id] = directory
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *localDirContext) Get(id ContextKey) *LocalDir {
|
|
||||||
c.l.RLock()
|
|
||||||
defer c.l.RUnlock()
|
|
||||||
|
|
||||||
return c.store[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *localDirContext) List() []*LocalDir {
|
|
||||||
c.l.RLock()
|
|
||||||
defer c.l.RUnlock()
|
|
||||||
|
|
||||||
directories := make([]*LocalDir, 0, len(c.store))
|
|
||||||
for _, d := range c.store {
|
|
||||||
directories = append(directories, d)
|
|
||||||
}
|
|
||||||
|
|
||||||
return directories
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *localDirContext) Paths() (map[string]string, error) {
|
func (c *localDirContext) Paths() (map[string]string, error) {
|
||||||
@ -48,12 +23,12 @@ func (c *localDirContext) Paths() (map[string]string, error) {
|
|||||||
|
|
||||||
directories := make(map[string]string)
|
directories := make(map[string]string)
|
||||||
for _, d := range c.store {
|
for _, d := range c.store {
|
||||||
abs, err := filepath.Abs(d.Path)
|
abs, err := filepath.Abs(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
directories[d.Path] = abs
|
directories[d] = abs
|
||||||
}
|
}
|
||||||
|
|
||||||
return directories, nil
|
return directories, nil
|
||||||
|
@ -1,26 +1,82 @@
|
|||||||
package plancontext
|
package plancontext
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
type secretContext struct {
|
"cuelang.org/go/cue"
|
||||||
l sync.RWMutex
|
"go.dagger.io/dagger/compiler"
|
||||||
store map[ContextKey]*Secret
|
"go.dagger.io/dagger/stdlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
secretIDPath = cue.MakePath(
|
||||||
|
cue.Hid("_secret", stdlib.PackageName),
|
||||||
|
cue.Str("id"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsSecretValue(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(secretIDPath).Exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Secret struct {
|
type Secret struct {
|
||||||
PlainText string
|
id string
|
||||||
|
plainText string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *secretContext) Register(secret *Secret) ContextKey {
|
func (s *Secret) ID() string {
|
||||||
|
return s.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Secret) PlainText() string {
|
||||||
|
return s.plainText
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Secret) MarshalCUE() *compiler.Value {
|
||||||
|
v := compiler.NewValue()
|
||||||
|
if err := v.FillPath(secretIDPath, s.id); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
type secretContext struct {
|
||||||
|
l sync.RWMutex
|
||||||
|
store map[string]*Secret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *secretContext) New(plaintext string) *Secret {
|
||||||
|
secret := &Secret{
|
||||||
|
id: hashID(plaintext),
|
||||||
|
plainText: plaintext,
|
||||||
|
}
|
||||||
|
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
id := hashID(secret.PlainText)
|
c.store[secret.id] = secret
|
||||||
c.store[id] = secret
|
return secret
|
||||||
return id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *secretContext) Get(id ContextKey) *Secret {
|
func (c *secretContext) FromValue(v *compiler.Value) (*Secret, error) {
|
||||||
|
c.l.RLock()
|
||||||
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
|
id, err := v.LookupPath(secretIDPath).String()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid secret %q: %w", v.Path(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, ok := c.store[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("secret %q not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return secret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *secretContext) Get(id string) *Secret {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
|
@ -1,27 +1,89 @@
|
|||||||
package plancontext
|
package plancontext
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
type serviceContext struct {
|
"cuelang.org/go/cue"
|
||||||
l sync.RWMutex
|
"go.dagger.io/dagger/compiler"
|
||||||
store map[ContextKey]*Service
|
"go.dagger.io/dagger/stdlib"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
serviceIDPath = cue.MakePath(
|
||||||
|
cue.Hid("_service", stdlib.PackageName),
|
||||||
|
cue.Str("id"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsServiceValue(v *compiler.Value) bool {
|
||||||
|
return v.LookupPath(serviceIDPath).Exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service struct {
|
type Service struct {
|
||||||
Unix string
|
id string
|
||||||
Npipe string
|
|
||||||
|
unix string
|
||||||
|
npipe string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *serviceContext) Register(service *Service) ContextKey {
|
func (s *Service) ID() string {
|
||||||
|
return s.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Unix() string {
|
||||||
|
return s.unix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) NPipe() string {
|
||||||
|
return s.npipe
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) MarshalCUE() *compiler.Value {
|
||||||
|
v := compiler.NewValue()
|
||||||
|
if err := v.FillPath(serviceIDPath, s.id); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
type serviceContext struct {
|
||||||
|
l sync.RWMutex
|
||||||
|
store map[string]*Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *serviceContext) New(unix, npipe string) *Service {
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|
||||||
id := hashID(service)
|
s := &Service{
|
||||||
c.store[id] = service
|
id: hashID(unix, npipe),
|
||||||
return id
|
unix: unix,
|
||||||
|
npipe: npipe,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.store[s.id] = s
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *serviceContext) Get(id ContextKey) *Service {
|
func (c *serviceContext) FromValue(v *compiler.Value) (*Service, error) {
|
||||||
|
c.l.RLock()
|
||||||
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
|
id, err := v.LookupPath(serviceIDPath).String()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid service %q: %w", v.Path(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, ok := c.store[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("service %q not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *serviceContext) Get(id string) *Service {
|
||||||
c.l.RLock()
|
c.l.RLock()
|
||||||
defer c.l.RUnlock()
|
defer c.l.RUnlock()
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ type inputStore struct {
|
|||||||
func (s *inputStore) GetSecret(ctx context.Context, id string) ([]byte, error) {
|
func (s *inputStore) GetSecret(ctx context.Context, id string) ([]byte, error) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
secret := s.pctx.Secrets.Get(plancontext.ContextKey(id))
|
secret := s.pctx.Secrets.Get(id)
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
return nil, secrets.ErrNotFound
|
return nil, secrets.ErrNotFound
|
||||||
}
|
}
|
||||||
@ -31,5 +31,5 @@ func (s *inputStore) GetSecret(ctx context.Context, id string) ([]byte, error) {
|
|||||||
Str("id", id).
|
Str("id", id).
|
||||||
Msg("injecting secret")
|
Msg("injecting secret")
|
||||||
|
|
||||||
return []byte(secret.PlainText), nil
|
return []byte(secret.PlainText()), nil
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ func (sp *SocketProvider) ForwardAgent(stream sshforward.SSH_ForwardAgentServer)
|
|||||||
id = v[0]
|
id = v[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
service := sp.pctx.Services.Get(plancontext.ContextKey(id))
|
service := sp.pctx.Services.Get(id)
|
||||||
if service == nil {
|
if service == nil {
|
||||||
return fmt.Errorf("invalid socket id %q", id)
|
return fmt.Errorf("invalid socket id %q", id)
|
||||||
}
|
}
|
||||||
|
@ -12,9 +12,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func dialService(service *plancontext.Service) (net.Conn, error) {
|
func dialService(service *plancontext.Service) (net.Conn, error) {
|
||||||
if service.Unix == "" {
|
if service.Unix() == "" {
|
||||||
return nil, errors.New("unsupported socket type")
|
return nil, errors.New("unsupported socket type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return net.DialTimeout("unix", service.Unix, time.Second)
|
return net.DialTimeout("unix", service.Unix(), time.Second)
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func dialService(service *plancontext.Service) (net.Conn, error) {
|
func dialService(service *plancontext.Service) (net.Conn, error) {
|
||||||
if service.Npipe == "" {
|
if service.NPipe() == "" {
|
||||||
return nil, errors.New("unsupported socket type")
|
return nil, errors.New("unsupported socket type")
|
||||||
}
|
}
|
||||||
|
|
||||||
dur := time.Second
|
dur := time.Second
|
||||||
return winio.DialPipe(service.Npipe, &dur)
|
return winio.DialPipe(service.NPipe(), &dur)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"cuelang.org/go/cue"
|
"cuelang.org/go/cue"
|
||||||
|
|
||||||
"go.dagger.io/dagger/compiler"
|
"go.dagger.io/dagger/compiler"
|
||||||
"go.dagger.io/dagger/plancontext"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// An input is a value or artifact supplied by the user.
|
// An input is a value or artifact supplied by the user.
|
||||||
@ -121,9 +120,7 @@ func (dir dirInput) Compile(state *State) (*compiler.Value, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
state.Context.LocalDirs.Register(&plancontext.LocalDir{
|
state.Context.LocalDirs.Add(p)
|
||||||
Path: p,
|
|
||||||
})
|
|
||||||
|
|
||||||
llb := fmt.Sprintf(
|
llb := fmt.Sprintf(
|
||||||
`#up: [{do: "local", dir: %s, include: %s, exclude: %s}]`,
|
`#up: [{do: "local", dir: %s, include: %s, exclude: %s}]`,
|
||||||
@ -195,11 +192,8 @@ func SecretInput(data string) Input {
|
|||||||
type secretInput string
|
type secretInput string
|
||||||
|
|
||||||
func (i secretInput) Compile(st *State) (*compiler.Value, error) {
|
func (i secretInput) Compile(st *State) (*compiler.Value, error) {
|
||||||
id := st.Context.Secrets.Register(&plancontext.Secret{
|
secret := st.Context.Secrets.New(i.PlainText())
|
||||||
PlainText: i.PlainText(),
|
return secret.MarshalCUE(), nil
|
||||||
})
|
|
||||||
secretValue := fmt.Sprintf(`{id: %q}`, id)
|
|
||||||
return compiler.Compile("", secretValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i secretInput) PlainText() string {
|
func (i secretInput) PlainText() string {
|
||||||
@ -301,10 +295,6 @@ type socketInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i socketInput) Compile(st *State) (*compiler.Value, error) {
|
func (i socketInput) Compile(st *State) (*compiler.Value, error) {
|
||||||
id := st.Context.Services.Register(&plancontext.Service{
|
service := st.Context.Services.New(i.Unix, i.Npipe)
|
||||||
Unix: i.Unix,
|
return service.MarshalCUE(), nil
|
||||||
Npipe: i.Npipe,
|
|
||||||
})
|
|
||||||
socketValue := fmt.Sprintf(`{id: %q}`, id)
|
|
||||||
return compiler.Compile("", socketValue)
|
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ func VendorUniverse(ctx context.Context, p string) error {
|
|||||||
// add universe and lock file to `.gitignore`
|
// add universe and lock file to `.gitignore`
|
||||||
if err := os.WriteFile(
|
if err := os.WriteFile(
|
||||||
path.Join(p, "cue.mod", "pkg", ".gitignore"),
|
path.Join(p, "cue.mod", "pkg", ".gitignore"),
|
||||||
[]byte(fmt.Sprintf("# generated by dagger\n%s\ndagger.lock\n", stdlib.PackageName)),
|
[]byte(fmt.Sprintf("# generated by dagger\n%s\ndagger.lock\n", stdlib.ModuleName)),
|
||||||
0600,
|
0600,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -408,7 +408,7 @@ func VendorUniverse(ctx context.Context, p string) error {
|
|||||||
log.Ctx(ctx).Debug().Str("mod", p).Msg("vendoring universe")
|
log.Ctx(ctx).Debug().Str("mod", p).Msg("vendoring universe")
|
||||||
if err := stdlib.Vendor(ctx, p); err != nil {
|
if err := stdlib.Vendor(ctx, p); err != nil {
|
||||||
// FIXME(samalba): disabled install remote stdlib temporarily
|
// FIXME(samalba): disabled install remote stdlib temporarily
|
||||||
// if _, err := mod.Install(ctx, p, "alpha.dagger.io", ""); err != nil {
|
// if _, err := mod.Install(ctx, p, stdlib.ModuleName, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,13 +24,18 @@ import (
|
|||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dagger stream. Can be mounted as a UNIX socket.
|
// A reference to a network service endpoint, for example:
|
||||||
#Stream: {
|
// - A TCP or UDP port
|
||||||
@dagger(stream)
|
// - A unix or npipe socket
|
||||||
|
// - An HTTPS endpoint
|
||||||
id: string
|
#Service: {
|
||||||
|
_service: id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dagger stream. Can be mounted as a UNIX socket.
|
||||||
|
// FIXME: Deprecated. For backward compatibility only, use #Service instead.
|
||||||
|
#Stream: #Service
|
||||||
|
|
||||||
// A reference to an external secret, for example:
|
// A reference to an external secret, for example:
|
||||||
// - A password
|
// - A password
|
||||||
// - A SSH private key
|
// - A SSH private key
|
||||||
@ -38,9 +43,7 @@ import (
|
|||||||
// Secrets are never merged in the Cue tree. They can only be used
|
// Secrets are never merged in the Cue tree. They can only be used
|
||||||
// by a special filesystem mount designed to minimize leak risk.
|
// by a special filesystem mount designed to minimize leak risk.
|
||||||
#Secret: {
|
#Secret: {
|
||||||
@dagger(secret)
|
_secret: id: string
|
||||||
|
|
||||||
id: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#Input: {
|
#Input: {
|
||||||
|
@ -17,8 +17,9 @@ var (
|
|||||||
//go:embed **/*.cue **/*/*.cue
|
//go:embed **/*.cue **/*/*.cue
|
||||||
FS embed.FS
|
FS embed.FS
|
||||||
|
|
||||||
PackageName = "alpha.dagger.io"
|
ModuleName = "alpha.dagger.io"
|
||||||
Path = path.Join("cue.mod", "pkg", PackageName)
|
PackageName = fmt.Sprintf("%s/dagger", ModuleName)
|
||||||
|
Path = path.Join("cue.mod", "pkg", ModuleName)
|
||||||
lockFilePath = path.Join("cue.mod", "dagger.lock")
|
lockFilePath = path.Join("cue.mod", "dagger.lock")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ TestSecrets: #up: [
|
|||||||
|
|
||||||
op.#Exec & {
|
op.#Exec & {
|
||||||
mount: "/secret": secret: mySecret
|
mount: "/secret": secret: mySecret
|
||||||
env: PLAIN: mySecret.id
|
|
||||||
args: [
|
args: [
|
||||||
"/bin/bash",
|
"/bin/bash",
|
||||||
"--noprofile",
|
"--noprofile",
|
||||||
@ -27,7 +26,6 @@ TestSecrets: #up: [
|
|||||||
"-c",
|
"-c",
|
||||||
#"""
|
#"""
|
||||||
test "$(cat /secret)" = "SecretValue"
|
test "$(cat /secret)" = "SecretValue"
|
||||||
test "$PLAIN" != "SecretValue"
|
|
||||||
"""#,
|
"""#,
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -141,10 +141,6 @@ setup() {
|
|||||||
"$DAGGER" input secret mySecret SecretValue
|
"$DAGGER" input secret mySecret SecretValue
|
||||||
run "$DAGGER" up
|
run "$DAGGER" up
|
||||||
assert_success
|
assert_success
|
||||||
|
|
||||||
# Make sure the secret doesn't show in dagger query
|
|
||||||
run "$DAGGER" query mySecret.id -f text
|
|
||||||
assert_success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "core: stream" {
|
@test "core: stream" {
|
||||||
|
Reference in New Issue
Block a user