Initial Commit

This commit is contained in:
2019-09-16 21:36:27 +02:00
commit a86462206b
17 changed files with 771 additions and 0 deletions

10
pkg/hub/errors.go Normal file
View File

@ -0,0 +1,10 @@
package hub
import "errors"
var (
errorNoUserDefined = errors.New("No User defined")
errorNoPasswordDefined = errors.New("No Password defined")
errorNoNamespaceDefined = errors.New("No Namespace defined")
errorNoRepositoryDefined = errors.New("No Repository defined")
)

179
pkg/hub/hub.go Normal file
View File

@ -0,0 +1,179 @@
package hub
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/go-flucky/flucky/pkg/logger"
"github.com/volker-raschek/dhd/pkg/types"
)
var (
dockerHubAPI = "https://hub.docker.com/v2"
flogger logger.Logger
)
func init() {
flogger = logger.NewSilentLogger()
}
func GetRepository(namespace string, name string, token *types.Token) (*types.Repository, error) {
if len(namespace) <= 0 {
return nil, errorNoNamespaceDefined
}
if len(name) <= 0 {
return nil, errorNoRepositoryDefined
}
client := new(http.Client)
url, err := url.Parse(fmt.Sprintf("%v/repositories/%v/%v", dockerHubAPI, namespace, name))
if err != nil {
return nil, fmt.Errorf("Can not prase URL: %v", err)
}
req, err := http.NewRequest(http.MethodGet, url.String(), nil)
if err != nil {
return nil, fmt.Errorf("Can not create request to get repository: %v", err)
}
if token != nil {
req.Header.Add("Authorization", fmt.Sprintf("JWT %v", token.Token))
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("An error has occured: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Invalid HTTP-Statuscode: Get %v but expect 200", resp.StatusCode)
}
repository := new(types.Repository)
jsonDecoder := json.NewDecoder(resp.Body)
if err := jsonDecoder.Decode(repository); err != nil {
return nil, fmt.Errorf("Can not encode JSON from Repository struct: %v", err)
}
return repository, nil
}
func GetToken(loginCredentials *types.LoginCredentials) (*types.Token, error) {
if len(loginCredentials.User) <= 0 {
return nil, errorNoUserDefined
}
if len(loginCredentials.Password) <= 0 {
return nil, errorNoPasswordDefined
}
client := new(http.Client)
loginBuffer := new(bytes.Buffer)
jsonEncoder := json.NewEncoder(loginBuffer)
if err := jsonEncoder.Encode(loginCredentials); err != nil {
return nil, fmt.Errorf("Can not encode JSON from LoginCredential struct: %v", err)
}
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%v/users/login/", dockerHubAPI), loginBuffer)
if err != nil {
return nil, fmt.Errorf("Can not create request to get token from %v: %v", dockerHubAPI, err)
}
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("An error has occured after sending the http request to get a JWT token from %v: %v", dockerHubAPI, err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("Invalid HTTP-Statuscode while getting the JWT Token: Get %v but expect 200", resp.StatusCode)
}
token := new(types.Token)
jsonDecoder := json.NewDecoder(resp.Body)
if err := jsonDecoder.Decode(token); err != nil {
return nil, fmt.Errorf("Can not decode token: %v", err)
}
return token, nil
}
func PatchRepository(repository *types.Repository, token *types.Token) (*types.Repository, error) {
if len(repository.Namespcace) <= 0 {
return nil, errorNoNamespaceDefined
}
if len(repository.Name) <= 0 {
return nil, errorNoRepositoryDefined
}
repositoryBuffer := new(bytes.Buffer)
jsonEncoder := json.NewEncoder(repositoryBuffer)
if err := jsonEncoder.Encode(repository); err != nil {
return nil, fmt.Errorf("Can not encode JSON from Repository struct: %v", err)
}
client := new(http.Client)
// patchURL, err := url.Parse(fmt.Sprintf("%v/repositories/%v/%v", dockerHubAPI, repository.Namespcace, repository.Name))
// if err != nil {
// return nil, fmt.Errorf("Can not prase URL: %v", err)
// }
patchURL := "https://httpbin.org/patch"
data := url.Values{}
data.Set("full_description", repository.FullDescription)
req, err := http.NewRequest(http.MethodPatch, patchURL, strings.NewReader(data.Encode()))
if err != nil {
return nil, fmt.Errorf("Can not create request to update readme: %v", err)
}
req.Header.Add("Accept", "*/*")
req.Header.Add("Authorization", fmt.Sprintf("JWT %v", token.Token))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
req.Header.Del("Accept-Encoding")
flogger.Debug("Content-Length", strconv.Itoa(len(data.Encode())))
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("An error has occured: %v", err)
}
defer resp.Body.Close()
flogger.Debug("Get Statuscode: %v", resp.StatusCode)
if resp.StatusCode == 200 {
bodyBytes, _ := ioutil.ReadAll(resp.Body)
//return nil, fmt.Errorf("Invalid HTTP-Statuscode: Get %v but expect 200: %v", resp.StatusCode, string(bodyBytes))
flogger.Debug("RESP_BODY: %v", string(bodyBytes))
}
patchedRepository := new(types.Repository)
if err := json.NewDecoder(resp.Body).Decode(patchedRepository); err != nil {
return nil, fmt.Errorf("Can not encode JSON from Repository struct: %v", err)
}
return patchedRepository, nil
}
func SetLogger(l logger.Logger) {
flogger = l
}

