Skip to content

Commit

Permalink
#6 unified project setup, added graphql project, added repositories a…
Browse files Browse the repository at this point in the history
…nd tags endpoint
  • Loading branch information
whymatter committed May 7, 2020
1 parent 274910b commit 296236d
Show file tree
Hide file tree
Showing 36 changed files with 803 additions and 123 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions cmd/harbour-gateway/app/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package app

import (
server "github.com/harbourrocks/harbour/pkg/harbourgateway"
"github.com/harbourrocks/harbour/pkg/harbourgateway/configuration"
"github.com/harbourrocks/harbour/pkg/logconfig"
"github.com/harbourrocks/harbour/pkg/redisconfig"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// NewGatewayServerCommand creates a *cobra.Command object with default parameters
func NewGatewayServerCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "harbour-gateway",
Long: `The harbour.rocks Gateway server manages
all incoming http requests.`,
RunE: func(cmd *cobra.Command, args []string) error {

// load OIDC config
s := configuration.ParseViperConfig()

// configure logging
l := logconfig.ParseViperConfig()
logconfig.ConfigureLog(l)

logrus.Info("Harbour Gateway configured")

// test redis connection
redisconfig.TestConnection(s.Redis)

return server.RunGatewayServer(s)
},
}

return cmd
}

func init() {
cobra.OnInitialize(initCobra)
}

func initCobra() {
viper.AutomaticEnv()
}
15 changes: 15 additions & 0 deletions cmd/harbour-gateway/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package main

import (
"os"

"github.com/harbourrocks/harbour/cmd/harbour-gateway/app"
)

