Skip to content
This repository has been archived by the owner on May 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #124 from chmouel/witng
Browse files Browse the repository at this point in the history
Check that space exists
  • Loading branch information
piyush-garg authored Nov 30, 2018
2 parents 2a6fbef + 257f963 commit d0d4e99
Show file tree
Hide file tree
Showing 14 changed files with 370 additions and 29 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ tool/
migration/sqlbindata.go
environment/generated/
auth/client
application/wit/witservice
13 changes: 12 additions & 1 deletion Gopkg.lock

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

9 changes: 9 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ required = [
"github.com/fabric8-services/fabric8-common/errors", # needed by goa generator
"github.com/fabric8-services/fabric8-common/goasupport/jsonapi_errors_helpers", # needed by goa generator
"github.com/fabric8-services/fabric8-common/goasupport/status", # needed by goa generator
"github.com/fabric8-services/fabric8-wit/design",
"github.com/goadesign/goa/cors",
"github.com/goadesign/goa/encoding/form",
"github.com/goadesign/goa/goagen",
Expand Down Expand Up @@ -57,3 +58,11 @@ ignored = [
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"

[[constraint]]
name = "gopkg.in/h2non/gock.v1"
revision = "master"

[[constraint]]
name = "github.com/fabric8-services/fabric8-wit"
revision = "b59d0dc8ae9b2bfea1fb5dc6ff3552c42b735756"
11 changes: 5 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,13 @@ AUTH_CONTAINER_NAME = auth
AUTH_CONTAINER_PORT = 8089
AUTH_CONTAINER_IMAGE = quay.io/openshiftio/fabric8-services-fabric8-auth:latest

AUTH_DB_CONTAINER_NAME = db-auth
AUTH_DB_CONTAINER_IMAGE = $(DB_CONTAINER_IMAGE)

# Env
ENV_CONTAINER_NAME = f8env
ENV_CONTAINER_PORT = 8080
ENV_CONTAINER_IMAGE = quay.io/openshiftio/fabric8-services-fabric8-env:latest

ENV_DB_CONTAINER_NAME = db-env
ENV_DB_CONTAINER_IMAGE = $(DB_CONTAINER_IMAGE)
# Wit
WIT_CONTAINER_NAME = f8wit
WIT_CONTAINER_IMAGE = quay.io/openshiftio/fabric8-services-fabric8-wit:latest

# By default reduce the amount of log output from tests, set this to debug and GO_TEST_VERBOSITY_FLAG to -v to increase it
F8_LOG_LEVEL ?= error
Expand Down Expand Up @@ -277,6 +274,7 @@ clean-generated:
-rm -rf ./app
-rm -rf ./swagger/
-rm -f ./migration/sqlbindata.go
-rm -rf application/wit/witservice

CLEAN_TARGETS += clean-vendor
.PHONY: clean-vendor
Expand Down Expand Up @@ -321,6 +319,7 @@ app/controllers.go: $(DESIGNS) $(GOAGEN_BIN) $(VENDOR_DIR)
$(GOAGEN_BIN) app -d ${PACKAGE_NAME}/${DESIGN_DIR}
$(GOAGEN_BIN) controller -d ${PACKAGE_NAME}/${DESIGN_DIR} -o controller/ --pkg controller --app-pkg ${PACKAGE_NAME}/app
$(GOAGEN_BIN) swagger -d ${PACKAGE_NAME}/${DESIGN_DIR}
$(GOAGEN_BIN) client -d github.com/fabric8-services/fabric8-wit/design --notool --pkg witservice -o application/wit
$(GOAGEN_BIN) gen -d ${PACKAGE_NAME}/${DESIGN_DIR} --pkg-path=github.com/fabric8-services/fabric8-common/goasupport/status --out app
$(GOAGEN_BIN) gen -d ${PACKAGE_NAME}/${DESIGN_DIR} \
--pkg-path=github.com/fabric8-services/fabric8-common/goasupport/jsonapi_errors_helpers --out app
Expand Down
33 changes: 33 additions & 0 deletions application/rest/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package rest

import (
"context"
"net/http"

"github.com/goadesign/goa/client"
)

// Doer is a wrapper interface for goa client Doer
type HttpDoer interface {
client.Doer
}

// HttpClient defines the Do method of the http client.
type HttpClient interface {
Do(req *http.Request) (*http.Response, error)
}

// HttpClientDoer implements HttpDoer
type HttpClientDoer struct {
HttpClient HttpClient
}

// DefaultHttpDoer creates a new HttpDoer with default http client
func DefaultHttpDoer() HttpDoer {
return &HttpClientDoer{HttpClient: http.DefaultClient}
}

// Do overrides Do method of the default goa client Doer. It's needed for mocking http clients in tests.
func (d *HttpClientDoer) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
return d.HttpClient.Do(req)
}
42 changes: 42 additions & 0 deletions application/rest/url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package rest

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
)

