merge branch helm-list-refactor

pull/8423/head
ys.achinta 5 years ago
commit 5d510c6cae

@ -6,31 +6,39 @@ import (
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/api"
"helm.sh/helm/v3/pkg/api/list"
"helm.sh/helm/v3/pkg/api/logger"
"helm.sh/helm/v3/pkg/api/ping"
"helm.sh/helm/v3/pkg/servercontext"
)
func main() {
app := servercontext.NewApp()
startServer(app)
servercontext.NewApp()
startServer()
}
func startServer(appconfig *servercontext.Application) {
func startServer() {
router := http.NewServeMux()
//TODO: use gorilla mux and add middleware to write content type and other headers
app := servercontext.App()
logger.Setup("debug")
<<<<<<< HEAD
actionInstall := action.NewInstall(app.ActionConfig)
actionUpgrade := action.NewUpgrade(app.ActionConfig)
actionHistory := action.NewHistory(app.ActionConfig)
service := api.NewService(app.Config, new(action.ChartPathOptions), api.NewInstaller(actionInstall), api.NewUpgrader(actionUpgrade), api.NewHistory(actionHistory))
=======
service := api.NewService(app.Config,
new(action.ChartPathOptions),
api.NewInstall(action.NewInstall(app.ActionConfig)),
api.NewList(action.NewList(app.ActionConfig)))
>>>>>>> helm-service-refactor
router.Handle("/ping", ping.Handler())
router.Handle("/list", list.Handler())
router.Handle("/list", api.List(service))
router.Handle("/install", api.Install(service))
router.Handle("/upgrade", api.Upgrade(service))

@ -0,0 +1,9 @@
package api
import (
"helm.sh/helm/v3/pkg/cli"
)
type chartloader interface {
LocateChart(name string, settings *cli.EnvSettings) (string, error)
}

@ -37,7 +37,7 @@ func Install(svc Service) http.Handler {
respondError(w, "error while installing chart: %v", err)
return
}
response.Status = res.status
response.Status = res.Status
if err := json.NewEncoder(w).Encode(&response); err != nil {
logger.Errorf("[Install] error writing response %v", err)
w.WriteHeader(http.StatusInternalServerError)

@ -15,7 +15,6 @@ import (
"gotest.tools/assert"
"helm.sh/helm/v3/pkg/api"
"helm.sh/helm/v3/pkg/api/logger"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
)
@ -24,8 +23,9 @@ type InstallerTestSuite struct {
suite.Suite
recorder *httptest.ResponseRecorder
server *httptest.Server
mockInstaller *mockInstaller
mockInstall *mockInstall
mockChartLoader *mockChartLoader
mockList *mockList
appConfig *cli.EnvSettings
}
@ -35,13 +35,14 @@ func (s *InstallerTestSuite) SetupSuite() {
func (s *InstallerTestSuite) SetupTest() {
s.recorder = httptest.NewRecorder()
s.mockInstaller = new(mockInstaller)
s.mockInstall = new(mockInstall)
s.mockChartLoader = new(mockChartLoader)
s.mockList = new(mockList)
s.appConfig = &cli.EnvSettings{
RepositoryConfig: "./testdata/helm",
PluginsDirectory: "./testdata/helm/plugin",
}
service := api.NewService(s.appConfig, s.mockChartLoader, s.mockInstaller, nil, nil)
service := api.NewService(s.appConfig, s.mockChartLoader,nil, s.mockInstall, nil, nil)
handler := api.Install(service)
s.server = httptest.NewServer(handler)
}
@ -55,11 +56,11 @@ func (s *InstallerTestSuite) TestShouldReturnDeployedStatusOnSuccessfulInstall()
req, _ := http.NewRequest("POST", fmt.Sprintf("%s/install", s.server.URL), strings.NewReader(body))
s.mockChartLoader.On("LocateChart", chartName, s.appConfig).Return("./testdata/albatross", nil)
icfg := api.ReleaseConfig{ChartName: chartName, Name: "redis-v5", Namespace: "something"}
s.mockInstaller.On("SetConfig", icfg)
s.mockInstall.On("SetConfig", icfg)
release := &release.Release{Info: &release.Info{Status: release.StatusDeployed}}
var vals map[string]interface{}
//TODO: pass chart object and verify values present testdata chart yml
s.mockInstaller.On("Run", mock.AnythingOfType("*chart.Chart"), vals).Return(release, nil)
s.mockInstall.On("Run", mock.AnythingOfType("*chart.Chart"), vals).Return(release, nil)
resp, err := http.DefaultClient.Do(req)
@ -68,7 +69,7 @@ func (s *InstallerTestSuite) TestShouldReturnDeployedStatusOnSuccessfulInstall()
respBody, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), expectedResponse, string(respBody))
require.NoError(s.T(), err)
s.mockInstaller.AssertExpectations(s.T())
s.mockInstall.AssertExpectations(s.T())
s.mockChartLoader.AssertExpectations(s.T())
}
@ -88,7 +89,7 @@ func (s *InstallerTestSuite) TestShouldReturnInternalServerErrorOnFailure() {
respBody, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), expectedResponse, string(respBody))
require.NoError(s.T(), err)
s.mockInstaller.AssertExpectations(s.T())
s.mockInstall.AssertExpectations(s.T())
s.mockChartLoader.AssertExpectations(s.T())
}
@ -99,21 +100,3 @@ func (s *InstallerTestSuite) TearDownTest() {
func TestInstallAPI(t *testing.T) {
suite.Run(t, new(InstallerTestSuite))
}
type mockInstaller struct{ mock.Mock }
func (m *mockInstaller) SetConfig(cfg api.ReleaseConfig) {
m.Called(cfg)
}
func (m *mockInstaller) Run(c *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
args := m.Called(c, vals)
return args.Get(0).(*release.Release), args.Error(1)
}
type mockChartLoader struct{ mock.Mock }
func (m *mockChartLoader) LocateChart(name string, settings *cli.EnvSettings) (string, error) {
args := m.Called(name, settings)
return args.String(0), args.Error(1)
}

@ -6,19 +6,20 @@ import (
"helm.sh/helm/v3/pkg/release"
)
type Installer struct {
type install struct {
*action.Install
}
type installrunner interface {
type Installer interface {
Run(*chart.Chart, map[string]interface{}) (*release.Release, error)
SetConfig(ReleaseConfig)
}
func (i *Installer) SetConfig(cfg ReleaseConfig) {
func (i *install) SetConfig(cfg ReleaseConfig) {
i.ReleaseName = cfg.Name
i.Namespace = cfg.Namespace
}
func NewInstaller(ai *action.Install) *Installer {
return &Installer{ai}
func NewInstall(ai *action.Install) *install {
return &install{ai}
}

@ -0,0 +1,66 @@
package api
import (
"encoding/json"
"helm.sh/helm/v3/pkg/api/logger"
"net/http"
)
type ListRequest struct {
NameSpace string `json:"namespace"`
ReleaseStatus string `json:"release_status"`
}
type ListResponse struct {
Error string `json:"error,omitempty"`
Releases []Release
}
type Release struct {
Name string `json:"release"`
Namespace string `json:"namespace"`
}
func List(svc Service) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var response ListResponse
var request ListRequest
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&request); err != nil {
logger.Errorf("[List] error decoding request: %v", err)
response.Error = err.Error()
payload, _ := json.Marshal(response)
w.WriteHeader(http.StatusBadRequest)
w.Write(payload)
return
}
defer r.Body.Close()
helmReleases, err := svc.List(request.ReleaseStatus)
if err != nil {
logger.Errorf("[List] error while installing chart: %v", err)
response.Error = err.Error()
payload, _ := json.Marshal(response)
w.WriteHeader(http.StatusInternalServerError)
w.Write(payload)
return
}
response = ListResponse{"", helmReleases}
payload, err := json.Marshal(response)
if err != nil {
logger.Errorf("[List] error writing response %v", err)
response.Error = err.Error()
payload, _ := json.Marshal(response)
w.WriteHeader(http.StatusInternalServerError)
w.Write(payload)
return
}
w.WriteHeader(http.StatusOK)
w.Write(payload)
})
}

@ -1,15 +0,0 @@
package list
type ListRequest struct {
RequestID string
}
type ListRespose struct {
Status bool
Data []HelmRelease
}
type HelmRelease struct {
Release string `json:"release"`
Namespace string `json:"namespace"`
}

@ -1,52 +0,0 @@
package list
import (
"encoding/json"
"fmt"
"net/http"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/servercontext"
)
func Handler() http.Handler {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.Header().Set("Content-Type", "application/json")
defer req.Body.Close()
var request ListRequest
decoder := json.NewDecoder(req.Body)
decoder.UseNumber()
if err := decoder.Decode(&request); err != nil {
fmt.Println("error in request")
return
}
request.RequestID = req.Header.Get("Request-Id")
list := action.NewList(servercontext.App().ActionConfig)
list.SetStateMask()
results, err := list.Run()
if err != nil {
fmt.Printf("error while running helm list %v", err)
}
var helmReleases []HelmRelease
for _, res := range results {
r := HelmRelease{Release: res.Name, Namespace: res.Namespace}
helmReleases = append(helmReleases, r)
}
response := ListRespose{Status: true, Data: helmReleases}
payload, err := json.Marshal(response)
if err != nil {
fmt.Println("error parsing response")
return
}
res.Write(payload)
})
}

