-
Notifications
You must be signed in to change notification settings - Fork 0
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 #1 from DEXPRO-Solutions-GmbH/feat/base-client
Add initial StoreClient implementation including test setup
- Loading branch information
Showing
11 changed files
with
310 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: Build | ||
|
||
on: | ||
push: | ||
branches: [ "master" ] | ||
pull_request: | ||
branches: [ "master" ] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
|
||
- name: Set up Go | ||
uses: actions/setup-go@v3 | ||
with: | ||
go-version: 1.21 | ||
|
||
- name: Build | ||
run: go build -v ./... | ||
|
||
- name: Install Test Runner | ||
run: go install github.com/mfridman/tparse@latest | ||
- name: Test | ||
run: set -o pipefail && go test -json -v ./... | tparse -all | ||
|
||
- name: Lint | ||
run: go vet -v ./... |
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 |
---|---|---|
@@ -1 +1,2 @@ | ||
.idea | ||
.env |
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,16 @@ | ||
module github.com/DEXPRO-Solutions-GmbH/easclient | ||
|
||
go 1.21.4 | ||
|
||
require ( | ||
github.com/joho/godotenv v1.5.1 | ||
github.com/stretchr/testify v1.8.4 | ||
gopkg.in/resty.v1 v1.12.0 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
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,16 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis= | ||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= | ||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
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,72 @@ | ||
package easclient | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
) | ||
|
||
type StoreStatus struct { | ||
Registry struct { | ||
AllRecords int `json:"allRecords"` | ||
IndexedRecords int `json:"indexedRecords"` | ||
AllAttachments int `json:"allAttachments"` | ||
IndexedAttachments int `json:"indexedAttachments"` | ||
} `json:"registry"` | ||
Index struct { | ||
Documents int `json:"documents"` | ||
IsCurrent bool `json:"isCurrent"` | ||
HasDeletions bool `json:"hasDeletions"` | ||
Records int `json:"records"` | ||
Attachments int `json:"attachments"` | ||
} `json:"index"` | ||
Capacity struct { | ||
Maximum int64 `json:"maximum"` | ||
Utilized float64 `json:"utilized"` | ||
GrowthRate float64 `json:"growthRate"` | ||
ExpectedEnd time.Time `json:"expectedEnd"` | ||
Lifetime int `json:"lifetime"` | ||
} `json:"capacity"` | ||
Periods []struct { | ||
Start string `json:"start"` | ||
End string `json:"end"` | ||
Registry struct { | ||
AllRecords int `json:"allRecords"` | ||
IndexedRecords int `json:"indexedRecords"` | ||
AllAttachments int `json:"allAttachments"` | ||
IndexedAttachments int `json:"indexedAttachments"` | ||
} `json:"registry"` | ||
Index struct { | ||
Records int `json:"records"` | ||
Attachments int `json:"attachments"` | ||
} `json:"index"` | ||
Capacity struct { | ||
Utilized float64 `json:"utilized"` | ||
} `json:"capacity"` | ||
} `json:"periods"` | ||
} | ||
|
||
func (c *StoreClient) GetStoreStatus(ctx context.Context) (*StoreStatus, error) { | ||
req, err := c.newRequest(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
type Res struct { | ||
Status *StoreStatus `json:"status"` | ||
} | ||
|
||
var result Res | ||
|
||
req.SetResult(&result) | ||
res, err := req.Get("/status") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if status := res.StatusCode(); status != 200 { | ||
return nil, fmt.Errorf("unexpected response status %v", status) | ||
} | ||
|
||
return result.Status, 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,21 @@ | ||
package easclient_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/DEXPRO-Solutions-GmbH/easclient" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestStoreClient_GetStoreStatus(t *testing.T) { | ||
testPrelude(t) | ||
|
||
ctx := context.Background() | ||
user := easclient.NewUserClaims("[email protected]") | ||
ctx = user.SetOnContext(ctx) | ||
|
||
status, err := DefaultClient.GetStoreStatus(ctx) | ||
require.NoError(t, err) | ||
require.NotNil(t, status) | ||
} |
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,30 @@ | ||
package easclient | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"gopkg.in/resty.v1" | ||
) | ||
|
||
type StoreClient struct { | ||
c *resty.Client | ||
} | ||
|
||
func NewStoreClient(c *resty.Client) *StoreClient { | ||
return &StoreClient{c: c} | ||
} | ||
|
||
func (c *StoreClient) newRequest(ctx context.Context) (*resty.Request, error) { | ||
claims := UserClaimsFromContext(ctx) | ||
if claims == nil { | ||
return nil, errors.New("missing user claims in context object") | ||
} | ||
|
||
req := c.c.NewRequest() | ||
req.SetContext(ctx) | ||
req.SetHeader("Accept", "application/json") | ||
claims.SetOnHeader(req.Header) | ||
|
||
return req, 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,36 @@ | ||
package easclient_test | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"testing" | ||
|
||
"github.com/DEXPRO-Solutions-GmbH/easclient" | ||
"github.com/joho/godotenv" | ||
"gopkg.in/resty.v1" | ||
) | ||
|
||
var DefaultClient *easclient.StoreClient | ||
|
||
// init is run before any tests are executed. | ||
// it loads the environment variables from .env and creates | ||
// a default client for all tests to use. | ||
func init() { | ||
err := godotenv.Load(".env") | ||
if errors.Is(err, os.ErrNotExist) { | ||
return | ||
} | ||
|
||
client := resty.New() | ||
client.SetHostURL(fmt.Sprintf("http://%s/eas/archives/%s", os.Getenv("EAS_HOST"), os.Getenv("EAS_STORE"))) | ||
client.SetBasicAuth(os.Getenv("EAS_USER"), os.Getenv("EAS_PASSWORD")) | ||
|
||
DefaultClient = easclient.NewStoreClient(client) | ||
} | ||
|
||
func testPrelude(t *testing.T) { | ||
if os.Getenv("GITHUB_ACTION") != "" { | ||
t.Skip("Tests can't currently be run in the GitHub Action environment. We will first have to make it possible to run the EAS or a mocked variant in CI") | ||
} | ||
} |
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,23 @@ | ||
package easclient | ||
|
||
// User is a custom type to represent one of the four EAS user instances. | ||
type User string | ||
|
||
const ( | ||
// UserAdmin is the administrator which most permissions. | ||
UserAdmin User = "eas_administrator" | ||
// UserKeeper is responsible for auditing, moderating, etc. | ||
UserKeeper User = "eas_keeper" | ||
// UserUser is the default user being able to read and write. | ||
UserUser User = "eas_user" | ||
// UserGuest is a guest user. | ||
UserGuest User = "eas_guest" | ||
) | ||
|
||
type RequestHeader string | ||
|
||
const ( | ||
HeaderUser RequestHeader = "x-otris-eas-user" | ||
HeaderUserFullname RequestHeader = "x-otris-eas-user-fullname" | ||
HeaderTokens RequestHeader = "x-otris-eas-tokens" | ||
) |
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,59 @@ | ||
package easclient | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
// UserClaims aggregates all claims that are scoped to an EAS archive user. | ||
type UserClaims struct { | ||
// UserId - Technischer Identifikator des Nutzers, der im Host-System die Anfrage ausgelöst hat. | ||
UserId string `json:"user,omitempty"` | ||
|
||
// UserFullname - Optionaler, vollständiger Name des Nutzers, der im Host-System die Anfrage ausgelöst hat | ||
UserFullname string `json:"user_fullname,omitempty"` | ||
|
||
// Tokens - Securitytokens (Gruppenzugehörigkeit) -getrennt durch Kommata- des Nutzers, der im Host-System den Request | ||
// ausgelöst hat. | ||
Tokens []string `json:"tokens,omitempty"` | ||
} | ||
|
||
func NewUserClaims(userId string) *UserClaims { | ||
return &UserClaims{UserId: userId, Tokens: []string{}} | ||
} | ||
|
||
// SetOnHeader sets all possible eas.RequestHeader based on this UserClaims | ||
func (claims *UserClaims) SetOnHeader(header http.Header) { | ||
header.Set(string(HeaderUser), claims.UserId) | ||
|
||
// Set optional fullname | ||
if claims.UserFullname != "" { | ||
header.Set(string(HeaderUserFullname), claims.UserFullname) | ||
} | ||
|
||
// Set optional tokens | ||
if len(claims.Tokens) > 0 { | ||
header.Set(string(HeaderTokens), strings.Join(claims.Tokens, ",")) | ||
} else { | ||
header.Set(string(HeaderTokens), "") | ||
} | ||
} | ||
|
||
const UserClaimsKey = "easclient-user-claims-key" | ||
|
||
func (claims *UserClaims) SetOnContext(ctx context.Context) context.Context { | ||
return context.WithValue(ctx, UserClaimsKey, claims) | ||
} | ||
|
||
func UserClaimsFromContext(ctx context.Context) *UserClaims { | ||
if ctx == nil { | ||
return nil | ||
} | ||
|
||
if claims, ok := ctx.Value(UserClaimsKey).(*UserClaims); ok { | ||
return claims | ||
} | ||
|
||
return nil | ||
} |