354 lines
9.9 KiB
Go
354 lines
9.9 KiB
Go
package sources
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
portainer "github.com/portainer/portainer/api"
|
|
"github.com/portainer/portainer/api/dataservices"
|
|
"github.com/portainer/portainer/api/datastore"
|
|
gittypes "github.com/portainer/portainer/api/git/types"
|
|
|
|
"github.com/segmentio/encoding/json"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestGitSourceUpdate_Success(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{Name: "old-name", Type: portainer.SourceTypeGit}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/new.git",
|
|
Name: "new-name",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusOK, rr.Code)
|
|
|
|
var src portainer.Source
|
|
err = json.NewDecoder(rr.Body).Decode(&src)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "new-name", src.Name)
|
|
require.NotNil(t, src.GitConfig)
|
|
require.Equal(t, "https://github.com/org/new.git", src.GitConfig.URL)
|
|
}
|
|
|
|
func TestGitSourceUpdate_DerivesNameFromURL(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{Name: "old-name", Type: portainer.SourceTypeGit}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/my-project.git",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusOK, rr.Code)
|
|
|
|
var src portainer.Source
|
|
err = json.NewDecoder(rr.Body).Decode(&src)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "my-project", src.Name)
|
|
}
|
|
|
|
func TestGitSourceUpdate_PreservesAuthWhenNotProvided(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{
|
|
Name: "auth-source",
|
|
Type: portainer.SourceTypeGit,
|
|
GitConfig: &gittypes.RepoConfig{
|
|
URL: "https://github.com/org/repo.git",
|
|
Authentication: &gittypes.GitAuthentication{
|
|
Username: "alice",
|
|
Password: "secret",
|
|
},
|
|
},
|
|
}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/repo.git",
|
|
Name: "renamed",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusOK, rr.Code)
|
|
|
|
var stored *portainer.Source
|
|
require.NoError(t, store.ViewTx(func(tx dataservices.DataStoreTx) error {
|
|
var err error
|
|
stored, err = tx.Source().Read(srcID)
|
|
return err
|
|
}))
|
|
require.NotNil(t, stored.GitConfig)
|
|
require.NotNil(t, stored.GitConfig.Authentication)
|
|
require.Equal(t, "alice", stored.GitConfig.Authentication.Username)
|
|
require.Equal(t, "secret", stored.GitConfig.Authentication.Password)
|
|
}
|
|
|
|
func TestGitSourceUpdate_ClearsAuthWhenRequested(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{
|
|
Name: "auth-source",
|
|
Type: portainer.SourceTypeGit,
|
|
GitConfig: &gittypes.RepoConfig{
|
|
URL: "https://github.com/org/repo.git",
|
|
Authentication: &gittypes.GitAuthentication{
|
|
Username: "alice",
|
|
Password: "secret",
|
|
},
|
|
},
|
|
}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/repo.git",
|
|
Authentication: &GitAuthenticationPayload{},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusOK, rr.Code)
|
|
|
|
var stored *portainer.Source
|
|
require.NoError(t, store.ViewTx(func(tx dataservices.DataStoreTx) error {
|
|
var err error
|
|
stored, err = tx.Source().Read(srcID)
|
|
return err
|
|
}))
|
|
require.NotNil(t, stored.GitConfig)
|
|
require.Nil(t, stored.GitConfig.Authentication)
|
|
}
|
|
|
|
func TestGitSourceUpdate_ReplacesAuthWhenProvided(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{
|
|
Name: "auth-source",
|
|
Type: portainer.SourceTypeGit,
|
|
GitConfig: &gittypes.RepoConfig{
|
|
URL: "https://github.com/org/repo.git",
|
|
Authentication: &gittypes.GitAuthentication{
|
|
Username: "alice",
|
|
Password: "secret",
|
|
},
|
|
},
|
|
}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/repo.git",
|
|
Authentication: &GitAuthenticationPayload{
|
|
Username: "bob",
|
|
Password: "new-secret",
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusOK, rr.Code)
|
|
|
|
var stored *portainer.Source
|
|
require.NoError(t, store.ViewTx(func(tx dataservices.DataStoreTx) error {
|
|
var err error
|
|
stored, err = tx.Source().Read(srcID)
|
|
return err
|
|
}))
|
|
require.NotNil(t, stored.GitConfig)
|
|
require.NotNil(t, stored.GitConfig.Authentication)
|
|
require.Equal(t, "bob", stored.GitConfig.Authentication.Username)
|
|
require.Equal(t, "new-secret", stored.GitConfig.Authentication.Password)
|
|
}
|
|
|
|
func TestGitSourceUpdate_NotFound(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{URL: "https://github.com/org/repo.git"})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, 99, body))
|
|
|
|
require.Equal(t, http.StatusNotFound, rr.Code)
|
|
}
|
|
|
|
func TestGitSourceUpdate_ConflictOnDuplicateURL(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
existing := &portainer.Source{
|
|
Name: "existing",
|
|
Type: portainer.SourceTypeGit,
|
|
GitConfig: &gittypes.RepoConfig{
|
|
URL: "https://github.com/org/existing.git",
|
|
},
|
|
}
|
|
err := tx.Source().Create(existing)
|
|
require.NoError(t, err)
|
|
|
|
src := &portainer.Source{Name: "other", Type: portainer.SourceTypeGit}
|
|
err = tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{
|
|
URL: "https://github.com/org/existing.git",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusConflict, rr.Code)
|
|
}
|
|
|
|
func TestGitSourceUpdate_NotGitSource(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{Name: "helm-source", Type: portainer.SourceTypeHelm}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{URL: "https://github.com/org/repo.git"})
|
|
require.NoError(t, err)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), body))
|
|
|
|
require.Equal(t, http.StatusBadRequest, rr.Code)
|
|
}
|
|
|
|
func TestGitSourceUpdate_MalformedJSON(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
var srcID portainer.SourceID
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
src := &portainer.Source{Name: "src", Type: portainer.SourceTypeGit}
|
|
err := tx.Source().Create(src)
|
|
require.NoError(t, err)
|
|
srcID = src.ID
|
|
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, buildUpdateReq(t, 1, int(srcID), []byte("not-valid-json{")))
|
|
|
|
require.Equal(t, http.StatusBadRequest, rr.Code)
|
|
}
|
|
|
|
func TestGitSourceUpdate_NonNumericID(t *testing.T) {
|
|
t.Parallel()
|
|
_, store := datastore.MustNewTestStore(t, false, true)
|
|
|
|
require.NoError(t, store.UpdateTx(func(tx dataservices.DataStoreTx) error {
|
|
return tx.User().Create(&portainer.User{ID: 1, Role: portainer.AdministratorRole})
|
|
}))
|
|
|
|
h := newTestHandler(t, store)
|
|
|
|
body, err := json.Marshal(GitSourceCreatePayload{URL: "https://github.com/org/repo.git"})
|
|
require.NoError(t, err)
|
|
|
|
req := buildUpdateReqWithRawID(t, 1, "not-a-number", body)
|
|
rr := httptest.NewRecorder()
|
|
h.ServeHTTP(rr, req)
|
|
|
|
require.Equal(t, http.StatusBadRequest, rr.Code)
|
|
}
|