@ -0,0 +1,109 @@
package api_test
import (
"fmt"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gotest.tools/assert"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/api"
"helm.sh/helm/v3/pkg/api/logger"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
type ListTestSuite struct {
suite.Suite
recorder *httptest.ResponseRecorder
server *httptest.Server
mockInstall *mockInstall
mockChartLoader *mockChartLoader
mockList *mockList
appConfig *cli.EnvSettings
}
type mockList struct{ mock.Mock }
func (m *mockList) Run() ([]*release.Release, error) {
args := m.Called()
return args.Get(0).([]*release.Release), args.Error(1)
}
func (m *mockList) SetStateMask() {
m.Called()
}
func (m *mockList) SetState(state action.ListStates) {
m.Called(state)
}
func (s *ListTestSuite) SetupSuite() {
logger.Setup("default")
}
func (s *ListTestSuite) SetupTest() {
s.recorder = httptest.NewRecorder()
s.mockList = new(mockList)
s.appConfig = &cli.EnvSettings{
RepositoryConfig: "./testdata/helm",
PluginsDirectory: "./testdata/helm/plugin",
}
service := api.NewService(s.appConfig, nil, s.mockList, nil, nil, nil)
handler := api.List(service)
s.server = httptest.NewServer(handler)
}
func (s *ListTestSuite) TestShouldReturnReleasesWhenSuccessfulAPICall() {
body := `{"release_status":"deployed"}`
req, _ := http.NewRequest("POST", fmt.Sprintf("%s/list", s.server.URL), strings.NewReader(body))
var releases []*release.Release
releases = append(releases,
&release.Release{Name: "test-release",
Namespace: "test-namespace",
Info: &release.Info{Status: release.StatusDeployed}})
s.mockList.On("SetStateMask")
s.mockList.On("SetState", action.ListDeployed)
s.mockList.On("Run").Return(releases, nil)
resp, err := http.DefaultClient.Do(req)
assert.Equal(s.T(), 200, resp.StatusCode)
expectedResponse := `{"Releases":[{"release":"test-release","namespace":"test-namespace"}]}`
respBody, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), expectedResponse, string(respBody))
require.NoError(s.T(), err)
s.mockList.AssertExpectations(s.T())
}
func (s *ListTestSuite) TestShouldReturnBadRequestErrorIfItHasInvalidCharacter() {
body := `{"request_id":"test-request-id""""}`
req, _ := http.NewRequest("POST", fmt.Sprintf("%s/list", s.server.URL), strings.NewReader(body))
resp, err := http.DefaultClient.Do(req)
assert.Equal(s.T(), 400, resp.StatusCode)
expectedResponse := `{"error":"invalid character '\"' after object key:value pair","Releases":null}`
respBody, _ := ioutil.ReadAll(resp.Body)
assert.Equal(s.T(), expectedResponse, string(respBody))
require.NoError(s.T(), err)
}
func (s *ListTestSuite) TearDownTest() {
s.server.Close()
}
func TestListAPI(t *testing.T) {
suite.Run(t, new(ListTestSuite))
}

