diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 67758ad..323e66a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: "1.25.10" + go-version: "1.25.11" - name: Check shell completions are up-to-date run: ./run-tests.sh --shell-completions @@ -32,7 +32,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: "1.25.10" + go-version: "1.25.11" - name: Check Go code formatting run: ./run-tests.sh --format-go @@ -71,7 +71,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: "1.25.10" + go-version: "1.25.11" - name: Run Go test suite run: ./run-tests.sh --go-tests @@ -116,7 +116,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: "1.25.10" + go-version: "1.25.11" - name: Run Go audit checks run: ./run-tests.sh --lint-goaudit diff --git a/.mise.toml b/.mise.toml index b0de804..40bb3fa 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,2 +1,2 @@ [tools] -go = "1.25.10" +go = "1.25.11" diff --git a/client/operations/info_responses.go b/client/operations/info_responses.go index 967441b..e610351 100644 --- a/client/operations/info_responses.go +++ b/client/operations/info_responses.go @@ -320,6 +320,12 @@ type InfoOKBody struct { // supported workflow engines SupportedWorkflowEngines *InfoOKBodySupportedWorkflowEngines `json:"supported_workflow_engines,omitempty"` + // vetted container images allowlist + VettedContainerImagesAllowlist *InfoOKBodyVettedContainerImagesAllowlist `json:"vetted_container_images_allowlist,omitempty"` + + // vetted container images enabled + VettedContainerImagesEnabled *InfoOKBodyVettedContainerImagesEnabled `json:"vetted_container_images_enabled,omitempty"` + // workspaces available WorkspacesAvailable *InfoOKBodyWorkspacesAvailable `json:"workspaces_available,omitempty"` @@ -461,6 +467,14 @@ func (o *InfoOKBody) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := o.validateVettedContainerImagesAllowlist(formats); err != nil { + res = append(res, err) + } + + if err := o.validateVettedContainerImagesEnabled(formats); err != nil { + res = append(res, err) + } + if err := o.validateWorkspacesAvailable(formats); err != nil { res = append(res, err) } @@ -1196,6 +1210,52 @@ func (o *InfoOKBody) validateSupportedWorkflowEngines(formats strfmt.Registry) e return nil } +func (o *InfoOKBody) validateVettedContainerImagesAllowlist(formats strfmt.Registry) error { + if swag.IsZero(o.VettedContainerImagesAllowlist) { // not required + return nil + } + + if o.VettedContainerImagesAllowlist != nil { + if err := o.VettedContainerImagesAllowlist.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("infoOK" + "." + "vetted_container_images_allowlist") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("infoOK" + "." + "vetted_container_images_allowlist") + } + + return err + } + } + + return nil +} + +func (o *InfoOKBody) validateVettedContainerImagesEnabled(formats strfmt.Registry) error { + if swag.IsZero(o.VettedContainerImagesEnabled) { // not required + return nil + } + + if o.VettedContainerImagesEnabled != nil { + if err := o.VettedContainerImagesEnabled.Validate(formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("infoOK" + "." + "vetted_container_images_enabled") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("infoOK" + "." + "vetted_container_images_enabled") + } + + return err + } + } + + return nil +} + func (o *InfoOKBody) validateWorkspacesAvailable(formats strfmt.Registry) error { if swag.IsZero(o.WorkspacesAvailable) { // not required return nil @@ -1416,6 +1476,14 @@ func (o *InfoOKBody) ContextValidate(ctx context.Context, formats strfmt.Registr res = append(res, err) } + if err := o.contextValidateVettedContainerImagesAllowlist(ctx, formats); err != nil { + res = append(res, err) + } + + if err := o.contextValidateVettedContainerImagesEnabled(ctx, formats); err != nil { + res = append(res, err) + } + if err := o.contextValidateWorkspacesAvailable(ctx, formats); err != nil { res = append(res, err) } @@ -2213,6 +2281,56 @@ func (o *InfoOKBody) contextValidateSupportedWorkflowEngines(ctx context.Context return nil } +func (o *InfoOKBody) contextValidateVettedContainerImagesAllowlist(ctx context.Context, formats strfmt.Registry) error { + + if o.VettedContainerImagesAllowlist != nil { + + if swag.IsZero(o.VettedContainerImagesAllowlist) { // not required + return nil + } + + if err := o.VettedContainerImagesAllowlist.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("infoOK" + "." + "vetted_container_images_allowlist") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("infoOK" + "." + "vetted_container_images_allowlist") + } + + return err + } + } + + return nil +} + +func (o *InfoOKBody) contextValidateVettedContainerImagesEnabled(ctx context.Context, formats strfmt.Registry) error { + + if o.VettedContainerImagesEnabled != nil { + + if swag.IsZero(o.VettedContainerImagesEnabled) { // not required + return nil + } + + if err := o.VettedContainerImagesEnabled.ContextValidate(ctx, formats); err != nil { + ve := new(errors.Validation) + if stderrors.As(err, &ve) { + return ve.ValidateName("infoOK" + "." + "vetted_container_images_enabled") + } + ce := new(errors.CompositeError) + if stderrors.As(err, &ce) { + return ce.ValidateName("infoOK" + "." + "vetted_container_images_enabled") + } + + return err + } + } + + return nil +} + func (o *InfoOKBody) contextValidateWorkspacesAvailable(ctx context.Context, formats strfmt.Registry) error { if o.WorkspacesAvailable != nil { @@ -3602,6 +3720,88 @@ func (o *InfoOKBodySupportedWorkflowEngines) UnmarshalBinary(b []byte) error { return nil } +/* +InfoOKBodyVettedContainerImagesAllowlist info o k body vetted container images allowlist +swagger:model InfoOKBodyVettedContainerImagesAllowlist +*/ +type InfoOKBodyVettedContainerImagesAllowlist struct { + + // title + Title string `json:"title,omitempty"` + + // value + Value []string `json:"value"` +} + +// Validate validates this info o k body vetted container images allowlist +func (o *InfoOKBodyVettedContainerImagesAllowlist) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this info o k body vetted container images allowlist based on context it is used +func (o *InfoOKBodyVettedContainerImagesAllowlist) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *InfoOKBodyVettedContainerImagesAllowlist) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *InfoOKBodyVettedContainerImagesAllowlist) UnmarshalBinary(b []byte) error { + var res InfoOKBodyVettedContainerImagesAllowlist + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +InfoOKBodyVettedContainerImagesEnabled info o k body vetted container images enabled +swagger:model InfoOKBodyVettedContainerImagesEnabled +*/ +type InfoOKBodyVettedContainerImagesEnabled struct { + + // title + Title string `json:"title,omitempty"` + + // value + Value bool `json:"value"` +} + +// Validate validates this info o k body vetted container images enabled +func (o *InfoOKBodyVettedContainerImagesEnabled) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this info o k body vetted container images enabled based on context it is used +func (o *InfoOKBodyVettedContainerImagesEnabled) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *InfoOKBodyVettedContainerImagesEnabled) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *InfoOKBodyVettedContainerImagesEnabled) UnmarshalBinary(b []byte) error { + var res InfoOKBodyVettedContainerImagesEnabled + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + /* InfoOKBodyWorkspacesAvailable info o k body workspaces available swagger:model InfoOKBodyWorkspacesAvailable diff --git a/cmd/info.go b/cmd/info.go index fffc6c6..63b9a0e 100644 --- a/cmd/info.go +++ b/cmd/info.go @@ -202,6 +202,16 @@ func (o *infoOptions) run(cmd *cobra.Command) error { if p.SupportedWorkflowEngines != nil { displayInfoSliceItem(cmd, p.SupportedWorkflowEngines.Title, p.SupportedWorkflowEngines.Value) } + if p.VettedContainerImagesAllowlist != nil { + displayInfoSliceItem(cmd, p.VettedContainerImagesAllowlist.Title, p.VettedContainerImagesAllowlist.Value) + } + if p.VettedContainerImagesEnabled != nil { + value := "False" + if p.VettedContainerImagesEnabled.Value { + value = "True" + } + cmd.Printf("%s: %s\n", p.VettedContainerImagesEnabled.Title, value) + } if p.WorkspacesAvailable != nil { displayInfoSliceItem(cmd, p.WorkspacesAvailable.Title, p.WorkspacesAvailable.Value) } diff --git a/cmd/info_test.go b/cmd/info_test.go index 63dc1e8..0e9bd6b 100644 --- a/cmd/info_test.go +++ b/cmd/info_test.go @@ -57,6 +57,8 @@ func TestInfo(t *testing.T) { "Users can set custom interactive session images: False", "Recommended jupyter images for interactive sessions: docker.io/jupyter/scipy-notebook:notebook-6.4.5", "List of supported workflow engines: cwl, serial, snakemake, yadage", + "List of vetted container images allowed in user workflows: docker.io/library/python:2.7-slim, docker.io/reanahub/reana-env-root6:6.18.04", + "Vetted container images required for user workflows: True", "CWL engine tool: cwltool", "CWL engine version: 3.1.20210628163208", "Yadage engine version: 0.20.1", @@ -89,6 +91,8 @@ func TestInfo(t *testing.T) { "\"interactive_sessions_custom_image_allowed\": {", "\"value\": \"False\"", "\"interactive_session_recommended_jupyter_images\": {", "\"value\": [", "\"docker.io/jupyter/scipy-notebook:notebook-6.4.5\"", "\"supported_workflow_engines\": {", "\"value\": [", "\"cwl\",", "\"serial\",", "\"snakemake\",", "\"yadage\"", + "\"vetted_container_images_allowlist\": {", "\"docker.io/library/python:2.7-slim\"", + "\"vetted_container_images_enabled\": {", "\"value\": true", "\"cwl_engine_tool\": {", "\"value\": \"cwltool\"", "\"cwl_engine_version\": {", "\"value\": \"3.1.20210628163208\"", "\"yadage_engine_version\": {", "\"value\": \"0.20.1\"", diff --git a/go.mod b/go.mod index 7dbf9c4..fe6e4ba 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module reanahub/reana-client-go -go 1.25.10 +go 1.25.11 require ( github.com/go-gota/gota v0.12.0 diff --git a/testdata/inputs/info_big.json b/testdata/inputs/info_big.json index 47aaed8..89c4ea1 100644 --- a/testdata/inputs/info_big.json +++ b/testdata/inputs/info_big.json @@ -106,5 +106,16 @@ "dask_enabled": { "title": "Dask workflows allowed in the cluster", "value": "False" + }, + "vetted_container_images_allowlist": { + "title": "List of vetted container images allowed in user workflows", + "value": [ + "docker.io/library/python:2.7-slim", + "docker.io/reanahub/reana-env-root6:6.18.04" + ] + }, + "vetted_container_images_enabled": { + "title": "Vetted container images required for user workflows", + "value": true } }