Files
helm-dashboard/pkg/dashboard/api_test.go
Andrey Pokhilko e4240ed107 v2.0 with React-based frontend (#233)
* Correct path to static dir

* Add UI build to makefile

* Fix docker build

* describe now works

* Installed page - revision view - implement url consistent state logic (#403)

* refactor

* refactor

* Fix/responsive and small stylings (#404)

* add user defined (#405)

* Fix/modal loading button (#406)

* add repo to url (#407)

* Fix/resources table badges (#408)

* filters is now good

* fix

* test results fix

* fix

* fixes - error modal, uninstall modals, typees

* fixes

* bug fix

* Helm dashboard v2 (#402)

* missing config (#409)

* fixes

* fixes

* Fix/minor responsiveness (#410)

* installed release page

* default helm icon

* guard

* refactor

* refactor

* refactor

* key

* refactor

* fixes

* fixes to install

* install, add, upgrade, reconfigure now works

* latest ver fix

* Revision page ui fixes (#411)

* link color

* Add-repository-link (#412)

* empty badge fix

* diff fix in install repo

* removed console.log

* unique key in helathstatus

* Cosmetics

* Goreleaser upgraded

* Another way to fix it

* refactor

* refactor

* chart install fix (#413)

* more maintailable

* loading, empty space and default namespace

* typed

* loading diff state is shared

* modal height fix

* upgrade and add repo connected

* add repo suggestion data connected to modal

* removed console.log

* Chart install fix (#414)

* refactor: fix text align uninstall

* install modal values big fix

* refactor

* no changes in diff msg

* refactor

* sorted versions

* typography changes

* refactor

* refactor

* refactor

* migrate to sb 7 (#416)

* Chart install fix (#415)

* Add troubleshoot in komodor (#417)

* status style

* fix

* fixes

* delete now reload the page correclty

* navigate after add repo fix

* Chart install fix (#419)

* refactor

* refactor

* Fix revision age (#420)

* refactor

* fixed redirects and nav links selected ui (#421)

* test modal ui fixes

* arrows fix

* loading ui (#422)

* test dialog now shows errors

* fixed rollback diff, redirect after rollback, and debouncing before refetching chart values after changing user defined values (#423)

* everything is working besides install chart

* install chart should work now

* no need for this anymore

* styling and naming

* improvements

* navigation fix

* flow fixes

* top bar pixel perfect

* onClose is optional

* ts optional

* pixel perfect - clusters, box shadow, error modal

* installed page pixel perfect

* fixes

* need to fix this naming

* rollback logic is now good

* buttons now similiar to the old app

* pass release instead of release date (#426)

* repository page style fixes

* rounded input

* colors like in the old app

* more rounding

* colors

* colors

* Cosmetics

* drop-shadow cause the dropdown to swallowed

* smaller text

* fixes (#428)

* fixes

* describe fix

* Fix/lint (#431)

* style fixes

* fix

* describe panel style fixes

* diff when repo is available

* diff style fixes

* fixes to install dialog

* specific version should be latests revision

* refactor

* fixes

* fixes

* cause troubles

* Fixes (#434)

* fix

* dont fetch if repo not available

* tag should not be visible

* custom-shdaow fixes

* space and shadow like in the old app

* refactor (#435)

* describe display logic aligned with the old app

* style fix

* action button style fix

* selected revision default logic fix

* font fix

* style fixes

* shutdown button fix

* latest revision is now consistent in dev and prod

* namespace should be empty on install

* fix for current version on install

* sorting fix

* checkmark should be displayed in options - install

* state jump fix

* local charts (#436)

* Several more fixes (#438)

* api docs (#439)

* html remove diff2html dep (#437)

* Refactor

* refactor

* Adding storybook for StatusLabel component (#441)

* refactor (#442)

* we need the css

* add prettier (#440)

* add prettier

* refactor

* refactor

* Fix reconfigure issue (#443)

* first diff fetch fix

* missing dep in hooks (#444)

* namespace should be from query

* triggering diff rerender by listening to loading

* missing uservalues

* no need for auto retry

* we should work against latest revision

* refactor

* Fix build merge

* refactor

* refactor

* fix

* refactor

* refactor

* age tooltip

* prettier fix

* fix bug (#447)

* Add eslint now (#449)

* repo install chart now works as expected

* release modal and eslint working good now

* we should fetch when return to the initial value

* Tailwind theme reorganized (#446)

* install release code is like reading a story !

* namespace is not needed for chart values

* install repo chart is now like reading a story :)

* Fix/filternamesapce (#451)

* not needed dep

* prettier fix

* namespace fix

* add debounce (#452)

* namespace filter fix

* now namespace filter behaves like in the old app

* more linter rules and configurations

* intial value should be empty

* no need to keep filters on cluster change

* we don't want to keep tab state between pages

* button should be disabled when loading

* prettier fix

* initial value we're not presented

* navigation fix

* namespace should always be empty

* supporting pre selected namespaces

* lint adjustments

* Refactor stories fodler (#450)

* refactor

* refactor

* if no user values, use the release values

* Adding layer to base style (#456)

* Extract duplicate type to types file (#453)

* Refactor callApi into direct usage of apiService (#454)

* Remove scanners from backend

* Give some room for multiple HealthStatus (#458)

* refactor: add dynamic api docs (#460)

* remove scanners from openapi

* was loading forever

* fix

* Extract defined values from the Modals (#461)

* refactor (#462)

* fix chart with no repo diff flow

* naming fix

* crypto UUID not available through https

* revert

* Update analytics.js with UUID fallback

* Cosmetics

* repo fetch fix

* not need to depened on versions

* forgot to push

* revert

* was causing infinite loop

* COsmetics

---------

Co-authored-by: Nir Parisian <nir.parisian@gmail.com>
Co-authored-by: dav-sap <davidsaper@gmail.com>
Co-authored-by: chad11111 <chad1111@tutanota.com>
Co-authored-by: IdanSchiller <58664272+IdanSchiller@users.noreply.github.com>
Co-authored-by: dav-sap <16819417+dav-sap@users.noreply.github.com>
Co-authored-by: rotembm12 <46103618+rotembm12@users.noreply.github.com>
Co-authored-by: naorzr <naorzruk@gmail.com>
Co-authored-by: Gary Gensler <127234894+chad11111@users.noreply.github.com>
Co-authored-by: Tamir Abutbul <1tamir198@gmail.com>
Co-authored-by: Nir Parisian <nir2002@users.noreply.github.com>
2023-09-26 09:21:04 +01:00

390 lines
11 KiB
Go

package dashboard
import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"github.com/gin-gonic/gin"
"github.com/komodorio/helm-dashboard/pkg/dashboard/handlers"
"github.com/komodorio/helm-dashboard/pkg/dashboard/objects"
log "github.com/sirupsen/logrus"
"gotest.tools/v3/assert"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/cli"
kubefake "helm.sh/helm/v3/pkg/kube/fake"
"helm.sh/helm/v3/pkg/registry"
"helm.sh/helm/v3/pkg/storage"
"helm.sh/helm/v3/pkg/storage/driver"
)
var inMemStorage *storage.Storage
var repoFile string
func TestMain(m *testing.M) { // fixture to set logging level via env variable
if os.Getenv("DEBUG") != "" {
log.SetLevel(log.DebugLevel)
log.Debugf("Set logging level")
}
inMemStorage = storage.Init(driver.NewMemory())
d, err := os.MkdirTemp("", "helm")
if err != nil {
panic(err)
}
repoFile = filepath.Join(d, "repositories.yaml")
m.Run()
inMemStorage = nil
repoFile = ""
}
func GetTestGinContext(w *httptest.ResponseRecorder) *gin.Context {
gin.SetMode(gin.TestMode)
ctx, _ := gin.CreateTestContext(w)
ctx.Request = &http.Request{
Header: make(http.Header),
}
return ctx
}
func TestNoCacheMiddleware(t *testing.T) {
w := httptest.NewRecorder()
con := GetTestGinContext(w)
noCache(con)
assert.Equal(t, w.Header().Get("Cache-Control"), "no-cache")
}
func TestEnableCacheControl(t *testing.T) {
w := httptest.NewRecorder()
con := GetTestGinContext(w)
// Sets deafault policy to `no-cache`
noCache(con)
h := handlers.HelmHandler{
Contexted: &handlers.Contexted{
Data: &objects.DataLayer{},
},
}
h.EnableClientCache(con)
assert.Equal(t, w.Header().Get("Cache-Control"), "max-age=43200")
}
func TestConfigureStatic(t *testing.T) {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
}
// Create an API Engine
api := gin.Default()
// Configure static routes
configureStatic(api)
// Start the server
api.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
}
func TestConfigureRoutes(t *testing.T) {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/status", nil)
if err != nil {
t.Fatal(err)
}
// Create a API Engine
api := gin.Default()
// Required arguments for route configuration
abortWeb := func() {}
data, err := objects.NewDataLayer([]string{"TestSpace"}, "T-1", NewHelmConfig, false)
if err != nil {
t.Fatal(err)
}
// Configure routes to API engine
configureRoutes(abortWeb, data, api)
// Start the server
api.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
}
func TestContextSetter(t *testing.T) {
w := httptest.NewRecorder()
con := GetTestGinContext(w)
// Required arguments
data, err := objects.NewDataLayer([]string{"TestSpace"}, "T-1", NewHelmConfig, false)
if err != nil {
t.Fatal(err)
}
// Set the context
ctxHandler := contextSetter(data)
ctxHandler(con)
appName, exists := con.Get("app")
if !exists {
t.Fatal("Value app doesn't exist in context")
}
tmp := handlers.Contexted{Data: data}
assert.Equal(t, appName, tmp.GetApp(con))
}
func TestNewRouter(t *testing.T) {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/status", nil)
if err != nil {
t.Fatal(err)
}
// Required arguemnets
abortWeb := func() {}
data, err := objects.NewDataLayer([]string{"TestSpace"}, "T-1", NewHelmConfig, false)
if err != nil {
t.Fatal(err)
}
// Create a new router with the function
newRouter := NewRouter(abortWeb, data, false)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
}
func TestConfigureKubectls(t *testing.T) {
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/api/kube/contexts", nil)
if err != nil {
t.Fatal(err)
}
// Required arguemnets
data, err := objects.NewDataLayer([]string{"TestSpace"}, "T-1", NewHelmConfig, false)
if err != nil {
t.Fatal(err)
}
apiEngine := gin.Default()
// Required middleware for kubectl api configuration
apiEngine.Use(contextSetter(data))
configureKubectls(apiEngine.Group("/api/kube"), data)
apiEngine.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
}
func TestE2E(t *testing.T) {
// Initialize data layer
data, err := objects.NewDataLayer([]string{""}, "0.0.0-test", getFakeHelmConfig, false)
assert.NilError(t, err)
// Create a new router with the function
abortWeb := func() {}
newRouter := NewRouter(abortWeb, data, false)
// initially, we don't have any releases
w := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/api/helm/releases", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
assert.Equal(t, w.Body.String(), "[]")
// initially, we don't have any repositories
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/repositories", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
assert.Equal(t, w.Body.String(), "[]")
// then we add one repository
w = httptest.NewRecorder()
form := url.Values{}
form.Add("name", "komodorio")
form.Add("url", "https://helm-charts.komodor.io")
req, err = http.NewRequest("POST", "/api/helm/repositories", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusNoContent)
assert.Equal(t, w.Body.String(), "")
// now, we have one repo
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/repositories", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
assert.Equal(t, w.Body.String(), `[
{
"name": "komodorio",
"url": "https://helm-charts.komodor.io"
}
]`)
// what's the latest version of that chart
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/repositories/latestver?name=helm-dashboard", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
// generate template for potential release
w = httptest.NewRecorder()
form = url.Values{}
form.Add("preview", "true")
form.Add("name", "release1")
form.Add("chart", "komodorio/helm-dashboard")
req, err = http.NewRequest("POST", "/api/helm/releases/test1", strings.NewReader(form.Encode()))
assert.NilError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
// install the release
w = httptest.NewRecorder()
form = url.Values{}
form.Add("name", "release1")
form.Add("chart", "komodorio/helm-dashboard")
req, err = http.NewRequest("POST", "/api/helm/releases/test1", strings.NewReader(form.Encode()))
assert.NilError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusAccepted)
// get list of releases
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/releases", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
t.Logf("Release: %s", w.Body.String())
//assert.Equal(t, w.Body.String(), "[]")
// upgrade/reconfigure release
w = httptest.NewRecorder()
form = url.Values{}
form.Add("chart", "komodorio/helm-dashboard")
form.Add("values", "dashboard:\n allowWriteActions: true\n")
req, err = http.NewRequest("POST", "/api/helm/releases/test1/release1", strings.NewReader(form.Encode()))
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
assert.Equal(t, w.Code, http.StatusAccepted)
// get history of revisions for release
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/releases/test1/release1/history", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
t.Logf("Revs: %s", w.Body.String())
//assert.Equal(t, w.Body.String(), "[]")
// get values for revision
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/releases/test1/release1/values?revision=2&userDefined=true", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
//assert.Equal(t, w.Body.String(), "[]")
// rollback
w = httptest.NewRecorder()
form = url.Values{}
form.Add("revision", "1")
req, err = http.NewRequest("POST", "/api/helm/releases/test1/release1/rollback", strings.NewReader(form.Encode()))
assert.NilError(t, err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusAccepted)
// get manifest diff for release
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/releases/test1/release1/manifests?revision=1&revisionDiff=2", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
//assert.Equal(t, w.Body.String(), "[]")
// delete repo
w = httptest.NewRecorder()
req, err = http.NewRequest("DELETE", "/api/helm/repositories/komodorio", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusNoContent)
// reconfigure release without repo connection
w = httptest.NewRecorder()
form = url.Values{}
form.Add("chart", "komodorio/helm-dashboard")
form.Add("values", "dashboard:\n allowWriteActions: false\n")
req, err = http.NewRequest("POST", "/api/helm/releases/test1/release1", strings.NewReader(form.Encode()))
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
assert.Equal(t, w.Code, http.StatusAccepted)
t.Logf("Upgraded: %s", w.Body.String())
// uninstall
w = httptest.NewRecorder()
req, err = http.NewRequest("DELETE", "/api/helm/releases/test1/release1", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusAccepted)
// check we don't have releases again
w = httptest.NewRecorder()
req, err = http.NewRequest("GET", "/api/helm/releases", nil)
assert.NilError(t, err)
newRouter.ServeHTTP(w, req)
assert.Equal(t, w.Code, http.StatusOK)
assert.Equal(t, w.Body.String(), "[]")
}
func getFakeHelmConfig(settings *cli.EnvSettings, _ string) (*action.Configuration, error) {
settings.RepositoryConfig = repoFile
registryClient, err := registry.NewClient()
if err != nil {
return nil, err
}
return &action.Configuration{
Releases: inMemStorage,
KubeClient: &kubefake.FailingKubeClient{PrintingKubeClient: kubefake.PrintingKubeClient{Out: os.Stderr}},
Capabilities: chartutil.DefaultCapabilities,
RegistryClient: registryClient,
Log: log.Infof,
}, nil
}