Skip to content

Commit

Permalink
Closes #12 - Introducing fake client (#17)
Browse files Browse the repository at this point in the history
* Closes #12 - Introducing fake client 🙈

Signed-off-by: Ricardo Zanini <[email protected]>

* Add Maven Repository services fake

Signed-off-by: Ricardo Zanini <[email protected]>

* Fixing Maven proxy repo bug

Signed-off-by: Ricardo Zanini <[email protected]>

* Writing documentation

Signed-off-by: Ricardo Zanini <[email protected]>
  • Loading branch information
ricardozanini authored Jul 27, 2020
1 parent e84c204 commit 7078f9e
Show file tree
Hide file tree
Showing 13 changed files with 344 additions and 25 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 16 additions & 6 deletions nexus/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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()
Expand Down
14 changes: 10 additions & 4 deletions nexus/repositories_maven_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
42 changes: 42 additions & 0 deletions nexus/repositories_maven_group_fake.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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
}
41 changes: 41 additions & 0 deletions nexus/repositories_maven_group_fake_test.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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)
}
7 changes: 4 additions & 3 deletions nexus/repositories_maven_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
14 changes: 10 additions & 4 deletions nexus/repositories_maven_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
41 changes: 41 additions & 0 deletions nexus/repositories_maven_proxy_fake.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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
}
38 changes: 38 additions & 0 deletions nexus/repositories_maven_proxy_fake_test.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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)
}
7 changes: 4 additions & 3 deletions nexus/repositories_maven_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Loading

0 comments on commit 7078f9e

Please sign in to comment.