forked from fabric8-services/fabric8-wit
/
deployments_osioclient.go
176 lines (152 loc) · 5.93 KB
/
deployments_osioclient.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package controller
import (
"context"
"encoding/json"
"io/ioutil"
"net/http"
"github.com/fabric8-services/fabric8-wit/app"
witclient "github.com/fabric8-services/fabric8-wit/client"
"github.com/fabric8-services/fabric8-wit/goasupport"
"github.com/fabric8-services/fabric8-wit/log"
goaclient "github.com/goadesign/goa/client"
goauuid "github.com/goadesign/goa/uuid"
errs "github.com/pkg/errors"
uuid "github.com/satori/go.uuid"
)
// ResponseReader allows for reading from responses or mocked responses
type ResponseReader interface {
ReadResponse(*http.Response) ([]byte, error)
}
// IOResponseReader actual implementation of ResponseReader
type IOResponseReader struct {
}
// ReadResponse implementation for ResponseReader
func (r *IOResponseReader) ReadResponse(resp *http.Response) ([]byte, error) {
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
// ensure IOResponseReader implements all methods in ResponseReader
var _ ResponseReader = &IOResponseReader{}
var _ ResponseReader = (*IOResponseReader)(nil)
// WitClient is an interface for mocking the witclient.Client
type WitClient interface {
ShowSpace(ctx context.Context, path string, ifModifiedSince *string, ifNoneMatch *string) (*http.Response, error)
ShowUserService(ctx context.Context, path string) (*http.Response, error)
}
// OpenshiftIOClient is an interface for mocking OSIOClient
type OpenshiftIOClient interface {
GetNamespaceByType(ctx context.Context, userService *app.UserService, namespaceType string) (*app.NamespaceAttributes, error)
GetUserServices(ctx context.Context) (*app.UserService, error)
GetSpaceByID(ctx context.Context, spaceID uuid.UUID) (*app.Space, error)
}
// OSIOClient contains configuration and methods for interacting with OSIO API
type OSIOClient struct {
wc WitClient
responseReader ResponseReader
userServices *app.UserService
}
// ensure OSIOClient implements all methods in OpenshiftIOClient
var _ OpenshiftIOClient = &OSIOClient{}
var _ OpenshiftIOClient = (*OSIOClient)(nil)
// NewOSIOClient creates an openshift IO client given an http request context
func NewOSIOClient(ctx context.Context, scheme string, host string) OpenshiftIOClient {
wc := witclient.New(goaclient.HTTPClientDoer(http.DefaultClient))
wc.Host = host
wc.Scheme = scheme
wc.SetJWTSigner(goasupport.NewForwardSigner(ctx))
return CreateOSIOClient(wc, &IOResponseReader{})
}
// CreateOSIOClient factory method replaced during unit testing
func CreateOSIOClient(witclient WitClient, responseReader ResponseReader) OpenshiftIOClient {
client := new(OSIOClient)
client.wc = witclient
client.responseReader = responseReader
return client
}
// GetNamespaceByType finds a namespace by type (user, che, stage, etc)
// if userService is nil, will fetch the user services under the hood
func (osioclient *OSIOClient) GetNamespaceByType(ctx context.Context, userService *app.UserService, namespaceType string) (*app.NamespaceAttributes, error) {
if userService == nil {
us, err := osioclient.GetUserServices(ctx)
if err != nil {
return nil, errs.Wrapf(err, "could not retrieve user services")
}
userService = us
}
nameSpaces := userService.Attributes.Namespaces
for _, ns := range nameSpaces {
if *ns.Type == namespaceType {
return ns, nil
}
}
return nil, nil
}
// GetUserServices - fetch array of user services
// In the future, consider calling the tenant service (as /api/user/services implementation does)
func (osioclient *OSIOClient) GetUserServices(ctx context.Context) (*app.UserService, error) {
if osioclient.userServices != nil {
return osioclient.userServices, nil
}
resp, err := osioclient.wc.ShowUserService(goasupport.ForwardContextRequestID(ctx), witclient.ShowUserServicePath())
if err != nil {
return nil, errs.Wrapf(err, "could not retrieve uses services")
}
respBody, err := osioclient.responseReader.ReadResponse(resp)
status := resp.StatusCode
if status == http.StatusNotFound {
return nil, nil
} else if status != http.StatusOK {
log.Error(nil, map[string]interface{}{
"err": err,
"path": witclient.ShowUserServicePath(),
"http_status": status,
}, "failed to get user service from WIT service due to HTTP error %d", status)
return nil, errs.Errorf("failed to GET %s due to status code %d", witclient.ShowUserServicePath(), status)
}
var respType app.UserServiceSingle
err = json.Unmarshal(respBody, &respType)
if err != nil {
log.Error(nil, map[string]interface{}{
"err": err,
"path": witclient.ShowUserServicePath(),
"response": respBody,
}, "unable to unmarshal user service from WIT service")
return nil, errs.Wrapf(err, "could not unmarshal user services JSON")
}
osioclient.userServices = respType.Data
return respType.Data, nil
}
// GetSpaceByID - fetch space given UUID
func (osioclient *OSIOClient) GetSpaceByID(ctx context.Context, spaceID uuid.UUID) (*app.Space, error) {
guid := goauuid.UUID(spaceID)
urlpath := witclient.ShowSpacePath(guid)
resp, err := osioclient.wc.ShowSpace(goasupport.ForwardContextRequestID(ctx), urlpath, nil, nil)
if err != nil {
return nil, errs.Wrapf(err, "could not connect to %s", urlpath)
}
respBody, err := osioclient.responseReader.ReadResponse(resp)
status := resp.StatusCode
if status == http.StatusNotFound {
return nil, nil
} else if status != http.StatusOK {
log.Error(nil, map[string]interface{}{
"err": err,
"space_id": spaceID,
"path": urlpath,
"http_status": status,
}, "failed to get user space from WIT service due to HTTP error %s", status)
return nil, errs.Errorf("failed to GET %s due to status code %d", urlpath, status)
}
var respType app.SpaceSingle
err = json.Unmarshal(respBody, &respType)
if err != nil {
log.Error(nil, map[string]interface{}{
"err": err,
"space_id": spaceID,
"path": urlpath,
"response": respBody,
}, "unable to unmarshal user space from WIT service")
return nil, errs.Wrap(err, "could not unmarshal SpaceSingle JSON")
}
return respType.Data, nil
}