Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
ff5ed79
echo tags
SergioLangaritaBenitez Apr 9, 2025
708df2e
echo tags
SergioLangaritaBenitez Apr 9, 2025
a032c77
echo tags
SergioLangaritaBenitez Apr 9, 2025
544d0f3
echo tags
SergioLangaritaBenitez Apr 9, 2025
6969995
Merge branch 'main' of github.com:grycap/oscar-cli into dev-slangarita
SergioLangaritaBenitez Sep 30, 2025
70e225d
Merge branch 'main' of github.com:grycap/oscar-cli into dev-slangarita
SergioLangaritaBenitez Oct 6, 2025
68609fd
list log pagination
SergioLangaritaBenitez Oct 6, 2025
72ee90b
list log pagination
SergioLangaritaBenitez Oct 6, 2025
bf9ebd9
update go version to 1.25
SergioLangaritaBenitez Oct 6, 2025
9ec5ba4
Merge branch 'main' of github.com:grycap/oscar-cli into dev-slangarita
SergioLangaritaBenitez Oct 6, 2025
d95cf33
Adapt autentication to keycloak
SergioLangaritaBenitez Oct 6, 2025
27f513e
Merge branch 'main' of github.com:grycap/oscar-cli into dev-slangarita
SergioLangaritaBenitez Oct 6, 2025
b371883
update machine run
SergioLangaritaBenitez Oct 7, 2025
f9e6782
adapt jobs old and new version
SergioLangaritaBenitez Oct 16, 2025
9a999ff
resolve conflict
SergioLangaritaBenitez Oct 16, 2025
acc5044
merge devel into dev-slangarita
SergioLangaritaBenitez May 20, 2026
b5c7e35
add skills-lock
SergioLangaritaBenitez May 20, 2026
47492ac
remove skills and skills-lock
SergioLangaritaBenitez May 25, 2026
e4ba732
Merge branch 'devel' of github.com:grycap/oscar-cli into dev-slangarita
SergioLangaritaBenitez Jul 29, 2026
dbceb9b
feat-pass-envvar implementation
SergioLangaritaBenitez Jul 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ type FDL struct {
- `ListServicesWithContext(ctx, c) ([]*types.Service, error)`
- `RemoveService(c, name) error` — DELETE `/system/services/{name}`
- `ApplyService(svc, c, method) error` — POST or PUT `/system/services`
- `RunService(c, name, token, endpoint, input) (io.ReadCloser, error)` — synchronous POST `/run/{name}`
- `RunService(c, name, token, endpoint, input,header) (io.ReadCloser, error)` — synchronous POST `/run/{name}`
- `JobService(c, name, token, endpoint, input) (io.ReadCloser, error)` — async POST `/job/{name}`
- `ListLogs(c, name, page) (types.JobsResponse, error)` — GET `/system/logs/{name}`
- `GetLogs(c, svcName, jobName, timestamps) (string, error)`
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ Flags:
--decode-output decode the last base64-encoded line in the response and ignore logs
-e, --endpoint string endpoint of a non registered cluster
-f, --file-input string input file for the request
-H, --header string header on service invocation (e.g. "Content-Type:application/json")
-h, --help help for run
-o, --output string file path to store the output
-i, --text-input string text input string for the request
Expand All @@ -370,6 +371,11 @@ Global Flags:
--config string set the location of the config file (YAML or JSON)
```

Examples:
```
oscar-cli service run my-service -i '{"key":"value"}' -H "Content-Type:application/json"
```

##### logs list

List the logs from a service.
Expand Down
4 changes: 3 additions & 1 deletion cmd/hub_validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type hubValidateOptions struct {
name string
localPath string
printAcceptanceCommands bool
header string
}

func (o *hubValidateOptions) applyToClient() []hub.Option {
Expand Down Expand Up @@ -98,7 +99,7 @@ func hubValidateFunc(cmd *cobra.Command, args []string, opts *hubValidateOptions

fmt.Fprintf(out, "Acceptance tests for %s\n", args[0])

results, err := client.ValidateService(cmd.Context(), args[0], conf.Oscar[clusterID], opts.name, opts.localPath)
results, err := client.ValidateService(cmd.Context(), args[0], conf.Oscar[clusterID], opts.name, opts.localPath, opts.header)
if err != nil {
return err
}
Expand Down Expand Up @@ -154,6 +155,7 @@ func makeHubValidateCmd() *cobra.Command {
cmd.Flags().StringVar(&opts.apiBase, "api-base", "", "override the GitHub API base URL")
cmd.Flags().StringVarP(&opts.name, "name", "n", "", "override the OSCAR service name during validation")
cmd.Flags().StringVar(&opts.localPath, "local-path", "", "use a local directory containing the RO-Crate metadata instead of fetching it from GitHub")
cmd.Flags().StringVarP(&opts.header, "header", "H", "", "header on service invocation (e.g. \"Content-Type:application/json\")")
cmd.Flags().BoolVar(&opts.printAcceptanceCommands, "print-acceptance-commands", false, "print the acceptance test shell commands instead of executing them")
if flag := cmd.Flags().Lookup("api-base"); flag != nil {
flag.Hidden = true
Expand Down
4 changes: 3 additions & 1 deletion cmd/service_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func serviceRunFunc(cmd *cobra.Command, args []string) error {
textInput, _ := cmd.Flags().GetString("text-input")
outputFile, _ := cmd.Flags().GetString("output")
decodeOutput, _ := cmd.Flags().GetBool("decode-output")
header, _ := cmd.Flags().GetString("header")
if inputFile == "" && textInput == "" {
return errors.New("you must specify \"--file-input\" or \"--text-input\" flag")
}
Expand Down Expand Up @@ -94,7 +95,7 @@ func serviceRunFunc(cmd *cobra.Command, args []string) error {
writer.Close()
}()
// Make the request
resBody, err := service.RunService(conf.Oscar[cluster], args[0], token, endpoint, reader)
resBody, err := service.RunService(conf.Oscar[cluster], args[0], token, endpoint, reader, header)
if err != nil {
return err
}
Expand Down Expand Up @@ -237,6 +238,7 @@ func makeServiceRunCmd() *cobra.Command {
serviceRunCmd.Flags().StringP("file-input", "f", "", "input file for the request")
serviceRunCmd.Flags().StringP("text-input", "i", "", "text input string for the request")
serviceRunCmd.Flags().StringP("output", "o", "", "file path to store the output")
serviceRunCmd.Flags().StringP("header", "H", "", "header on service invocation")
serviceRunCmd.Flags().Bool("decode-output", false, "decode the last base64-encoded line in the response and ignore logs")

return serviceRunCmd
Expand Down
16 changes: 8 additions & 8 deletions pkg/hub/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ type AcceptanceCommandSet struct {
}

// ValidateService downloads the RO-Crate metadata for the provided slug, runs its acceptance tests against the cluster and returns the aggregated results.
func (c *Client) ValidateService(ctx context.Context, slug string, clusterCfg *cluster.Cluster, serviceNameOverride string, localRoot string) ([]AcceptanceResult, error) {
func (c *Client) ValidateService(ctx context.Context, slug string, clusterCfg *cluster.Cluster, serviceNameOverride string, localRoot string, header string) ([]AcceptanceResult, error) {
if strings.TrimSpace(slug) == "" {
return nil, errors.New("service slug cannot be empty")
}
Expand All @@ -110,7 +110,7 @@ func (c *Client) ValidateService(ctx context.Context, slug string, clusterCfg *c
testName = test.ID
}
c.logf("Running acceptance test: %s\n", testName)
res := c.runAcceptanceTest(ctx, repoPath, slug, test, clusterCfg, serviceNameOverride, localCratePath, serviceCache)
res := c.runAcceptanceTest(ctx, repoPath, slug, test, clusterCfg, serviceNameOverride, localCratePath, serviceCache, header)
c.logAcceptanceResult(res)
results = append(results, res)
}
Expand Down Expand Up @@ -178,7 +178,7 @@ func (c *Client) loadAcceptanceTests(ctx context.Context, slug string, localRoot
return repoPath, localCratePath, tests, nil
}

func (c *Client) runAcceptanceTest(ctx context.Context, repoPath, slug string, test AcceptanceTest, clusterCfg *cluster.Cluster, serviceNameOverride string, localCratePath string, svcCache map[string]*types.Service) AcceptanceResult {
func (c *Client) runAcceptanceTest(ctx context.Context, repoPath, slug string, test AcceptanceTest, clusterCfg *cluster.Cluster, serviceNameOverride string, localCratePath string, svcCache map[string]*types.Service, header string) AcceptanceResult {
result := AcceptanceResult{Test: test}

steps := test.Steps
Expand All @@ -201,7 +201,7 @@ func (c *Client) runAcceptanceTest(ctx context.Context, repoPath, slug string, t
var lastOutput string

for _, step := range steps {
stepRes := c.executeAcceptanceStep(ctx, repoPath, slug, test, step, supplyCache, clusterCfg, serviceNameOverride, localCratePath, svcCache, tempDir)
stepRes := c.executeAcceptanceStep(ctx, repoPath, slug, test, step, supplyCache, clusterCfg, serviceNameOverride, localCratePath, svcCache, tempDir, header)
result.StepResults = append(result.StepResults, stepRes)

if stepRes.Output != "" {
Expand Down Expand Up @@ -444,7 +444,7 @@ func shellQuote(value string) string {
return value
}

func (c *Client) executeAcceptanceStep(ctx context.Context, repoPath, slug string, test AcceptanceTest, step AcceptanceStep, baseSupply map[string]TestInput, clusterCfg *cluster.Cluster, serviceNameOverride string, localCratePath string, svcCache map[string]*types.Service, tempDir string) AcceptanceStepResult {
func (c *Client) executeAcceptanceStep(ctx context.Context, repoPath, slug string, test AcceptanceTest, step AcceptanceStep, baseSupply map[string]TestInput, clusterCfg *cluster.Cluster, serviceNameOverride string, localCratePath string, svcCache map[string]*types.Service, tempDir string, header string) AcceptanceStepResult {
result := AcceptanceStepResult{Step: step}

if strings.TrimSpace(step.Command) == "" {
Expand Down Expand Up @@ -480,7 +480,7 @@ func (c *Client) executeAcceptanceStep(ctx context.Context, repoPath, slug strin
return result
}

responseBytes, err := invokeServiceWithContent(clusterCfg, serviceName, payload)
responseBytes, err := invokeServiceWithContent(clusterCfg, serviceName, payload, header)
if err != nil {
result.Err = err
return result
Expand Down Expand Up @@ -1434,7 +1434,7 @@ func isWhitespace(r rune) bool {
return r == ' ' || r == '\t' || r == '\n' || r == '\r'
}

func invokeServiceWithContent(clusterCfg *cluster.Cluster, serviceName string, payload []byte) ([]byte, error) {
func invokeServiceWithContent(clusterCfg *cluster.Cluster, serviceName string, payload []byte, header string) ([]byte, error) {
reader, writer := io.Pipe()
go func() {
encoder := base64.NewEncoder(base64.StdEncoding, writer)
Expand All @@ -1447,7 +1447,7 @@ func invokeServiceWithContent(clusterCfg *cluster.Cluster, serviceName string, p
}
}()

response, err := service.RunService(clusterCfg, serviceName, "", "", reader)
response, err := service.RunService(clusterCfg, serviceName, "", "", reader, header)
if err != nil {
return nil, err
}
Expand Down
9 changes: 8 additions & 1 deletion pkg/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func ApplyService(svc *types.Service, c *cluster.Cluster, method string) error {
}

// RunService invokes a service synchronously (a Serverless backend in the cluster is required)
func RunService(c *cluster.Cluster, name string, token string, endpoint string, input io.Reader) (responseBody io.ReadCloser, err error) {
func RunService(c *cluster.Cluster, name string, token string, endpoint string, input io.Reader, header string) (responseBody io.ReadCloser, err error) {
client := &http.Client{Timeout: time.Second * runServiceTimeoutSeconds}
if token == "" {
client, _ = c.GetClientSafe(runServiceTimeoutSeconds)
Expand Down Expand Up @@ -288,6 +288,13 @@ func RunService(c *cluster.Cluster, name string, token string, endpoint string,
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
if header != "" {
for _, lines := range strings.Split(header, ",") {
chunck := strings.Split(lines, ":")
req.Header.Add(chunck[0], chunck[1])
}

}
if err != nil {
return nil, cluster.ErrMakingRequest
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/service/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func TestRunServiceUsesServiceToken(t *testing.T) {
SSLVerify: true,
}

resp, err := RunService(c, serviceName, "", "", bytes.NewBufferString(payload))
resp, err := RunService(c, serviceName, "", "", bytes.NewBufferString(payload), "")
if err != nil {
t.Fatalf("RunService returned error: %v", err)
}
Expand Down Expand Up @@ -224,7 +224,7 @@ func TestRunServiceWithProvidedToken(t *testing.T) {
}))
defer server.Close()

resp, err := RunService(&cluster.Cluster{Endpoint: server.URL, SSLVerify: true}, serviceName, token, server.URL, bytes.NewBufferString(payload))
resp, err := RunService(&cluster.Cluster{Endpoint: server.URL, SSLVerify: true}, serviceName, token, server.URL, bytes.NewBufferString(payload), "")
if err != nil {
t.Fatalf("RunService returned error: %v", err)
}
Expand Down
Loading