// AbsoluteURL prefixes a relative URL with absolute address
func AbsoluteURL(req *http.Request, relative string) string {
scheme := "http"
if req.URL != nil && req.URL.Scheme == "https" { // isHTTPS
scheme = "https"
}
xForwardProto := req.Header.Get("X-Forwarded-Proto")
if xForwardProto != "" {
scheme = xForwardProto
}
return fmt.Sprintf("%s://%s%s", scheme, req.Host, relative)
}

// AbsoluteURLAsURL returns the result of AbsoluteURL parsed into a URL
// structure and a potential parsing error.
func AbsoluteURLAsURL(req *http.Request, relative string) (*url.URL, error) {
return url.Parse(AbsoluteURL(req, relative))
}

// ReadBody reads body from a ReadCloser and returns it as a string
func ReadBody(body io.ReadCloser) string {
buf := new(bytes.Buffer)
_, _ = buf.ReadFrom(body)
return buf.String()
}

// CloseResponse reads the body and close the response. To be used to prevent file descriptor leaks.
func CloseResponse(response *http.Response) {
_, _ = ioutil.ReadAll(response.Body)
response.Body.Close()
}
26 changes: 26 additions & 0 deletions application/services.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package application

import (
"github.com/fabric8-services/fabric8-build/application/wit"
"github.com/fabric8-services/fabric8-build/configuration"
)

type ServiceFactory interface {
WITService() wit.WITService
}

type serviceFactoryImpl struct {
Config *configuration.Config
}

func (s serviceFactoryImpl) WITService() wit.WITService {
return &wit.WITServiceImpl{
Config: *s.Config,
}
}

func NewServiceFactory(config *configuration.Config) ServiceFactory {
return serviceFactoryImpl{
Config: config,
}
}
104 changes: 104 additions & 0 deletions application/wit/wit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package wit

import (
"context"
"net/http"
"net/url"

"github.com/fabric8-services/fabric8-build/application/rest"
"github.com/fabric8-services/fabric8-build/application/wit/witservice"
"github.com/fabric8-services/fabric8-build/configuration"
commonerr "github.com/fabric8-services/fabric8-common/errors"
"github.com/fabric8-services/fabric8-common/goasupport"
"github.com/pkg/errors"

"github.com/goadesign/goa/uuid"
"github.com/prometheus/common/log"
)

type Space struct {
ID uuid.UUID
OwnerID uuid.UUID
Name string
Description string
}

type WITService interface {
GetSpace(ctx context.Context, spaceID string) (space *Space, e error)
}

type WITServiceImpl struct {
Config configuration.Config
doer rest.HttpDoer
}

// GetSpace talks to the WIT service to retrieve a space record for the specified spaceID, then returns space
func (s *WITServiceImpl) GetSpace(ctx context.Context, spaceID string) (space *Space, e error) {
remoteWITService, err := s.createClientWithContextSigner(ctx)
if err != nil {
return nil, err
}

spaceIDUUID, err := uuid.FromString(spaceID)
if err != nil {
return nil, err
}

res, err := remoteWITService.ShowSpace(ctx, witservice.ShowSpacePath(spaceIDUUID), nil, nil)
if err != nil {
return nil, err
}

defer rest.CloseResponse(res)
if res.StatusCode != http.StatusOK {
bodyString := rest.ReadBody(res.Body)
log.Error(ctx, map[string]interface{}{
"spaceId": spaceID,
"response_status": res.Status,
"response_body": bodyString,
}, "unable to get space from WIT")
if res.StatusCode == 404 {
return nil, commonerr.NewNotFoundErrorFromString("Cannot find space: " + spaceID)
} else {
return nil, errors.Errorf("unable to get space from WIT. Response status: %s. Response body: %s", res.Status, bodyString)
}
}

spaceSingle, err := remoteWITService.DecodeSpaceSingle(res)
if err != nil {
return nil, err
}

return &Space{
ID: *spaceSingle.Data.ID,
Name: *spaceSingle.Data.Attributes.Name,
Description: *spaceSingle.Data.Attributes.Description,
OwnerID: *spaceSingle.Data.Relationships.OwnedBy.Data.ID}, nil
}

