diff --git a/README.md b/README.md
index d4e5493..e6d78a6 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,45 @@
`aicura` is a client library for [Sonatype Nexus Manager v3 API](https://help.sonatype.com/repomanager3/rest-and-integration-api) written in GoLang.
+## How to Use
+
+The most straightforward way to use this library is creating a new [`Client`](https://github.com/m88i/aicura/blob/master/nexus/client.go) and make calls to the API through services:
+
+```go
+import "github.com/m88i/aicura/nexus"
+
+(...)
+
+// New client with default credentials
+client := nexus.NewClient("http://localhost:8081").WithCredentials("admin", "admin123").Build()
+user, err := client.UserService.GetUserByID("admin")
+if err != nil {
+ return err
+}
+print(user.Name)
+```
+
+### Fake Client
+
+To use this library in your unit tests, create an instance of a "fake" `Client` instead:
+
+```go
+import "github.com/m88i/aicura/nexus"
+
+(...)
+
+client := nexus.NewFakeClient()
+
+// all interfaces remain the same
+user, err := client.UserService.GetUserByID("admin")
+if err != nil {
+ return err
+}
+print(user.Name) //will print nothing since there's no user in the cache, call client.UserService.Add(user) first :)
+```
+
+The fake `Client` is backed up by hash maps, so all write and read operations will work like in real scenarios.
+
## Development
To run a local Nexus Server 3.x container with Podman:
diff --git a/nexus/client.go b/nexus/client.go
index bf6c30e..de55fa9 100644
--- a/nexus/client.go
+++ b/nexus/client.go
@@ -51,9 +51,9 @@ type Client struct {
shared service // same instance shared among all services
logger *zap.SugaredLogger
- UserService *UserService
- MavenProxyRepositoryService *MavenProxyRepositoryService
- MavenGroupRepositoryService *MavenGroupRepositoryService
+ UserService UserService
+ MavenProxyRepositoryService MavenProxyRepositoryService
+ MavenGroupRepositoryService MavenGroupRepositoryService
mavenRepositoryService *mavenRepositoryService
}
@@ -112,14 +112,24 @@ func NewClient(baseURL string) *ClientBuilder {
c.shared.client = c
// services builder
- c.UserService = (*UserService)(&c.shared)
- c.MavenProxyRepositoryService = (*MavenProxyRepositoryService)(&c.shared)
- c.MavenGroupRepositoryService = (*MavenGroupRepositoryService)(&c.shared)
+ c.UserService = (*userService)(&c.shared)
+ c.MavenProxyRepositoryService = (*mavenProxyRepositoryService)(&c.shared)
+ c.MavenGroupRepositoryService = (*mavenGroupRepositoryService)(&c.shared)
c.mavenRepositoryService = (*mavenRepositoryService)(&c.shared)
return &ClientBuilder{c}
}
+// NewFakeClient creates a mocked client for testing purposes.
+// It's backed up by hashmaps, so if you insert a user for instance, you can list, update, or delete
+func NewFakeClient() *Client {
+ c := &Client{}
+ c.UserService = &userFakeService{}
+ c.MavenGroupRepositoryService = &mvnGroupFakeService{}
+ c.MavenProxyRepositoryService = &mvnProxyFakeService{}
+ return c
+}
+
// NewDefaultClient creates a new raw, straight forward Nexus Client. For a more customizable client, use `NewClient` instead
func NewDefaultClient(baseURL string) *Client {
return NewClient(baseURL).Build()
diff --git a/nexus/repositories_maven_group.go b/nexus/repositories_maven_group.go
index 1c63c43..0b0b3a9 100644
--- a/nexus/repositories_maven_group.go
+++ b/nexus/repositories_maven_group.go
@@ -20,10 +20,16 @@ package nexus
import "fmt"
// MavenGroupRepositoryService service to handle all Maven Proxy Repositories operations
-type MavenGroupRepositoryService service
+type MavenGroupRepositoryService interface {
+ Update(repo MavenGroupRepository) error
+ List() ([]MavenGroupRepository, error)
+ GetRepoByName(name string) (*MavenGroupRepository, error)
+}
+
+type mavenGroupRepositoryService service
// Update updates a given Maven Group repository
-func (m *MavenGroupRepositoryService) Update(repo MavenGroupRepository) error {
+func (m *mavenGroupRepositoryService) Update(repo MavenGroupRepository) error {
req, err := m.client.put(m.client.appendVersion(fmt.Sprintf("/repositories/maven/group/%s", repo.Name)), "", repo)
if err != nil {
return err
@@ -33,14 +39,14 @@ func (m *MavenGroupRepositoryService) Update(repo MavenGroupRepository) error {
}
// List lists all maven repositories from the Nexus Server
-func (m *MavenGroupRepositoryService) List() ([]MavenGroupRepository, error) {
+func (m *mavenGroupRepositoryService) List() ([]MavenGroupRepository, error) {
repositories := []MavenGroupRepository{}
err := m.client.mavenRepositoryService.list(RepositoryTypeGroup, &repositories)
return repositories, err
}
// GetRepoByName gets the repository by name or nil if not found
-func (m *MavenGroupRepositoryService) GetRepoByName(name string) (*MavenGroupRepository, error) {
+func (m *mavenGroupRepositoryService) GetRepoByName(name string) (*MavenGroupRepository, error) {
repos, err := m.List()
if err != nil {
return nil, err
diff --git a/nexus/repositories_maven_group_fake.go b/nexus/repositories_maven_group_fake.go
new file mode 100644
index 0000000..9cfe31c
--- /dev/null
+++ b/nexus/repositories_maven_group_fake.go
@@ -0,0 +1,42 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+type mvnGroupFakeService struct{}
+
+var mvnGrpFake = make(map[string]*MavenGroupRepository)
+
+func (m *mvnGroupFakeService) Update(repo MavenGroupRepository) error {
+ if mvnGrpFake[repo.Name] == nil {
+ return nil
+ }
+ mvnGrpFake[repo.Name] = &repo
+ return nil
+}
+
+func (m *mvnGroupFakeService) List() ([]MavenGroupRepository, error) {
+ repos := make([]MavenGroupRepository, 0)
+ for _, repo := range mvnGrpFake {
+ repos = append(repos, *repo)
+ }
+ return repos, nil
+}
+
+func (m *mvnGroupFakeService) GetRepoByName(name string) (*MavenGroupRepository, error) {
+ return mvnGrpFake[name], nil
+}
diff --git a/nexus/repositories_maven_group_fake_test.go b/nexus/repositories_maven_group_fake_test.go
new file mode 100644
index 0000000..6fc087c
--- /dev/null
+++ b/nexus/repositories_maven_group_fake_test.go
@@ -0,0 +1,41 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestMvnGroupServiceFakeCheck(t *testing.T) {
+ client := NewFakeClient()
+ repos, err := client.MavenGroupRepositoryService.List()
+ assert.NoError(t, err)
+ assert.Empty(t, repos)
+ group := MavenGroupRepository{
+ Repository: Repository{
+ Name: "maven-public",
+ },
+ }
+ err = client.MavenGroupRepositoryService.Update(group)
+ assert.NoError(t, err)
+ newGroup, err := client.MavenGroupRepositoryService.GetRepoByName("maven-public")
+ assert.NoError(t, err)
+ assert.Nil(t, newGroup)
+}
diff --git a/nexus/repositories_maven_group_test.go b/nexus/repositories_maven_group_test.go
index dd3b425..0958fc3 100644
--- a/nexus/repositories_maven_group_test.go
+++ b/nexus/repositories_maven_group_test.go
@@ -33,11 +33,12 @@ func TestMavenGroupRepositoryService_Update(t *testing.T) {
if len(repos) > 0 { //sanity check to not panic
s = newServerWrapper(t).Build()
- apacheMavenRepoMockData.Name = apacheMavenRepoMockData.Name + "3"
- err := s.Client().MavenProxyRepositoryService.Add(apacheMavenRepoMockData)
+ repo := apacheMavenRepoMockData
+ repo.Name = repo.Name + "3"
+ err := s.Client().MavenProxyRepositoryService.Add(repo)
assert.NoError(t, err)
- repos[0].Group.MemberNames = append(repos[0].Group.MemberNames, apacheMavenRepoMockData.Name)
+ repos[0].Group.MemberNames = append(repos[0].Group.MemberNames, repo.Name)
err = s.Client().MavenGroupRepositoryService.Update(repos[0])
assert.NoError(t, err)
}
diff --git a/nexus/repositories_maven_proxy.go b/nexus/repositories_maven_proxy.go
index b9e9ebd..9435d42 100644
--- a/nexus/repositories_maven_proxy.go
+++ b/nexus/repositories_maven_proxy.go
@@ -24,10 +24,16 @@ import (
)
// MavenProxyRepositoryService service to handle all Maven Proxy Repositories operations
-type MavenProxyRepositoryService service
+type MavenProxyRepositoryService interface {
+ Add(repositories ...MavenProxyRepository) error
+ List() ([]MavenProxyRepository, error)
+ GetRepoByName(name string) (*MavenProxyRepository, error)
+}
+
+type mavenProxyRepositoryService service
// Add adds new Proxy Maven repositories to the Nexus Server
-func (m *MavenProxyRepositoryService) Add(repositories ...MavenProxyRepository) error {
+func (m *mavenProxyRepositoryService) Add(repositories ...MavenProxyRepository) error {
if len(repositories) == 0 {
m.logger.Warnf("Called AddRepository with no repositories to add")
return nil
@@ -47,14 +53,14 @@ func (m *MavenProxyRepositoryService) Add(repositories ...MavenProxyRepository)
}
// List lists all maven repositories from the Nexus Server
-func (m *MavenProxyRepositoryService) List() ([]MavenProxyRepository, error) {
+func (m *mavenProxyRepositoryService) List() ([]MavenProxyRepository, error) {
repositories := []MavenProxyRepository{}
err := m.client.mavenRepositoryService.list(RepositoryTypeProxy, &repositories)
return repositories, err
}
// GetRepoByName gets the repository by name or nil if not found
-func (m *MavenProxyRepositoryService) GetRepoByName(name string) (*MavenProxyRepository, error) {
+func (m *mavenProxyRepositoryService) GetRepoByName(name string) (*MavenProxyRepository, error) {
repos, err := m.List()
if err != nil {
return nil, err
diff --git a/nexus/repositories_maven_proxy_fake.go b/nexus/repositories_maven_proxy_fake.go
new file mode 100644
index 0000000..94b4f45
--- /dev/null
+++ b/nexus/repositories_maven_proxy_fake.go
@@ -0,0 +1,41 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+type mvnProxyFakeService struct{}
+
+var mvnProxyFake = make(map[string]*MavenProxyRepository)
+
+func (m *mvnProxyFakeService) Add(repositories ...MavenProxyRepository) error {
+ for _, repo := range repositories {
+ mvnProxyFake[repo.Name] = &repo
+ }
+ return nil
+}
+
+func (m *mvnProxyFakeService) List() ([]MavenProxyRepository, error) {
+ repos := make([]MavenProxyRepository, 0)
+ for _, repo := range mvnProxyFake {
+ repos = append(repos, *repo)
+ }
+ return repos, nil
+}
+
+func (m *mvnProxyFakeService) GetRepoByName(name string) (*MavenProxyRepository, error) {
+ return mvnProxyFake[name], nil
+}
diff --git a/nexus/repositories_maven_proxy_fake_test.go b/nexus/repositories_maven_proxy_fake_test.go
new file mode 100644
index 0000000..c3e3ab1
--- /dev/null
+++ b/nexus/repositories_maven_proxy_fake_test.go
@@ -0,0 +1,38 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestMvnProxyServiceFakeCheck(t *testing.T) {
+ client := NewFakeClient()
+ repo := apacheMavenRepoMockData
+ err := client.MavenProxyRepositoryService.Add(repo)
+ assert.NoError(t, err)
+ newRepo, err := client.MavenProxyRepositoryService.GetRepoByName(repo.Name)
+ assert.NoError(t, err)
+ assert.NotNil(t, newRepo)
+ assert.Equal(t, "apache", newRepo.Name)
+ repos, err := client.MavenProxyRepositoryService.List()
+ assert.NoError(t, err)
+ assert.Len(t, repos, 1)
+}
diff --git a/nexus/repositories_maven_proxy_test.go b/nexus/repositories_maven_proxy_test.go
index ebe1945..2669265 100644
--- a/nexus/repositories_maven_proxy_test.go
+++ b/nexus/repositories_maven_proxy_test.go
@@ -51,15 +51,16 @@ func TestMavenProxyRepositoryService_Add(t *testing.T) {
s := newServerWrapper(t).Build()
defer s.teardown()
client := s.Client()
- apacheMavenRepoMockData.Name = apacheMavenRepoMockData.Name + "2"
- err := client.MavenProxyRepositoryService.Add(apacheMavenRepoMockData)
+ newRepo := apacheMavenRepoMockData
+ newRepo.Name = newRepo.Name + "2"
+ err := client.MavenProxyRepositoryService.Add(newRepo)
assert.NoError(t, err)
assertRemote(t, func() error {
// on remote testing we can check if the repository was correctly inserted
repos, err := client.MavenProxyRepositoryService.List()
assert.NotEmpty(t, repos)
for _, repo := range repos {
- if repo.Name == apacheMavenRepoMockData.Name {
+ if repo.Name == newRepo.Name {
assert.Equal(t, "https://repo.maven.apache.org/maven2/", repo.Proxy.RemoteURL)
return err
}
diff --git a/nexus/users.go b/nexus/users.go
index cd1a2d7..b023eb7 100644
--- a/nexus/users.go
+++ b/nexus/users.go
@@ -37,10 +37,17 @@ type User struct {
}
// UserService contains all operations related to the User domain
-type UserService service
+type UserService interface {
+ List() ([]User, error)
+ Update(user User) error
+ GetUserByID(userID string) (*User, error)
+ Add(user User) error
+}
+
+type userService service
// List Retrieves all users from default source
-func (u *UserService) List() ([]User, error) {
+func (u *userService) List() ([]User, error) {
req, err := u.client.get(u.client.appendVersion("/security/users"), "")
if err != nil {
return nil, err
@@ -51,7 +58,7 @@ func (u *UserService) List() ([]User, error) {
}
// Update persists a new version of an existing user on the Nexus server
-func (u *UserService) Update(user User) error {
+func (u *userService) Update(user User) error {
req, err := u.client.put(u.client.appendVersion(fmt.Sprintf("/security/users/%s", user.UserID)), "", user)
if err != nil {
return err
@@ -61,7 +68,7 @@ func (u *UserService) Update(user User) error {
}
// GetUserByID Gets the user by it's id (authentication username)
-func (u *UserService) GetUserByID(userID string) (*User, error) {
+func (u *userService) GetUserByID(userID string) (*User, error) {
parsedURL, err := url.ParseQuery("userId=" + userID)
if err != nil {
return nil, err
@@ -79,7 +86,7 @@ func (u *UserService) GetUserByID(userID string) (*User, error) {
}
// Add adds a new user in the Nexus Server. It's worth calling `GetUserByID` to verify if the desired user is not present.
-func (u *UserService) Add(user User) error {
+func (u *userService) Add(user User) error {
req, err := u.client.post(u.client.appendVersion("/security/users"), "", user)
if err != nil {
return err
diff --git a/nexus/users_fake.go b/nexus/users_fake.go
new file mode 100644
index 0000000..e174652
--- /dev/null
+++ b/nexus/users_fake.go
@@ -0,0 +1,47 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+type userFakeService struct{}
+
+var usersFake = make(map[string]*User)
+
+func (u *userFakeService) List() ([]User, error) {
+ users := make([]User, 0)
+ for _, user := range usersFake {
+ users = append(users, *user)
+ }
+ return users, nil
+}
+
+func (u *userFakeService) Update(user User) error {
+ if usersFake[user.UserID] == nil {
+ return nil
+ }
+ usersFake[user.UserID] = &user
+ return nil
+}
+
+func (u *userFakeService) GetUserByID(userID string) (*User, error) {
+ return usersFake[userID], nil
+}
+
+func (u *userFakeService) Add(user User) error {
+ usersFake[user.UserID] = &user
+ return nil
+}
diff --git a/nexus/users_fake_test.go b/nexus/users_fake_test.go
new file mode 100644
index 0000000..61bb587
--- /dev/null
+++ b/nexus/users_fake_test.go
@@ -0,0 +1,40 @@
+// Copyright 2020 Aicura Nexus Client and/or its authors
+//
+// This file is part of Aicura Nexus Client.
+//
+// Aicura Nexus Client is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Aicura Nexus Client is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with Aicura Nexus Client. If not, see .
+
+package nexus
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestUserFakeCheck(t *testing.T) {
+ user := defaultUser
+ client := NewFakeClient()
+ err := client.UserService.Add(user)
+ assert.NoError(t, err)
+ users, err := client.UserService.List()
+ assert.NoError(t, err)
+ assert.Len(t, users, 1)
+ user.Email = "user@fake.com"
+ err = client.UserService.Update(user)
+ assert.NoError(t, err)
+ newUser, err := client.UserService.GetUserByID(user.UserID)
+ assert.NoError(t, err)
+ assert.Equal(t, "user@fake.com", newUser.Email)
+}