diff --git a/go.mod b/go.mod index d6f574e..af878f3 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,15 @@ module github.com/cloud-club/Aviator-service go 1.21.1 require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect github.com/golang/mock v1.6.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/tools v0.15.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 29305c2..b83f748 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,20 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -31,5 +46,10 @@ golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index da29a2c..09c243e 100644 --- a/main.go +++ b/main.go @@ -1,4 +1,6 @@ package main +//go:generate mockery --dir=pkg --name=ServerInterface --filename=server_interface.go --output pkg/mocks --outpkg=mocks func main() { + } diff --git a/pkg/common.go b/pkg/common.go deleted file mode 100644 index 41ead87..0000000 --- a/pkg/common.go +++ /dev/null @@ -1,15 +0,0 @@ -package pkg - -import ( - "fmt" - "net/http" -) - -func GetCommonHeader(request *http.Request) { - request.Header.Set("Accept", "application/json") - request.Header.Set("cache-control", "max-age=0") -} - -func SetAuthToken(request *http.Request, token string) { - request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) -} diff --git a/pkg/common/constants.go b/pkg/common/constants.go new file mode 100644 index 0000000..47ac497 --- /dev/null +++ b/pkg/common/constants.go @@ -0,0 +1,3 @@ +package common + +const BaseUrl = "https://ncloud.apigw.ntruss.com/vserver/v2" diff --git a/pkg/common/httputil.go b/pkg/common/httputil.go new file mode 100644 index 0000000..8e12723 --- /dev/null +++ b/pkg/common/httputil.go @@ -0,0 +1,65 @@ +package common + +import ( + "bytes" + "fmt" + "net/http" + "time" +) + +type HttpService struct { + Client *http.Client + Interface HttpInterface +} + +type HttpInterface interface { + Get(url string) (*http.Response, error) + List(url string) (*http.Response, error) + Create(url string, payload []byte) (*http.Response, error) + Update(url string, payload []byte) (*http.Response, error) + Delete(url string) (*http.Response, error) +} + +func NewHttpClient(i HttpInterface) HttpService { + return HttpService{Client: &http.Client{Timeout: time.Second * 10}, Interface: i} +} + +func (h *HttpService) Create(url string, payload []byte) (*http.Response, error) { + return h.do(http.MethodPost, url, payload) +} + +func (h *HttpService) Get(url string) (*http.Response, error) { + return h.do(http.MethodGet, url, nil) +} + +func (h *HttpService) List(url string) (*http.Response, error) { + if len(url) == 0 { + return nil, fmt.Errorf("please input url") + } + //return nil, nil + return h.do(http.MethodGet, url, nil) +} + +func (h *HttpService) Delete(url string) (*http.Response, error) { + return h.do(http.MethodDelete, url, nil) +} + +func (h *HttpService) Update(url string, payload []byte) (*http.Response, error) { + return h.do(http.MethodPatch, url, payload) +} + +func (h *HttpService) do(method string, url string, payload []byte) (*http.Response, error) { + var req *http.Request + var err error + if method == http.MethodGet { + if req, err = http.NewRequest(method, url, nil); err != nil { + return nil, err + } + } else { + if req, err = http.NewRequest(method, url, bytes.NewReader(payload)); err != nil { + return nil, err + } + } + + return h.Client.Do(req) +} diff --git a/pkg/constant.go b/pkg/constant.go deleted file mode 100644 index c1caffe..0000000 --- a/pkg/constant.go +++ /dev/null @@ -1 +0,0 @@ -package pkg diff --git a/pkg/mocks/server_interface.go b/pkg/mocks/server_interface.go new file mode 100644 index 0000000..aee89a1 --- /dev/null +++ b/pkg/mocks/server_interface.go @@ -0,0 +1,328 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package pkg + +import ( + http "net/http" + + mock "github.com/stretchr/testify/mock" +) + +// MockServerInterface is an autogenerated mock type for the ServerInterface type +type MockServerInterface struct { + mock.Mock +} + +type MockServerInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *MockServerInterface) EXPECT() *MockServerInterface_Expecter { + return &MockServerInterface_Expecter{mock: &_m.Mock} +} + +// Create provides a mock function with given fields: url, payload +func (_m *MockServerInterface) Create(url string, payload []byte) (*http.Response, error) { + ret := _m.Called(url, payload) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(string, []byte) (*http.Response, error)); ok { + return rf(url, payload) + } + if rf, ok := ret.Get(0).(func(string, []byte) *http.Response); ok { + r0 = rf(url, payload) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(string, []byte) error); ok { + r1 = rf(url, payload) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockServerInterface_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type MockServerInterface_Create_Call struct { + *mock.Call +} + +// Create is a helper method to define mock.On call +// - url string +// - payload []byte +func (_e *MockServerInterface_Expecter) Create(url interface{}, payload interface{}) *MockServerInterface_Create_Call { + return &MockServerInterface_Create_Call{Call: _e.mock.On("Create", url, payload)} +} + +func (_c *MockServerInterface_Create_Call) Run(run func(url string, payload []byte)) *MockServerInterface_Create_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].([]byte)) + }) + return _c +} + +func (_c *MockServerInterface_Create_Call) Return(_a0 *http.Response, _a1 error) *MockServerInterface_Create_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockServerInterface_Create_Call) RunAndReturn(run func(string, []byte) (*http.Response, error)) *MockServerInterface_Create_Call { + _c.Call.Return(run) + return _c +} + +// Delete provides a mock function with given fields: url +func (_m *MockServerInterface) Delete(url string) (*http.Response, error) { + ret := _m.Called(url) + + if len(ret) == 0 { + panic("no return value specified for Delete") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(string) (*http.Response, error)); ok { + return rf(url) + } + if rf, ok := ret.Get(0).(func(string) *http.Response); ok { + r0 = rf(url) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(url) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockServerInterface_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' +type MockServerInterface_Delete_Call struct { + *mock.Call +} + +// Delete is a helper method to define mock.On call +// - url string +func (_e *MockServerInterface_Expecter) Delete(url interface{}) *MockServerInterface_Delete_Call { + return &MockServerInterface_Delete_Call{Call: _e.mock.On("Delete", url)} +} + +func (_c *MockServerInterface_Delete_Call) Run(run func(url string)) *MockServerInterface_Delete_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockServerInterface_Delete_Call) Return(_a0 *http.Response, _a1 error) *MockServerInterface_Delete_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockServerInterface_Delete_Call) RunAndReturn(run func(string) (*http.Response, error)) *MockServerInterface_Delete_Call { + _c.Call.Return(run) + return _c +} + +// Get provides a mock function with given fields: url +func (_m *MockServerInterface) Get(url string) (*http.Response, error) { + ret := _m.Called(url) + + if len(ret) == 0 { + panic("no return value specified for Get") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(string) (*http.Response, error)); ok { + return rf(url) + } + if rf, ok := ret.Get(0).(func(string) *http.Response); ok { + r0 = rf(url) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(url) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockServerInterface_Get_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Get' +type MockServerInterface_Get_Call struct { + *mock.Call +} + +// Get is a helper method to define mock.On call +// - url string +func (_e *MockServerInterface_Expecter) Get(url interface{}) *MockServerInterface_Get_Call { + return &MockServerInterface_Get_Call{Call: _e.mock.On("Get", url)} +} + +func (_c *MockServerInterface_Get_Call) Run(run func(url string)) *MockServerInterface_Get_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockServerInterface_Get_Call) Return(_a0 *http.Response, _a1 error) *MockServerInterface_Get_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockServerInterface_Get_Call) RunAndReturn(run func(string) (*http.Response, error)) *MockServerInterface_Get_Call { + _c.Call.Return(run) + return _c +} + +// List provides a mock function with given fields: url +func (_m *MockServerInterface) List(url string) (*http.Response, error) { + ret := _m.Called(url) + + if len(ret) == 0 { + panic("no return value specified for List") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(string) (*http.Response, error)); ok { + return rf(url) + } + if rf, ok := ret.Get(0).(func(string) *http.Response); ok { + r0 = rf(url) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(url) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockServerInterface_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' +type MockServerInterface_List_Call struct { + *mock.Call +} + +// List is a helper method to define mock.On call +// - url string +func (_e *MockServerInterface_Expecter) List(url interface{}) *MockServerInterface_List_Call { + return &MockServerInterface_List_Call{Call: _e.mock.On("List", url)} +} + +func (_c *MockServerInterface_List_Call) Run(run func(url string)) *MockServerInterface_List_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string)) + }) + return _c +} + +func (_c *MockServerInterface_List_Call) Return(_a0 *http.Response, _a1 error) *MockServerInterface_List_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockServerInterface_List_Call) RunAndReturn(run func(string) (*http.Response, error)) *MockServerInterface_List_Call { + _c.Call.Return(run) + return _c +} + +// Update provides a mock function with given fields: url, payload +func (_m *MockServerInterface) Update(url string, payload []byte) (*http.Response, error) { + ret := _m.Called(url, payload) + + if len(ret) == 0 { + panic("no return value specified for Update") + } + + var r0 *http.Response + var r1 error + if rf, ok := ret.Get(0).(func(string, []byte) (*http.Response, error)); ok { + return rf(url, payload) + } + if rf, ok := ret.Get(0).(func(string, []byte) *http.Response); ok { + r0 = rf(url, payload) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*http.Response) + } + } + + if rf, ok := ret.Get(1).(func(string, []byte) error); ok { + r1 = rf(url, payload) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockServerInterface_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update' +type MockServerInterface_Update_Call struct { + *mock.Call +} + +// Update is a helper method to define mock.On call +// - url string +// - payload []byte +func (_e *MockServerInterface_Expecter) Update(url interface{}, payload interface{}) *MockServerInterface_Update_Call { + return &MockServerInterface_Update_Call{Call: _e.mock.On("Update", url, payload)} +} + +func (_c *MockServerInterface_Update_Call) Run(run func(url string, payload []byte)) *MockServerInterface_Update_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(string), args[1].([]byte)) + }) + return _c +} + +func (_c *MockServerInterface_Update_Call) Return(_a0 *http.Response, _a1 error) *MockServerInterface_Update_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockServerInterface_Update_Call) RunAndReturn(run func(string, []byte) (*http.Response, error)) *MockServerInterface_Update_Call { + _c.Call.Return(run) + return _c +} + +// NewMockServerInterface creates a new instance of MockServerInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMockServerInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *MockServerInterface { + mock := &MockServerInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/ncp.go b/pkg/ncp.go index fae63c6..4ba7d7d 100644 --- a/pkg/ncp.go +++ b/pkg/ncp.go @@ -1,56 +1,26 @@ package pkg import ( - "errors" - "github.com/cloud-club/Aviator-service/types/auth" - "github.com/dgrijalva/jwt-go/v4" - "time" -) - -const ( - JwtTokenExpireTime = time.Minute * 30 - SignKey = "CloudClubAviator" + "github.com/cloud-club/Aviator-service/pkg/common" + "github.com/cloud-club/Aviator-service/pkg/network" ) type NcpService struct { - token string - Server ServerInterface -} - -func NewNcpService(token string) *NcpService { - return &NcpService{token: token} -} - -func (n *NcpService) GetToken() string { - return n.token + Server ServerService + HttpService common.HttpService + Network network.Network } -func (n *NcpService) CreateToken(username string, name string, role []string) error { - claim := auth.AuthTokenClaims{ - Username: username, - Name: name, - Role: role, - StandardClaims: jwt.StandardClaims{ - Issuer: "CloudClub", - ExpiresAt: jwt.At(time.Now().Add(JwtTokenExpireTime)), - }, - } +func New() *NcpService { + ncp := newNcpService() + ncp.Network = network.Init(ncp.Network.Interface) + ncp.Server = Init(ncp.Server.Interface) + ncp.Network.HttpService = common.NewHttpClient(ncp.HttpService.Interface) + ncp.Server.HttpService = common.NewHttpClient(ncp.HttpService.Interface) - authToken := jwt.NewWithClaims(jwt.SigningMethodHS512, &claim) - signedAuthToken, err := authToken.SignedString([]byte(SignKey)) - if err != nil { - return err - } - n.token = signedAuthToken - return nil + return ncp } -func (n *NcpService) VerifyToken(token string, claim *auth.AuthTokenClaims) (bool, error) { - t, err := jwt.ParseWithClaims(token, claim, func(t *jwt.Token) (interface{}, error) { - if _, isOk := t.Method.(*jwt.SigningMethodHMAC); !isOk { - return nil, errors.New("deny to provide JWT Token") - } - return []byte(SignKey), nil - }) - return t.Valid, err +func newNcpService() *NcpService { + return &NcpService{} } diff --git a/pkg/ncp_test.go b/pkg/ncp_test.go index c6e43f2..318b638 100644 --- a/pkg/ncp_test.go +++ b/pkg/ncp_test.go @@ -1,48 +1,15 @@ package pkg_test import ( - "errors" - "fmt" - "github.com/cloud-club/Aviator-service/pkg" "github.com/cloud-club/Aviator-service/types/auth" - "github.com/stretchr/testify/assert" - "log" - "testing" ) -func TestCreateAndVerifyToken_success(t *testing.T) { - ncp := pkg.NewNcpService("ncp service token") - ncp.Server = pkg.NewServerService("ncp server token") - - err := ncp.CreateToken("admin", "CloudClubAdmin", []string{"admin"}) - if err != nil { - t.Fatal(err) - } - isSuccess, err := ncp.VerifyToken(ncp.GetToken(), &auth.AuthTokenClaims{}) - if err != nil { - t.Fatal(err) - } - - if isSuccess { - t.Log(ncp.GetToken()) - } else { - t.Fatal(errors.New(fmt.Sprintf("token verify failed : %s", ncp.GetToken()))) - } +func (suite *NcpSuite) TestVerifyToken_success() { + _, err := suite.ncp.VerifyToken(suite.ncp.GetToken(), &auth.AuthTokenClaims{}) + suite.Equal(err, nil, nil) } -func TestCreateAndVerifyToken_fail_token_is_invalid(t *testing.T) { - ncp := pkg.NewNcpService("ncp service token") - ncp.Server = pkg.NewServerService("ncp server token") - - err := ncp.CreateToken("admin", "CloudClubAdmin", []string{"admin"}) - if err != nil { - t.Fatal(err) - } - isSuccess, err := ncp.VerifyToken(ncp.GetToken()+"is failed", &auth.AuthTokenClaims{}) - log.Println(err) - if isSuccess { - t.Fail() - } else { - assert.Error(t, err, errors.New("token signature is invalid")) - } +func (suite *NcpSuite) TestCreateAndVerifyToken_fail_token_is_invalid() { + _, err := suite.ncp.VerifyToken(suite.ncp.GetToken()+"is failed", &auth.AuthTokenClaims{}) + suite.EqualError(err, "token signature is invalid") } diff --git a/pkg/network/core.go b/pkg/network/core.go new file mode 100644 index 0000000..25f0b66 --- /dev/null +++ b/pkg/network/core.go @@ -0,0 +1,24 @@ +package network + +import ( + "github.com/cloud-club/Aviator-service/pkg/common" + "github.com/cloud-club/Aviator-service/types/network" + "net/http" +) + +type Network struct { + HttpService common.HttpService + Interface NetServiceInterface +} + +type NetServiceInterface interface { + GetNetworkInterfaceList(dto *network.RequestBodyNetworkInterfaceList) (*http.Response, error) +} + +func Init(i NetServiceInterface) Network { + return Network{Interface: i} +} + +func (n Network) GetNetworkInterfaceList(dto *network.RequestBodyNetworkInterfaceList) (*http.Response, error) { + return n.getNetworkInterfaceList(dto) +} diff --git a/pkg/network/core_test.go b/pkg/network/core_test.go new file mode 100644 index 0000000..02fff50 --- /dev/null +++ b/pkg/network/core_test.go @@ -0,0 +1,30 @@ +package network_test + +import ( + "encoding/json" + "github.com/cloud-club/Aviator-service/types/network" + "io" + "log" +) + +func (suite *NcpSuite) TestGetNetworkInterfaceList() { + + resp, err := suite.ncp.Network.GetNetworkInterfaceList(&network.RequestBodyNetworkInterfaceList{ + RegionCode: "KR", + }) + defer resp.Body.Close() + rawData, err := io.ReadAll(resp.Body) + if err != nil { + suite.T().Fatalf("%v", err) + } + log.Println(resp.Status) + data := new(ResponseOfGetNetworkInterfaceList) + if err = json.Unmarshal(rawData, data); err != nil { + suite.T().Fatalf("%v", err) + } + log.Println(data.GetNetworkInterfaceListResponse) + + if err != nil { + suite.T().Fatalf("%v", err) + } +} diff --git a/pkg/network/network.go b/pkg/network/network.go new file mode 100644 index 0000000..d658db5 --- /dev/null +++ b/pkg/network/network.go @@ -0,0 +1,19 @@ +package network + +import ( + "fmt" + "github.com/cloud-club/Aviator-service/pkg/common" + "github.com/cloud-club/Aviator-service/types/network" + "net/http" +) + +func (n Network) getNetworkInterfaceList(dto *network.RequestBodyNetworkInterfaceList) (*http.Response, error) { + //url := fmt.Sprintf("%s/getNetworkInterfaceList?regionCode=%s&subnetName=%s,&networkInterfaceNoList.1=%s&networkInterfaceName=%s&networkInterfaceStatusCode=%s&ip=%s&secondaryIpList.1=%s&instanceNo%s&isDefault=%s&deviceName=%s&serverName=%s", + // common.BaseUrl, + // dto.RegionCode, dto.SubnetName, dto.NetworkInterfaceNoList, dto.NetworkInterfaceName, dto.NetworkInterfaceStatusCode, + // dto.Ip, dto.SecondaryIpList, dto.InstanceNo, strconv.FormatBool(dto.IsDefault), dto.DeviceName, dto.ServerName) + url := fmt.Sprintf("%s/getNetworkInterfaceList", common.BaseUrl) + //regionCode=%s&subnetName=%s,&networkInterfaceNoList.1=%s&networkInterfaceName=%s&networkInterfaceStatusCode=%s&ip=%s&secondaryIpList.1=%s&instanceNo%s&isDefault=%s&deviceName=%s&serverName=%s", + + return n.HttpService.Get(url) +} diff --git a/pkg/network/suite_test.go b/pkg/network/suite_test.go new file mode 100644 index 0000000..dee45c4 --- /dev/null +++ b/pkg/network/suite_test.go @@ -0,0 +1,23 @@ +package network_test + +import ( + "github.com/cloud-club/Aviator-service/pkg" + "github.com/stretchr/testify/suite" + "testing" +) + +// This is our suite +type NcpSuite struct { + suite.Suite + ncp *pkg.NcpService +} + +// This gets run automatically by `go test` so we call `suite.Run` inside it +func TestNcpSuite(t *testing.T) { + suite.Run(t, new(NcpSuite)) +} + +// This method gets run only first time before starting test +func (suite *NcpSuite) SetupSuite() { + suite.ncp = pkg.New() +} diff --git a/pkg/server.go b/pkg/server.go index ee3c2ca..529bd50 100644 --- a/pkg/server.go +++ b/pkg/server.go @@ -1,49 +1,60 @@ package pkg import ( - "errors" + "bytes" + "fmt" + "github.com/cloud-club/Aviator-service/pkg/common" + "net/http" ) type ServerService struct { - token string + Interface ServerInterface + HttpService common.HttpService + token string } -//go:generate mockgen -destination=mocks/mock_server.go -package=mocks github.com/cloud-club/Aviator-service/pkg ServerInterface type ServerInterface interface { - Get(url string) error - List(url string) error - Create(url string, payload interface{}) error - Update(url string) error - Delete(url string) error + Get(url string) (*http.Response, error) + List(url string) (*http.Response, error) + Create(url string, payload []byte) (*http.Response, error) + Update(url string, payload []byte) (*http.Response, error) + Delete(url string) (*http.Response, error) } -func NewServerService(token string) ServerInterface { - return &ServerService{token: token} +func Init(i ServerInterface) ServerService { + return ServerService{Interface: i} } -func (server *ServerService) GetToken() string { - return server.token +func (server *ServerService) Create(url string, payload []byte) (*http.Response, error) { + return server.do(http.MethodPost, url, payload) } -func (server *ServerService) Create(url string, payload interface{}) error { - return nil +func (server *ServerService) Get(url string) (*http.Response, error) { + return server.do(http.MethodGet, url, nil) } -func (server *ServerService) Get(url string) error { - return nil -} - -func (server *ServerService) List(url string) error { +func (server *ServerService) List(url string) (*http.Response, error) { if len(url) == 0 { - return errors.New("please input url") + return nil, fmt.Errorf("please input url") } - return nil + //return nil, nil + return server.do(http.MethodGet, url, nil) +} + +func (server *ServerService) Delete(url string) (*http.Response, error) { + return server.do(http.MethodDelete, url, nil) } -func (server *ServerService) Delete(url string) error { - return nil +func (server *ServerService) Update(url string, payload []byte) (*http.Response, error) { + return server.do(http.MethodPatch, url, payload) } -func (server *ServerService) Update(url string) error { - return nil +func (server *ServerService) do(method string, url string, payload []byte) (*http.Response, error) { + req, err := http.NewRequest(method, url, bytes.NewReader(payload)) + if err != nil { + return nil, err + } + common.GetCommonHeader(req) + + return server.HttpService.Client.Do(req) } diff --git a/pkg/server_test.go b/pkg/server_test.go index adb682d..8829445 100644 --- a/pkg/server_test.go +++ b/pkg/server_test.go @@ -1,13 +1,13 @@ package pkg_test import ( - "github.com/cloud-club/Aviator-service/pkg" + "fmt" + pkg2 "github.com/cloud-club/Aviator-service/pkg/mocks" "testing" ) -func TestList(t *testing.T) { - ncp := pkg.NewNcpService("ncp service token") - ncp.Server = pkg.NewServerService("ncp server token") +func (suite *NcpSuite) TestList() { + mockInterface := &pkg2.MockServerInterface{} // given tests := []struct { @@ -15,36 +15,50 @@ func TestList(t *testing.T) { url string payload interface{} expectedError string + actualError string expectedData interface{} }{ { name: "성공", url: "http://localhost:8080", payload: nil, + actualError: "", expectedError: "", expectedData: nil, }, { - name: "(실패) url을 입력 안함", + name: "(실패) url 입력 안함", url: "", payload: nil, + actualError: "please input url", expectedError: "please input url", expectedData: nil, }, } for i := range tests { - t.Logf("%s : running scenario %d", tests[i].name, i) - t.Run(tests[i].name, func(t *testing.T) { - err := ncp.Server.List(tests[i].url) + suite.T().Helper() + + suite.T().Run(tests[i].name, func(t *testing.T) { + suite.T().Logf("%s : running scenario %d", tests[i].name, i) + + if tests[i].actualError == "" { + mockInterface.On("List", tests[i].url). + Return(nil, nil). + Once() + + } else { + mockInterface.On("List", tests[i].url). + Return(nil, fmt.Errorf("%s", tests[i].actualError)). + Once() + } + suite.ncp.Server.Interface = mockInterface + + _, err := suite.ncp.Server.Interface.List(tests[i].url) if err != nil { - if err.Error() != tests[i].expectedError { - t.Fatalf("expected error : %v, got : %v", tests[i].expectedError, err) - } + suite.Assert().EqualError(err, tests[i].expectedError) } else { - if tests[i].expectedError != "" { - t.Fatalf("expected error : %v, got : %v", tests[i].expectedError, err) - } + suite.Assert().NoError(err) } }) } diff --git a/pkg/suite_test.go b/pkg/suite_test.go new file mode 100644 index 0000000..9ae486f --- /dev/null +++ b/pkg/suite_test.go @@ -0,0 +1,27 @@ +package pkg_test + +import ( + "github.com/cloud-club/Aviator-service/pkg" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "testing" +) + +// This is our suite +type NcpSuite struct { + suite.Suite + ncp *pkg.NcpService +} + +// This gets run automatically by `go test` so we call `suite.Run` inside it +func TestNcpSuite(t *testing.T) { + suite.Run(t, new(NcpSuite)) +} + +// This method gets run only first time before starting test +func (suite *NcpSuite) SetupSuite() { + suite.ncp = pkg.NewNcpService("ncp service token") + + err := suite.ncp.CreateToken("admin", "CloudClubAdmin", []string{"admin"}) + assert.NoError(suite.T(), err, nil) +} diff --git a/types/server/common.go b/types/common.go similarity index 100% rename from types/server/common.go rename to types/common.go diff --git a/types/network/common.go b/types/network/common.go new file mode 100644 index 0000000..1ae2e9d --- /dev/null +++ b/types/network/common.go @@ -0,0 +1 @@ +package network diff --git a/types/network/request.go b/types/network/request.go new file mode 100644 index 0000000..9b5349a --- /dev/null +++ b/types/network/request.go @@ -0,0 +1,15 @@ +package network + +type RequestBodyNetworkInterfaceList struct { + RegionCode string `json:"RegionCode"` + SubnetName string `json:"SubnetName"` + NetworkInterfaceNoList []string `json:"NetworkInterfaceNoList"` + NetworkInterfaceName string `json:"NetworkInterfaceName"` + NetworkInterfaceStatusCode string `json:"NetworkInterfaceStatusCode"` + SecondaryIpList []string `json:"SecondaryIpList"` + Ip string `json:"Ip"` + InstanceNo string `json:"InstanceNo"` + IsDefault bool `json:"IsDefault"` + DeviceName string `json:"DeviceName"` + ServerName string `json:"ServerName"` +} diff --git a/types/network/response.go b/types/network/response.go new file mode 100644 index 0000000..16916ab --- /dev/null +++ b/types/network/response.go @@ -0,0 +1,23 @@ +package network + +import "github.com/cloud-club/Aviator-service/types" + +type AccessControlGroupNoList []string +type SecondaryIpList []string + +type ResponseBodyNetworkInterface struct { + NetworkInterfaceNo string + NetworkInterfaceName string + SubnetNo string + DeleteOnTermination bool + IsDefault bool + DeviceName string + NetworkInterfaceStatus types.CommonCode + InstanceType types.CommonCode + InstanceNo string + IP string + MacAddress string + AccessControlGroupNoList AccessControlGroupNoList + NetworkInterfaceDescription string + SecondaryIpList SecondaryIpList +} diff --git a/types/server/response.go b/types/server/response.go index dfea4a2..b3152a5 100644 --- a/types/server/response.go +++ b/types/server/response.go @@ -1,6 +1,9 @@ package types -import "time" +import ( + "github.com/cloud-club/Aviator-service/types" + "time" +) // ServerInstanceResponse is same as compute server in Naver Cloud (such as AWS EC2) type ServerInstanceResponse struct { @@ -9,12 +12,12 @@ type ServerInstanceResponse struct { ServerDescription string CpuCount int MemorySize int64 - PlatformType CommonCode + PlatformType types.CommonCode LoginKeyName string PublicIpInstanceNo string PublicIp string - ServerInstanceStatus CommonCode - ServerInstanceOperation CommonCode + ServerInstanceStatus types.CommonCode + ServerInstanceOperation types.CommonCode ServerInstanceStatusName string CreateDate time.Time Uptime time.Time @@ -25,16 +28,16 @@ type ServerInstanceResponse struct { RegionCode string VpcNo string SubnetNo string - NetworkInterfaceNoList NetworkInterfaceNoList + NetworkInterfaceNoList types.NetworkInterfaceNoList InitScriptNo string - ServerInstanceType CommonCode - BaseBlockStorageDiskType CommonCode - BaseBlockStorageDiskDetailType CommonCode + ServerInstanceType types.CommonCode + BaseBlockStorageDiskType types.CommonCode + BaseBlockStorageDiskDetailType types.CommonCode PlacementGroupNo string PlacementGroupName string MemberServerImageInstanceNo string - BlockDevicePartitionList []BlockDevicePartition - HypervisorType CommonCode + BlockDevicePartitionList []types.BlockDevicePartition + HypervisorType types.CommonCode ServerImageNo string ServerSpecCode string }