// createClientWithContextSigner creates with a signer based on current context
func (s *WITServiceImpl) createClientWithContextSigner(ctx context.Context) (*witservice.Client, error) {
c, err := s.createClient()
if err != nil {
return nil, err
}

c.SetJWTSigner(goasupport.NewForwardSigner(ctx))
return c, nil
}

func (s *WITServiceImpl) createClient() (*witservice.Client, error) {
witURL, e := s.Config.GetWITURL()
if e != nil {
return nil, e
}
u, err := url.Parse(witURL)
if err != nil {
return nil, err
}

c := witservice.New(s.doer)
c.Host = u.Host
c.Scheme = u.Scheme
return c, nil
}
12 changes: 10 additions & 2 deletions configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const (
varMetricsHTTPAddress = "metrics.http.address"
varSentryDSN = "sentry.dsn"

// External f8 services
varAuthURL = "auth.url"
varWITURL = "wit.url"

// Postgres
varPostgresHost = "postgres.host"
varPostgresPort = "postgres.port"
Expand All @@ -36,8 +40,6 @@ const (
varPostgresConnectionRetrySleep = "postgres.connection.retrysleep"
varPostgresConnectionMaxIdle = "postgres.connection.maxidle"
varPostgresConnectionMaxOpen = "postgres.connection.maxopen"

varAuthURL = "auth.url"
)

// New creates a configuration reader object using a configurable configuration
Expand Down Expand Up @@ -272,3 +274,9 @@ func (c *Config) IsDBLogsEnabled() bool {
func (c *Config) IsCleanTestDataEnabled() bool {
return c.v.GetBool(varCleanTestDataEnabled)
}

// GetWITURL returns the WIT URL where WIT is running
// If AUTH_WIT_URL is not set and Auth in not in Dev Mode then we calculate the URL from the Auth Service URL domain
func (c *Config) GetWITURL() (string, error) {
return c.v.GetString(varWITURL), nil
}
14 changes: 10 additions & 4 deletions controller/pipeline_environments.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ import (
// PipelineEnvironmentController implements the PipelineEnvironment resource.
type PipelineEnvironmentController struct {
*goa.Controller
db application.DB
db application.DB
svcFactory application.ServiceFactory
}

// NewPipelineEnvironmentController creates a PipelineEnvironment controller.
func NewPipelineEnvironmentController(service *goa.Service, db application.DB) *PipelineEnvironmentController {
func NewPipelineEnvironmentController(service *goa.Service, db application.DB, svcFactory application.ServiceFactory) *PipelineEnvironmentController {
return &PipelineEnvironmentController{
Controller: service.NewController("PipelineEnvironmentController"),
db: db,
svcFactory: svcFactory,
}
}

Expand Down Expand Up @@ -139,7 +141,11 @@ func (c *PipelineEnvironmentController) Show(ctx *app.ShowPipelineEnvironmentsCo
}

func (c *PipelineEnvironmentController) checkSpaceExist(ctx context.Context, spaceID string) error {
// TODO check if space exists
// TODO check if space owner is the caller
// TODO(chmouel): Make sure we have the rights for that space
// TODO(chmouel): Better error reporting when NOTFound
_, err := c.svcFactory.WITService().GetSpace(ctx, spaceID)
if err != nil {
return errs.Wrapf(err, "failed to get space id: %s from wit", spaceID)
}
return nil
}
Loading

0 comments on commit d0d4e99

Please sign in to comment.