@ -0,0 +1,24 @@
package api
import (
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/release"
)
type list struct {
*action.List
}
type lister interface {
Run() ([]*release.Release, error)
SetStateMask()
SetState(state action.ListStates)
}
func NewList(action *action.List) *list{
return &list{action}
}
func (l *list) SetState(state action.ListStates){
l.StateMask = state
}

@ -4,8 +4,12 @@ import (
"context"
"errors"
"fmt"
"strings"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/api/logger"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
@ -14,10 +18,6 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
type installer interface {
SetConfig(ReleaseConfig)
installrunner
}
type upgrader interface {
SetConfig(ReleaseConfig)
@ -29,15 +29,12 @@ type history interface {
historyrunner
}
type chartloader interface {
LocateChart(name string, settings *cli.EnvSettings) (string, error)
}
type Service struct {
settings *cli.EnvSettings
installer
upgrader
chartloader
lister
Installer
upgrader
history
}
@ -47,13 +44,13 @@ type ReleaseConfig struct {
ChartName string
}
type chartValues map[string]interface{}
type ChartValues map[string]interface{}
type ReleaseResult struct {
status string
Status string
}
func (s Service) getValues(vals chartValues) (chartValues, error) {
func (s Service) getValues(vals ChartValues) (ChartValues, error) {
// valueOpts := &values.Options{}
//valueOpts.Values = append(valueOpts.Values, vals)
//TODO: we need to make this as Provider, so it'll be able to merge
@ -61,7 +58,8 @@ func (s Service) getValues(vals chartValues) (chartValues, error) {
return vals, nil
}
func (s Service) Install(ctx context.Context, cfg ReleaseConfig, values chartValues) (*ReleaseResult, error) {
func (s Service) Install(ctx context.Context, cfg ReleaseConfig, values ChartValues) (*ReleaseResult, error) {
if err := s.validate(cfg, values); err != nil {
return nil, fmt.Errorf("error request validation: %v", err)
}
@ -76,7 +74,7 @@ func (s Service) Install(ctx context.Context, cfg ReleaseConfig, values chartVal
return s.installChart(cfg, chart, vals)
}
func (s Service) Upgrade(ctx context.Context, cfg ReleaseConfig, values chartValues) (*ReleaseResult, error) {
func (s Service) Upgrade(ctx context.Context, cfg ReleaseConfig, values ChartValues) (*ReleaseResult, error) {
if err := s.validate(cfg, values); err != nil {
return nil, fmt.Errorf("error request validation: %v", err)
}
@ -112,20 +110,22 @@ func (s Service) loadChart(chartName string) (*chart.Chart, error) {
return requestedChart, nil
}
func (s Service) installChart(icfg ReleaseConfig, ch *chart.Chart, vals chartValues) (*ReleaseResult, error) {
s.installer.SetConfig(icfg)
release, err := s.installer.Run(ch, vals)
func (s Service) installChart(icfg ReleaseConfig, ch *chart.Chart, vals ChartValues) (*ReleaseResult, error) {
s.Installer.SetConfig(icfg)
release, err := s.Installer.Run(ch, vals)
if err != nil {
return nil, fmt.Errorf("error in installing chart: %v", err)
}
result := new(ReleaseResult)
if release.Info != nil {
result.status = release.Info.Status.String()
result.Status = release.Info.Status.String()
}
return result, nil
}
func (s Service) upgradeRelease(ucfg ReleaseConfig, ch *chart.Chart, vals chartValues) (*ReleaseResult, error) {
func (s Service) upgradeRelease(ucfg ReleaseConfig, ch *chart.Chart, vals ChartValues) (*ReleaseResult, error) {
s.upgrader.SetConfig(ucfg)
release, err := s.upgrader.Run(ucfg.Name, ch, vals)
if err != nil {
@ -133,12 +133,12 @@ func (s Service) upgradeRelease(ucfg ReleaseConfig, ch *chart.Chart, vals chartV
}
result := new(ReleaseResult)
if release.Info != nil {
result.status = release.Info.Status.String()
result.Status = release.Info.Status.String()
}
return result, nil
}
func (s Service) validate(icfg ReleaseConfig, values chartValues) error {
func (s Service) validate(icfg ReleaseConfig, values ChartValues) error {
if strings.HasPrefix(icfg.ChartName, ".") ||
strings.HasPrefix(icfg.ChartName, "/") {
return errors.New("cannot refer local chart")
@ -146,12 +146,34 @@ func (s Service) validate(icfg ReleaseConfig, values chartValues) error {
return nil
}
func NewService(settings *cli.EnvSettings, cl chartloader, i installer, u upgrader, h history) Service {
return Service{
settings: settings,
chartloader: cl,
installer: i,
upgrader: u,
history: h,
func (s Service) List(releaseStatus string) ([]Release, error) {
listStates := new(action.ListStates)
state := action.ListAll
if releaseStatus != "" {
state = listStates.FromName(releaseStatus)
}
if state == action.ListUnknown {
return nil, errors.New("invalid release status")
}
s.lister.SetState(state)
s.lister.SetStateMask()
releases, err := s.lister.Run()
if err != nil {
return nil, err
}
var helmReleases []Release
for _, eachRes := range releases {
r := Release{Name: eachRes.Name, Namespace: eachRes.Namespace}
helmReleases = append(helmReleases, r)
}
return helmReleases, nil
}
func NewService(settings *cli.EnvSettings, cl chartloader, l lister, i Installer, u upgrader, h history) Service {
return Service{settings,cl, l,i, u, h}
}

@ -1,8 +1,10 @@
package api
package api_test
import (
"context"
"errors"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/api"
"testing"
"github.com/stretchr/testify/assert"
@ -19,33 +21,35 @@ import (
type ServiceTestSuite struct {
suite.Suite
ctx context.Context
installer *mockInstaller
upgrader *mockUpgrader
history *mockHistory
installer *mockInstall
chartloader *mockChartLoader
svc Service
lister *mockList
svc api.Service
settings *cli.EnvSettings
}
func (s *ServiceTestSuite) SetupTest() {
logger.Setup("")
s.ctx = context.Background()
s.installer = new(mockInstaller)
s.settings = &cli.EnvSettings{}
s.chartloader = new(mockChartLoader)
s.lister = new(mockList)
s.installer = new(mockInstall)
s.upgrader = new(mockUpgrader)
s.history = new(mockHistory)
s.chartloader = new(mockChartLoader)
s.settings = &cli.EnvSettings{}
s.svc = NewService(s.settings, s.chartloader, s.installer, s.upgrader, s.history)
s.ctx = context.Background()
s.svc = api.NewService(s.settings, s.chartloader, s.lister, s.installer, s.upgrader, s.history)
}
func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnInvalidChart() {
chartName := "stable/invalid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
}
var vals chartValues
var vals api.ChartValues
s.chartloader.On("LocateChart", chartName, s.settings).Return("", errors.New("Unable to find chart"))
res, err := s.svc.Install(s.ctx, cfg, vals)
@ -60,12 +64,12 @@ func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnInvalidChart() {
func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnLocalChartReference() {
chartName := "./some/local-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
}
var vals chartValues
var vals api.ChartValues
res, err := s.svc.Install(s.ctx, cfg, vals)
@ -79,7 +83,7 @@ func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnLocalChartReference() {
func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnFailedInstallRun() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -101,7 +105,7 @@ func (s *ServiceTestSuite) TestInstallShouldReturnErrorOnFailedInstallRun() {
func (s *ServiceTestSuite) TestInstallShouldReturnResultOnSuccess() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -117,14 +121,14 @@ func (s *ServiceTestSuite) TestInstallShouldReturnResultOnSuccess() {
t := s.T()
assert.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, res.status, "deployed")
assert.Equal(t, res.Status, "deployed")
s.chartloader.AssertExpectations(t)
s.installer.AssertExpectations(t)
}
func (s *ServiceTestSuite) TestUpgradeInstallTrueShouldInstallChart() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -142,14 +146,14 @@ func (s *ServiceTestSuite) TestUpgradeInstallTrueShouldInstallChart() {
t := s.T()
assert.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, res.status, "deployed")
assert.Equal(t, res.Status, "deployed")
s.chartloader.AssertExpectations(t)
s.installer.AssertExpectations(t)
}
func (s *ServiceTestSuite) TestUpgradeInstallFalseShouldNotInstallChart() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -168,14 +172,14 @@ func (s *ServiceTestSuite) TestUpgradeInstallFalseShouldNotInstallChart() {
require.NotNil(t, res)
s.installer.AssertNotCalled(t, "Run")
s.history.AssertNotCalled(t, "Run")
assert.Equal(t, res.status, "deployed")
assert.Equal(t, res.Status, "deployed")
s.chartloader.AssertExpectations(t)
s.installer.AssertExpectations(t)
}
func (s *ServiceTestSuite) TestUpgradeShouldReturnErrorOnFailedUpgradeRun() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -197,7 +201,7 @@ func (s *ServiceTestSuite) TestUpgradeShouldReturnErrorOnFailedUpgradeRun() {
func (s *ServiceTestSuite) TestUpgradeShouldReturnResultOnSuccess() {
chartName := "stable/valid-chart"
cfg := ReleaseConfig{
cfg := api.ReleaseConfig{
Name: "some-component",
Namespace: "hermes",
ChartName: chartName,
@ -213,52 +217,127 @@ func (s *ServiceTestSuite) TestUpgradeShouldReturnResultOnSuccess() {
t := s.T()
assert.NoError(t, err)
require.NotNil(t, res)
assert.Equal(t, res.status, "deployed")
assert.Equal(t, res.Status, "deployed")
s.chartloader.AssertExpectations(t)
s.upgrader.AssertExpectations(t)
}
func TestServiceSuite(t *testing.T) {
suite.Run(t, new(ServiceTestSuite))
func (s *ServiceTestSuite) TestListShouldReturnErrorOnFailureOfListRun() {
s.lister.On("SetState", action.ListDeployed)
s.lister.On("SetStateMask")
var releases []*release.Release
s.lister.On("Run").Return(releases, errors.New("cluster issue"))
releaseStatus := "deployed"
res, err := s.svc.List(releaseStatus)
t := s.T()
assert.Error(t, err, "cluster issue")
assert.Nil(t, res)
s.lister.AssertExpectations(t)
}
type mockChartLoader struct{ mock.Mock }
func (s *ServiceTestSuite) TestListShouldReturnAllReleasesIfNoFilterIsPassed() {
s.lister.On("SetState", action.ListAll)
s.lister.On("SetStateMask")
func (m *mockChartLoader) LocateChart(name string, settings *cli.EnvSettings) (string, error) {
args := m.Called(name, settings)
return args.String(0), args.Error(1)
var releases []*release.Release
releases = append(releases,
&release.Release{Name: "test-release",
Namespace: "test-namespace",
Info: &release.Info{Status: release.StatusDeployed}})
s.lister.On("Run").Return(releases, nil)
releaseStatus := ""
res, err := s.svc.List(releaseStatus)
t := s.T()
assert.NoError(t, err)
require.NotNil(t, res)
var response []api.Release
response = append(response, api.Release{"test-release", "test-namespace"})
assert.Equal(t, len(res), 1)
assert.Equal(t, "test-release", response[0].Name)
assert.Equal(t, "test-namespace", response[0].Namespace)
s.lister.AssertExpectations(t)
}
type mockInstaller struct{ mock.Mock }
func (s *ServiceTestSuite) TestListShouldReturnErrorIfInvalidStatusIsPassedAsFilter() {
releaseStatus := "invalid"
_, err := s.svc.List(releaseStatus)
type mockUpgrader struct{ mock.Mock }
t := s.T()
assert.Error(t, err, "invalid release status")
}
type mockHistory struct{ mock.Mock }
func (s *ServiceTestSuite) TestListShouldReturnDeployedReleasesIfDeployedIsPassedAsFilter() {
s.lister.On("SetState", action.ListDeployed)
s.lister.On("SetStateMask")
func (m *mockInstaller) SetConfig(cfg ReleaseConfig) {
var releases []*release.Release
s.lister.On("Run").Return(releases, nil)
releaseStatus := "deployed"
_, err := s.svc.List(releaseStatus)
t := s.T()
assert.NoError(t, err)
s.lister.AssertExpectations(t)
}
type mockInstall struct{ mock.Mock }
func (m *mockInstall) SetConfig(cfg api.ReleaseConfig) {
m.Called(cfg)
}
func (m *mockInstaller) Run(c *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
func (m *mockInstall) Run(c *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
args := m.Called(c, vals)
return args.Get(0).(*release.Release), args.Error(1)
}
func (m *mockUpgrader) GetInstall() bool {
args := m.Called()
return args.Get(0).(bool)
type mockChartLoader struct{ mock.Mock }
func (m *mockChartLoader) LocateChart(name string, settings *cli.EnvSettings) (string, error) {
args := m.Called(name, settings)
return args.String(0), args.Error(1)
}
type mockUpgrader struct{ mock.Mock }
func (m *mockUpgrader) Run(name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
args := m.Called(name, chart, vals)
return args.Get(0).(*release.Release), args.Error(1)
}
func (m *mockUpgrader) SetConfig(cfg ReleaseConfig) {
func (m *mockUpgrader) SetConfig(cfg api.ReleaseConfig) {
_ = m.Called(cfg)
}
func (m *mockUpgrader) GetInstall() bool {
args := m.Called()
return args.Get(0).(bool)
}
type mockHistory struct{ mock.Mock }
func (m *mockHistory) Run(name string) ([]*release.Release, error) {
args := m.Called(name)
return args.Get(0).([]*release.Release), args.Error(1)
}
func TestServiceSuite(t *testing.T) {
suite.Run(t, new(ServiceTestSuite))
}

@ -30,6 +30,7 @@ func Upgrade(svc Service) http.Handler {
w.WriteHeader(http.StatusBadRequest)
return
}
defer r.Body.Close()
var response UpgradeResponse
cfg := ReleaseConfig{ChartName: req.Chart, Name: req.Name, Namespace: req.Namespace}
@ -38,7 +39,7 @@ func Upgrade(svc Service) http.Handler {
respondError(w, "error while upgrading chart: %v", err)
return
}
response.Status = res.status
response.Status = res.Status
if err := json.NewEncoder(w).Encode(&response); err != nil {
logger.Errorf("[Upgrade] error writing response %v", err)
w.WriteHeader(http.StatusInternalServerError)

@ -15,7 +15,6 @@ import (
"gotest.tools/assert"
"helm.sh/helm/v3/pkg/api"
"helm.sh/helm/v3/pkg/api/logger"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
)
@ -43,7 +42,7 @@ func (s *UpgradeTestSuite) SetupTest() {
RepositoryConfig: "./testdata/helm",
PluginsDirectory: "./testdata/helm/plugin",
}
service := api.NewService(s.appConfig, s.mockChartLoader, nil, s.mockUpgrader, s.mockHistory)
service := api.NewService(s.appConfig, s.mockChartLoader, nil, nil, s.mockUpgrader, s.mockHistory)
handler := api.Upgrade(service)
s.server = httptest.NewServer(handler)
}
@ -105,26 +104,3 @@ func (s *UpgradeTestSuite) TearDownTest() {
func TestUpgradeAPI(t *testing.T) {
suite.Run(t, new(UpgradeTestSuite))
}
type mockUpgrader struct{ mock.Mock }
type mockHistory struct{ mock.Mock }
func (m *mockUpgrader) Run(name string, chart *chart.Chart, vals map[string]interface{}) (*release.Release, error) {
args := m.Called(name, chart, vals)
return args.Get(0).(*release.Release), args.Error(1)
}
func (m *mockUpgrader) GetInstall() bool {
args := m.Called()
return args.Get(0).(bool)
}
func (m *mockUpgrader) SetConfig(cfg api.ReleaseConfig) {
_ = m.Called(cfg)
}
func (m *mockHistory) Run(name string) ([]*release.Release, error) {
args := m.Called(name)
return args.Get(0).([]*release.Release), args.Error(1)
}

Loading…
Cancel
Save