60
pkg/hub/hub_test.go Normal file
View File

@ -0,0 +1,60 @@
package hub_test
import (
"os"
"testing"
flogger "github.com/go-flucky/flucky/pkg/logger"
"github.com/stretchr/testify/require"
"github.com/volker-raschek/dhd/pkg/hub"
"github.com/volker-raschek/dhd/pkg/types"
)
func TestPatchRepository(t *testing.T) {
hub.SetLogger(flogger.NewDefaultLogger(flogger.LogLevelDebug))
dockerHubUser := os.Getenv("REGISTRY_USER")
if len(dockerHubUser) <= 0 {
t.Fatalf("Environment variable REGISTRY_USER is empty")
}
dockerHubPassword := os.Getenv("REGISTRY_PASSWORD")
if len(dockerHubPassword) <= 0 {
t.Fatalf("Environment variable REGISTRY_PASSWORD is empty")
}
dockerHubNamespace := os.Getenv("REGISTRY_NAMESPACE")
if len(dockerHubNamespace) <= 0 {
t.Fatalf("Environment variable REGISTRY_NAMESPACE is empty")
}
dockerHubRepository := os.Getenv("CONTAINER_IMAGE_NAME")
if len(dockerHubRepository) <= 0 {
t.Fatalf("Environment variable CONTAINER_IMAGE_NAME is empty")
}
loginCredentials := &types.LoginCredentials{
User: dockerHubUser,
Password: dockerHubPassword,
}
require := require.New(t)
token, err := hub.GetToken(loginCredentials)
require.NoError(err)
readme, err := Asset("README.md")
require.NoError(err)
currentRepository, err := hub.GetRepository(dockerHubNamespace, dockerHubRepository, token)
require.NoError(err)
expectedRepository := *currentRepository
expectedRepository.FullDescription = string(readme)
actualRepository, err := hub.PatchRepository(&expectedRepository, token)
require.NoError(err)
require.NotEqual(currentRepository, actualRepository, "The repository properties have remained the same even though an update was performed")
require.Equal(&expectedRepository, actualRepository, "The update was successfully")
}

6
pkg/types/login.go Normal file
View File

@ -0,0 +1,6 @@
package types
type LoginCredentials struct {
User string `json:"username"`
Password string `json:"password"`
}

29
pkg/types/repository.go Normal file
View File

@ -0,0 +1,29 @@
package types
import "time"
type Repository struct {
User string `json:"user"`
Name string `json:"name"`
Namespcace string `json:"namespace"`
Type string `json:"repository_type"`
Status int `json:"status"`
Description string `json:"description"`
Private bool `json:"is_private"`
Automated bool `json:"is_automated"`
Edit bool `json:"can_edit"`
StarCount int `json:"start_count"`
PullCount int `json:"pull_count"`
LastUpdated time.Time `json:"last_updated"`
IsMigrated bool `json:"is_migrated"`
HasStarred bool `json:"has_starred"`
FullDescription string `json:"full_description"`
Affiliation string `json:"affilition"`
Permissions *Permissions `json:"permissions"`
}
type Permissions struct {
Read bool `json:"read"`
Write bool `json:"write"`
Admin bool `json:"admin"`
}

6
pkg/types/token.go Normal file
View File

@ -0,0 +1,6 @@
package types
type Token struct {
Token string `json:"token"`
}