diff --git a/README.md b/README.md index 9bd09666e3..58111d46f5 100644 --- a/README.md +++ b/README.md @@ -290,6 +290,7 @@ Full documentation is available at [docs.dagu.cloud](https://docs.dagu.cloud/). |---------------------|---------|-------------| | `DAGU_HOME` | - | Base directory that overrides all path configurations | | `DAGU_DAGS_DIR` | `~/.config/dagu/dags` | Directory for DAG definitions | +| `DAGU_ALT_DAGS_DIR` | - | Additional directory to search for DAG definitions | | `DAGU_LOG_DIR` | `~/.local/share/dagu/logs` | Directory for log files | | `DAGU_DATA_DIR` | `~/.local/share/dagu/data` | Directory for application data | | `DAGU_SUSPEND_FLAGS_DIR` | `~/.local/share/dagu/suspend` | Directory for suspend flags | diff --git a/api/v2/api.gen.go b/api/v2/api.gen.go index 7b735a3f80..ced8658a75 100644 --- a/api/v2/api.gen.go +++ b/api/v2/api.gen.go @@ -1984,6 +1984,9 @@ type ExecuteDAGRunFromSpecParams struct { type EnqueueDAGRunFromSpecJSONBody struct { DagRunId *string `json:"dagRunId,omitempty"` + // Filename Filename for the yaml file + Filename *string `json:"filename,omitempty"` + // Name Optional name to use when the spec omits a name Name *string `json:"name,omitempty"` @@ -1994,7 +1997,8 @@ type EnqueueDAGRunFromSpecJSONBody struct { Queue *string `json:"queue,omitempty"` // Spec DAG specification in YAML format - Spec string `json:"spec"` + Spec *string `json:"spec,omitempty"` + union json.RawMessage } // EnqueueDAGRunFromSpecParams defines parameters for EnqueueDAGRunFromSpec. @@ -2003,6 +2007,12 @@ type EnqueueDAGRunFromSpecParams struct { RemoteNode *RemoteNode `form:"remoteNode,omitempty" json:"remoteNode,omitempty"` } +// EnqueueDAGRunFromSpecJSONBody0 defines parameters for EnqueueDAGRunFromSpec. +type EnqueueDAGRunFromSpecJSONBody0 = interface{} + +// EnqueueDAGRunFromSpecJSONBody1 defines parameters for EnqueueDAGRunFromSpec. +type EnqueueDAGRunFromSpecJSONBody1 = interface{} + // ListDAGRunsByNameParams defines parameters for ListDAGRunsByName. type ListDAGRunsByNameParams struct { // Status status of the DAG-run @@ -15296,134 +15306,135 @@ var swaggerSpec = []string{ "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", + "RpG09QFwQaGAb5+//X8BAAD///v3Vb1lLQIA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v2/api.yaml b/api/v2/api.yaml index 7db814db82..a0df3b3160 100644 --- a/api/v2/api.yaml +++ b/api/v2/api.yaml @@ -1613,8 +1613,12 @@ paths: queue: type: string description: "Override the queue to use for this DAG-run" - required: - - spec + filename: + type: string + description: "Filename for the yaml file" + oneOf: + - required: [spec] + - required: [filename] responses: "200": description: "DAG-run successfully enqueued" diff --git a/internal/cmd/context.go b/internal/cmd/context.go index fafa6ce1d8..625f94ac46 100644 --- a/internal/cmd/context.go +++ b/internal/cmd/context.go @@ -375,10 +375,16 @@ type dagStoreConfig struct { // dagStore returns a new DAGRepository instance. func (c *Context) dagStore(cfg dagStoreConfig) (exec.DAGStore, error) { + // Merge configured alternate DAGs directory into search paths if provided + searchPaths := append([]string{}, cfg.SearchPaths...) + if c.Config != nil && c.Config.Paths.AltDAGsDir != "" { + searchPaths = append(searchPaths, c.Config.Paths.AltDAGsDir) + } + store := filedag.New( c.Config.Paths.DAGsDir, filedag.WithFlagsBaseDir(c.Config.Paths.SuspendFlagsDir), - filedag.WithSearchPaths(cfg.SearchPaths), + filedag.WithSearchPaths(searchPaths), filedag.WithFileCache(cfg.Cache), filedag.WithSkipExamples(c.Config.Core.SkipExamples), filedag.WithSkipDirectoryCreation(cfg.SkipDirectoryCreation), diff --git a/internal/cmn/config/config.go b/internal/cmn/config/config.go index 0305df6d0f..05cab67104 100644 --- a/internal/cmn/config/config.go +++ b/internal/cmn/config/config.go @@ -240,6 +240,7 @@ type PathsConfig struct { SuspendFlagsDir string AdminLogsDir string BaseConfig string + AltDAGsDir string DAGRunsDir string QueueDir string ProcDir string diff --git a/internal/cmn/config/definition.go b/internal/cmn/config/definition.go index c44a099fdb..5ea088b54e 100644 --- a/internal/cmn/config/definition.go +++ b/internal/cmn/config/definition.go @@ -178,6 +178,7 @@ type PathsDef struct { SuspendFlagsDir string `mapstructure:"suspendFlagsDir"` AdminLogsDir string `mapstructure:"adminLogsDir"` BaseConfig string `mapstructure:"baseConfig"` + AltDagsDir string `mapstructure:"altDagsDir"` DAGRunsDir string `mapstructure:"dagRunsDir"` QueueDir string `mapstructure:"queueDir"` ProcDir string `mapstructure:"procDir"` diff --git a/internal/cmn/config/loader.go b/internal/cmn/config/loader.go index ef5b8908a0..ca8779a2c3 100644 --- a/internal/cmn/config/loader.go +++ b/internal/cmn/config/loader.go @@ -311,6 +311,7 @@ func (l *ConfigLoader) loadPathsConfig(cfg *Config, def Definition) error { source string }{ {"DAGsDir", &cfg.Paths.DAGsDir, def.Paths.DAGsDir}, + {"AltDAGsDir", &cfg.Paths.AltDAGsDir, def.Paths.AltDagsDir}, {"SuspendFlagsDir", &cfg.Paths.SuspendFlagsDir, def.Paths.SuspendFlagsDir}, {"DataDir", &cfg.Paths.DataDir, def.Paths.DataDir}, {"LogDir", &cfg.Paths.LogDir, def.Paths.LogDir}, diff --git a/internal/service/frontend/api/v2/dagruns.go b/internal/service/frontend/api/v2/dagruns.go index c9fab5d264..72411d7da7 100644 --- a/internal/service/frontend/api/v2/dagruns.go +++ b/internal/service/frontend/api/v2/dagruns.go @@ -149,15 +149,22 @@ func (a *API) EnqueueDAGRunFromSpec(ctx context.Context, request api.EnqueueDAGR return nil, err } - if request.Body == nil || request.Body.Spec == "" { + if request.Body == nil { return nil, &Error{ HTTPStatus: http.StatusBadRequest, Code: api.ErrorCodeBadRequest, - Message: "spec is required", + Message: "no body was given", } } - var dagRunId, params string + if request.Body.Spec == nil && request.Body.Filename == nil || request.Body.Spec != nil && request.Body.Filename != nil { + return nil, &Error{ + HTTPStatus: http.StatusBadRequest, + Code: api.ErrorCodeBadRequest, + Message: "either give spec or url; don't give both", + } + } + var dagRunId, params, filename string if request.Body.DagRunId != nil { dagRunId = *request.Body.DagRunId } @@ -171,8 +178,49 @@ func (a *API) EnqueueDAGRunFromSpec(ctx context.Context, request api.EnqueueDAGR if request.Body.Params != nil { params = *request.Body.Params } + if request.Body.Filename != nil { + filename = *request.Body.Filename + } + var finalSpec string + if strings.HasSuffix(filename, ".yaml") || strings.HasSuffix(filename, ".yml") { + // Use configured alternate DAGs directory if provided + if a.config != nil && a.config.Paths.AltDAGsDir != "" { + filename = fmt.Sprintf("%s/%s", a.config.Paths.AltDAGsDir, filepath.Base(filename)) + } else { + return nil, &Error{ + HTTPStatus: http.StatusBadRequest, + Code: api.ErrorCodeBadRequest, + Message: "Make sure ALT_DAGS_DIR is set in the config file", + } + } + const maxSpecBytes = 1 << 20 // 1 MiB (tune or reuse config) + info, err := os.Stat(filename) + if err != nil { + return nil, fmt.Errorf("error stating file: %w", err) + } + if info.Size() > maxSpecBytes { + return nil, &Error{ + HTTPStatus: http.StatusBadRequest, + Code: api.ErrorCodeBadRequest, + Message: "spec file too large", + } + } + data, err := os.ReadFile(filename) //nolint:gosec + if err != nil { + return nil, fmt.Errorf("Error reading file: %w", err) + } + finalSpec = string(data) + } else if request.Body.Spec != nil { + finalSpec = *request.Body.Spec + } else { + return nil, &Error{ + HTTPStatus: http.StatusBadRequest, + Code: api.ErrorCodeBadRequest, + Message: "Make sure file is a yaml file", + } + } - dag, cleanup, err := a.loadInlineDAG(ctx, request.Body.Spec, request.Body.Name, dagRunId) + dag, cleanup, err := a.loadInlineDAG(ctx, finalSpec, request.Body.Name, dagRunId) if err != nil { return nil, err } diff --git a/internal/service/frontend/api/v2/dags_test.go b/internal/service/frontend/api/v2/dags_test.go index 6970906371..f46a37ec2f 100644 --- a/internal/service/frontend/api/v2/dags_test.go +++ b/internal/service/frontend/api/v2/dags_test.go @@ -253,7 +253,7 @@ steps: name := "inline_enqueue_spec" resp := server.Client().Post("/api/v2/dag-runs/enqueue", api.EnqueueDAGRunFromSpecJSONRequestBody{ - Spec: spec, + Spec: &spec, Name: &name, }). ExpectStatus(http.StatusOK).