-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1026 from neicnordic/feature/sda-admin-cli
sda-admin cli
- Loading branch information
Showing
15 changed files
with
1,254 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,4 +52,27 @@ jobs: | |
uses: golangci/[email protected] | ||
with: | ||
args: -E bodyclose,gocritic,gofmt,gosec,govet,nestif,nlreturn,rowserrcheck -e G401,G501,G107,G115 --timeout 5m | ||
working-directory: sda | ||
working-directory: sda | ||
|
||
lint_sda_admin: | ||
name: Lint sda-admin code | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
go-version: ['1.22'] | ||
steps: | ||
- name: Set up Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
id: go | ||
|
||
- name: Check out code into the Go module directory | ||
uses: actions/checkout@v4 | ||
|
||
- name: Run golangci-lint | ||
uses: golangci/[email protected] | ||
with: | ||
args: -E bodyclose,gocritic,gofmt,gosec,govet,nestif,nlreturn,rowserrcheck -e G401,G501,G107,G115 --timeout 5m | ||
working-directory: sda-admin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,7 @@ jobs: | |
|
||
- name: Get dependencies | ||
run: | | ||
cd sda-download | ||
cd sda | ||
go get -v -t -d ./... | ||
if [ -f Gopkg.toml ]; then | ||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh | ||
|
@@ -104,3 +104,41 @@ jobs: | |
file: ./sda/coverage.txt | ||
flags: unittests | ||
fail_ci_if_error: false | ||
|
||
test_sda_admin: | ||
name: Test SDA Admin | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
go-version: ['1.22'] | ||
steps: | ||
|
||
- name: Set up Go ${{ matrix.go-version }} | ||
uses: actions/setup-go@v5 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
id: go | ||
|
||
- name: Check out code into the Go module directory | ||
uses: actions/checkout@v4 | ||
|
||
- name: Get dependencies | ||
run: | | ||
cd sda-admin | ||
go get -v -t -d ./... | ||
if [ -f Gopkg.toml ]; then | ||
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh | ||
dep ensure | ||
fi | ||
- name: Test | ||
run: | | ||
cd sda-admin | ||
go test -v -coverprofile=coverage.txt -covermode=atomic ./... | ||
- name: Codecov | ||
uses: codecov/[email protected] | ||
with: | ||
token: ${{ secrets.CODECOV_TOKEN }} | ||
file: ./sda-admin/coverage.txt | ||
flags: unittests | ||
fail_ci_if_error: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# sda-admin | ||
|
||
`sda-admin` is a command-line tool for managing sensitive data archives. It provides functionalities to list users and files, ingest and set accession IDs for files, and create or release datasets. | ||
|
||
## General Usage | ||
|
||
```sh | ||
sda-admin [-uri URI] [-token TOKEN] <command> [options] | ||
``` | ||
|
||
## Global Options | ||
- `-uri URI` | ||
Set the URI for the API server (optional if the environmental variable `API_HOST` is set). | ||
- `-token TOKEN` | ||
Set the authentication token (optional if the environmental variable `ACCESS_TOKEN` is set). | ||
|
||
## List all users | ||
|
||
Use the following command to return all users with active uploads | ||
```sh | ||
sda-admin user list | ||
``` | ||
|
||
## List all files for a specified user | ||
|
||
Use the following command to return all files belonging to the specified user `[email protected]` | ||
```sh | ||
sda-admin file list -user [email protected] | ||
``` | ||
|
||
## Ingest a file | ||
|
||
Use the following command to trigger the ingesting of a given file `/path/to/file.c4gh` that belongs to the user `[email protected]` | ||
|
||
```sh | ||
sda-admin file ingest -filepath /path/to/file.c4gh -user [email protected] | ||
``` | ||
|
||
## Assign an accession ID to a file | ||
|
||
Use the following command to assign an accession ID `my-accession-id-1` to a given file `/path/to/file.c4gh` that belongs to the user `[email protected]` | ||
|
||
```sh | ||
sda-admin file set-accession -filepath /path/to/file.c4gh -user [email protected] -accession-id my-accession-id-1 | ||
``` | ||
|
||
## Create a dataset from a list of accession IDs and a dataset ID | ||
|
||
Use the following command to create a dataset `dataset001` from accession IDs `my-accession-id-1` and `my-accession-id-2` | ||
|
||
```sh | ||
sda-admin dataset create -dataset-id dataset001 my-accession-id-1 my-accession-id-2 | ||
``` | ||
|
||
|
||
## Release a dataset for downloading | ||
|
||
Use the following command to release the dataset `dataset001` for downloading | ||
|
||
```sh | ||
sda-admin dataset release -dataset-id dataset001 | ||
``` | ||
|
||
## Show version information | ||
|
||
Use the following command to show the version information for sda-admin. | ||
|
||
```sh | ||
sda-admin version | ||
``` | ||
|
||
## Help | ||
|
||
For detailed usage information about specific commands or options, use: | ||
|
||
```sh | ||
sda-admin help <command> | ||
``` | ||
|
||
### Examples | ||
|
||
To get help on the `file` command: | ||
```sh | ||
sda-admin help file | ||
``` | ||
|
||
To get help on the `file ingest` command: | ||
|
||
```sh | ||
sda-admin help file ingest | ||
``` | ||
|
||
To get help on the `dataset create` command: | ||
|
||
```sh | ||
sda-admin help dataset create | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package dataset | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/url" | ||
"path" | ||
|
||
"github.com/neicnordic/sensitive-data-archive/sda-admin/helpers" | ||
) | ||
|
||
type RequestBodyDataset struct { | ||
AccessionIDs []string `json:"accession_ids"` | ||
DatasetID string `json:"dataset_id"` | ||
} | ||
|
||
// Create creates a dataset from a list of accession IDs and a dataset ID. | ||
func Create(apiURI, token, datasetID string, accessionIDs []string) error { | ||
parsedURL, err := url.Parse(apiURI) | ||
if err != nil { | ||
return err | ||
} | ||
parsedURL.Path = path.Join(parsedURL.Path, "dataset/create") | ||
|
||
requestBody := RequestBodyDataset{ | ||
AccessionIDs: accessionIDs, | ||
DatasetID: datasetID, | ||
} | ||
|
||
jsonBody, err := json.Marshal(requestBody) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal JSON, reason: %v", err) | ||
} | ||
|
||
_, err = helpers.PostRequest(parsedURL.String(), token, jsonBody) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Release releases a dataset for downloading | ||
func Release(apiURI, token, datasetID string) error { | ||
parsedURL, err := url.Parse(apiURI) | ||
if err != nil { | ||
return err | ||
} | ||
parsedURL.Path = path.Join(parsedURL.Path, "dataset/release") + "/" + datasetID | ||
|
||
_, err = helpers.PostRequest(parsedURL.String(), token, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package dataset | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"github.com/neicnordic/sensitive-data-archive/sda-admin/helpers" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
) | ||
|
||
// MockHelpers is a mock implementation of the helpers package functions | ||
type MockHelpers struct { | ||
mock.Mock | ||
} | ||
|
||
func (m *MockHelpers) PostRequest(url, token string, jsonBody []byte) ([]byte, error) { | ||
args := m.Called(url, token, jsonBody) | ||
|
||
return args.Get(0).([]byte), args.Error(1) | ||
} | ||
|
||
func TestCreate_Success(t *testing.T) { | ||
mockHelpers := new(MockHelpers) | ||
originalFunc := helpers.PostRequest | ||
helpers.PostRequest = mockHelpers.PostRequest | ||
defer func() { helpers.PostRequest = originalFunc }() // Restore original after test | ||
|
||
expectedURL := "http://example.com/dataset/create" | ||
token := "test-token" | ||
datasetID := "dataset-123" | ||
accessionIDs := []string{"accession-1", "accession-2"} | ||
jsonBody := []byte(`{"accession_ids":["accession-1","accession-2"],"dataset_id":"dataset-123"}`) | ||
|
||
mockHelpers.On("PostRequest", expectedURL, token, jsonBody).Return([]byte(`{}`), nil) | ||
|
||
err := Create("http://example.com", token, datasetID, accessionIDs) | ||
assert.NoError(t, err) | ||
mockHelpers.AssertExpectations(t) | ||
} | ||
|
||
func TestCreate_PostRequestFailure(t *testing.T) { | ||
mockHelpers := new(MockHelpers) | ||
originalFunc := helpers.PostRequest | ||
helpers.PostRequest = mockHelpers.PostRequest | ||
defer func() { helpers.PostRequest = originalFunc }() // Restore original after test | ||
|
||
expectedURL := "http://example.com/dataset/create" | ||
token := "test-token" | ||
datasetID := "dataset-123" | ||
accessionIDs := []string{"accession-1", "accession-2"} | ||
jsonBody := []byte(`{"accession_ids":["accession-1","accession-2"],"dataset_id":"dataset-123"}`) | ||
|
||
mockHelpers.On("PostRequest", expectedURL, token, jsonBody).Return([]byte(nil), errors.New("failed to send request")) | ||
|
||
err := Create("http://example.com", token, datasetID, accessionIDs) | ||
assert.Error(t, err) | ||
assert.EqualError(t, err, "failed to send request") | ||
mockHelpers.AssertExpectations(t) | ||
} | ||
|
||
func TestRelease_Success(t *testing.T) { | ||
mockHelpers := new(MockHelpers) | ||
originalFunc := helpers.PostRequest | ||
helpers.PostRequest = mockHelpers.PostRequest | ||
defer func() { helpers.PostRequest = originalFunc }() // Restore original after test | ||
|
||
expectedURL := "http://example.com/dataset/release/dataset-123" | ||
token := "test-token" | ||
|
||
mockHelpers.On("PostRequest", expectedURL, token, []byte(nil)).Return([]byte(`{}`), nil) | ||
|
||
err := Release("http://example.com", token, "dataset-123") | ||
assert.NoError(t, err) | ||
mockHelpers.AssertExpectations(t) | ||
} | ||
|
||
func TestRelease_PostRequestFailure(t *testing.T) { | ||
mockHelpers := new(MockHelpers) | ||
originalFunc := helpers.PostRequest | ||
helpers.PostRequest = mockHelpers.PostRequest | ||
defer func() { helpers.PostRequest = originalFunc }() // Restore original after test | ||
|
||
expectedURL := "http://example.com/dataset/release/dataset-123" | ||
token := "test-token" | ||
|
||
mockHelpers.On("PostRequest", expectedURL, token, []byte(nil)).Return([]byte(nil), errors.New("failed to send request")) | ||
|
||
err := Release("http://example.com", token, "dataset-123") | ||
assert.Error(t, err) | ||
assert.EqualError(t, err, "failed to send request") | ||
mockHelpers.AssertExpectations(t) | ||
} |
Oops, something went wrong.