func main() {
cmd := app.NewGatewayServerCommand()

if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
17 changes: 17 additions & 0 deletions deployments/registry/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: '3.3'
services:
registry:
container_name: standalone-registry
image: registry:2
ports:
- 5000:5000
# environment:
# REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
# REGISTRY_HTTP_TLS_KEY: /certs/domain.key
# REGISTRY_AUTH: htpasswd
# REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
# REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
# volumes:
# - /path/data:/var/lib/registry
# - /path/certs:/certs
# - /path/auth:/auth
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ require (
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-redis/redis/v7 v7.2.0
github.com/graphql-go/graphql v0.7.9
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
github.com/sirupsen/logrus v1.2.0
github.com/spf13/cobra v0.0.7
github.com/spf13/viper v1.4.0
github.com/stretchr/testify v1.5.1 // indirect
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
gopkg.in/square/go-jose.v2 v2.4.1 // indirect
)
6 changes: 5 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U=
github.com/go-redis/redis/v7 v7.2.0 h1:CrCexy/jYWZjW0AyVoHlcJUeZN19VWlbepTh1Vq6dJs=
github.com/go-redis/redis/v7 v7.2.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
Expand All @@ -46,11 +45,14 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/graphql-go/graphql v0.7.9 h1:5Va/Rt4l5g3YjwDnid3vFfn43faaQBq7rMcIZ0VnV34=
github.com/graphql-go/graphql v0.7.9/go.mod h1:k6yrAYQaSP59DC5UVxbgxESlmVyojThKdORUqGDGmrI=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
Expand Down Expand Up @@ -179,10 +181,12 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.4.1 h1:H0TmLt7/KmzlrDOpa1F+zr0Tk90PbJYBfsVUmRLrf9Y=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
6 changes: 3 additions & 3 deletions pkg/apiclient/apiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

// Get issues a GET request against the url.
//The response is unmarshaled into response
//The response is unmarshalled into response
func Get(url string, response interface{}) (resp *http.Response, err error) {
resp, err = http.Get(url)
if err != nil {
Expand All @@ -26,8 +26,8 @@ func Get(url string, response interface{}) (resp *http.Response, err error) {

// Post issues a POST request against the url.
// The POST payload is specified by body. If body is nil then no body is sent at all.
// The response is unmarshaled into response.
func Post(url string, response interface{}, body interface{}) (resp *http.Response, err error) {
// The response is unmarshalled into response.
func Post(url string, response interface{}, _ interface{}) (resp *http.Response, err error) {
resp, err = http.Post(url, "application/json", nil)
if err != nil {
l.
Expand Down
35 changes: 35 additions & 0 deletions pkg/harbourgateway/configuration/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package configuration

import (
"github.com/harbourrocks/harbour/pkg/auth"
"github.com/harbourrocks/harbour/pkg/redisconfig"
"github.com/harbourrocks/harbour/pkg/registry"
)

// Options defines all options available to configure the Gateway server.
type Options struct {
Redis redisconfig.RedisOptions
OIDCConfig auth.OIDCConfig
DockerRegistry registry.RegistryConfig
}

// NewDefaultOptions returns the default options
func NewDefaultOptions() *Options {
s := Options{
Redis: redisconfig.NewDefaultRedisOptions(),
OIDCConfig: auth.DefaultConfig(),
}

return &s
}

// ParseViperConfig tries to map a viper configuration
func ParseViperConfig() *Options {
s := NewDefaultOptions()

s.OIDCConfig = auth.ParseViperConfig()
s.Redis = redisconfig.ParseViperConfig()
s.DockerRegistry = registry.ParseViperConfig()

return s
}
48 changes: 48 additions & 0 deletions pkg/harbourgateway/graphql/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package graphql

import (
"github.com/graphql-go/graphql"
"github.com/harbourrocks/harbour/pkg/apiclient"
"github.com/harbourrocks/harbour/pkg/harbourgateway/configuration"
"github.com/harbourrocks/harbour/pkg/harbourgateway/model"
"github.com/harbourrocks/harbour/pkg/registry/models"
)

var repositoryListType = graphql.NewList(repositoryType)
var repositoryType = graphql.NewObject(
graphql.ObjectConfig{
Name: "Repository",
Description: "All repositories of the registry.",
Fields: graphql.Fields{
"name": &graphql.Field{
Type: graphql.String,
Description: "The name of the docker registry repository. " +
"This can contain slashes",
},
},
},
)

func RepositoriesField(options configuration.Options) *graphql.Field {
return &graphql.Field{
Type: repositoryListType,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// query repositories from docker registry
var regRepositories models.Repositories
_, err := apiclient.Get(options.DockerRegistry.RepositoriesURL(), &regRepositories)
if err != nil {
return nil, err
}

// map docker registry response to harbour response
var response = make([]model.Repository, len(regRepositories.Repositories))
for i, repository := range regRepositories.Repositories {
response[i] = model.Repository{
Name: repository,
}
}

return response, err
},
}
}
67 changes: 67 additions & 0 deletions pkg/harbourgateway/graphql/tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package graphql

import (
"github.com/graphql-go/graphql"
"github.com/harbourrocks/harbour/pkg/apiclient"
"github.com/harbourrocks/harbour/pkg/harbourgateway/configuration"
"github.com/harbourrocks/harbour/pkg/harbourgateway/model"
"github.com/harbourrocks/harbour/pkg/registry/models"
)

var tagListType = graphql.NewList(tagType)
var tagType = graphql.NewObject(
graphql.ObjectConfig{
Name: "Tag",
Fields: graphql.Fields{
"name": &graphql.Field{
Type: graphql.String,
Description: "The name of the tag. The tag combined with the repository " +
"is a unique identifier for an image",
},
"repository": &graphql.Field{
Type: repositoryType,
Description: "The repository of the tag.",
},
},
},
)

func TagsField(options configuration.Options) *graphql.Field {
return &graphql.Field{
Type: tagListType,
Description: "All tags of a specified repository.",
Args: graphql.FieldConfigArgument{
"repository": &graphql.ArgumentConfig{
Type: graphql.String,
Description: "Defines the repository of which the tags should be returned.",
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// parse query parameter
repositoryQuery, isOK := p.Args["repository"].(string)
if !isOK {
return nil, nil
}

// query tags of repository from docker registry
var regTags models.Tags
_, err := apiclient.Get(options.DockerRegistry.RepositoryTagsURL(repositoryQuery), &regTags)
if err != nil {
return nil, err
}

// map docker registry response to harbour response
var response = make([]model.Tag, len(regTags.Tags))
for i, repository := range regTags.Tags {
response[i] = model.Tag{
Name: repository,
Repository: model.Repository{
Name: regTags.Name,
},
}
}

return response, err
},
}
}
38 changes: 38 additions & 0 deletions pkg/harbourgateway/handler/graphqlhandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package handler

import (
"encoding/json"
"fmt"
"github.com/graphql-go/graphql"
traits2 "github.com/harbourrocks/harbour/pkg/harbourgateway/traits"
"github.com/harbourrocks/harbour/pkg/httphandler/traits"
)

func executeQuery(query string, schema graphql.Schema) *graphql.Result {
result := graphql.Do(graphql.Params{
Schema: schema,
RequestString: query,
})

if len(result.Errors) > 0 {
fmt.Printf("wrong result, unexpected errors: %v", result.Errors)
}

return result
}

// GraphQLModel is specific for one handler
type GraphQLModel struct {
traits.HttpModel
traits.IdTokenModel
traits2.GraphQLModel
}

func (h GraphQLModel) Handle() (err error) {
r := h.GetRequest()
w := h.GetResponse()
s := h.GetSchema()

result := executeQuery(r.URL.Query().Get("query"), s)
return json.NewEncoder(w).Encode(result)
}
7 changes: 7 additions & 0 deletions pkg/harbourgateway/model/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model

// Repository represents a repository on the docker registry
// A repository is identified by its name
type Repository struct {
Name string `json:"name"`
}
8 changes: 8 additions & 0 deletions pkg/harbourgateway/model/tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package model

// Tag represents a tagged image in a specific repository
// A tag is identified by its name
type Tag struct {
Name string `json:"Name"`
Repository Repository `json:"repository"`
}
Loading

0 comments on commit 296236d

Please sign in to comment.