251 lines
8.4 KiB
Go
251 lines
8.4 KiB
Go
package deployments
|
|
|
|
// import (
|
|
// "errors"
|
|
// "strings"
|
|
// "testing"
|
|
|
|
// "github.com/portainer/portainer/api/datastore"
|
|
|
|
// portainer "github.com/portainer/portainer/api"
|
|
// gittypes "github.com/portainer/portainer/api/git/types"
|
|
// "github.com/stretchr/testify/assert"
|
|
// )
|
|
|
|
// type gitService struct {
|
|
// cloneErr error
|
|
// id string
|
|
// }
|
|
|
|
// func (g *gitService) CloneRepository(destination, repositoryURL, referenceName, username, password string) error {
|
|
// return g.cloneErr
|
|
// }
|
|
|
|
// func (g *gitService) LatestCommitID(repositoryURL, referenceName, username, password string) (string, error) {
|
|
// return g.id, nil
|
|
// }
|
|
|
|
// func (g *gitService) ListRefs(repositoryURL, username, password string, hardRefresh bool) ([]string, error) {
|
|
// return nil, nil
|
|
// }
|
|
|
|
// func (g *gitService) ListFiles(repositoryURL, referenceName, username, password string, hardRefresh bool, includedExts []string) ([]string, error) {
|
|
// return nil, nil
|
|
// }
|
|
|
|
// type noopDeployer struct{}
|
|
|
|
// func (s *noopDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune bool, pullImage bool) error {
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *noopDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage bool, forceRereate bool) error {
|
|
// return nil
|
|
// }
|
|
|
|
// func (s *noopDeployer) DeployKubernetesStack(stack *portainer.Stack, endpoint *portainer.Endpoint, user *portainer.User) error {
|
|
// return nil
|
|
// }
|
|
|
|
// func Test_redeployWhenChanged_FailsWhenCannotFindStack(t *testing.T) {
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// err := RedeployWhenChanged(1, nil, store, nil)
|
|
// assert.Error(t, err)
|
|
// assert.Truef(t, strings.HasPrefix(err.Error(), "failed to get the stack"), "it isn't an error we expected: %v", err.Error())
|
|
// }
|
|
|
|
// func Test_redeployWhenChanged_DoesNothingWhenNotAGitBasedStack(t *testing.T) {
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// admin := &portainer.User{ID: 1, Username: "admin"}
|
|
// err := store.User().Create(admin)
|
|
// assert.NoError(t, err, "error creating an admin")
|
|
|
|
// err = store.Stack().Create(&portainer.Stack{ID: 1, CreatedBy: "admin"})
|
|
// assert.NoError(t, err, "failed to create a test stack")
|
|
|
|
// err = RedeployWhenChanged(1, nil, store, &gitService{nil, ""})
|
|
// assert.NoError(t, err)
|
|
// }
|
|
|
|
// func Test_redeployWhenChanged_DoesNothingWhenNoGitChanges(t *testing.T) {
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// tmpDir := t.TempDir()
|
|
|
|
// admin := &portainer.User{ID: 1, Username: "admin"}
|
|
// err := store.User().Create(admin)
|
|
// assert.NoError(t, err, "error creating an admin")
|
|
|
|
// err = store.Stack().Create(&portainer.Stack{
|
|
// ID: 1,
|
|
// CreatedBy: "admin",
|
|
// ProjectPath: tmpDir,
|
|
// GitConfig: &gittypes.RepoConfig{
|
|
// URL: "url",
|
|
// ReferenceName: "ref",
|
|
// ConfigHash: "oldHash",
|
|
// }})
|
|
// assert.NoError(t, err, "failed to create a test stack")
|
|
|
|
// err = RedeployWhenChanged(1, nil, store, &gitService{nil, "oldHash"})
|
|
// assert.NoError(t, err)
|
|
// }
|
|
|
|
// func Test_redeployWhenChanged_FailsWhenCannotClone(t *testing.T) {
|
|
// cloneErr := errors.New("failed to clone")
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// admin := &portainer.User{ID: 1, Username: "admin"}
|
|
// err := store.User().Create(admin)
|
|
// assert.NoError(t, err, "error creating an admin")
|
|
|
|
// err = store.Stack().Create(&portainer.Stack{
|
|
// ID: 1,
|
|
// CreatedBy: "admin",
|
|
// GitConfig: &gittypes.RepoConfig{
|
|
// URL: "url",
|
|
// ReferenceName: "ref",
|
|
// ConfigHash: "oldHash",
|
|
// }})
|
|
// assert.NoError(t, err, "failed to create a test stack")
|
|
|
|
// err = RedeployWhenChanged(1, nil, store, &gitService{cloneErr, "newHash"})
|
|
// assert.Error(t, err)
|
|
// assert.ErrorIs(t, err, cloneErr, "should failed to clone but didn't, check test setup")
|
|
// }
|
|
|
|
// func Test_redeployWhenChanged(t *testing.T) {
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// tmpDir := t.TempDir()
|
|
|
|
// err := store.Endpoint().Create(&portainer.Endpoint{ID: 1})
|
|
// assert.NoError(t, err, "error creating environment")
|
|
|
|
// username := "user"
|
|
// err = store.User().Create(&portainer.User{Username: username, Role: portainer.AdministratorRole})
|
|
// assert.NoError(t, err, "error creating a user")
|
|
|
|
// stack := portainer.Stack{
|
|
// ID: 1,
|
|
// EndpointID: 1,
|
|
// ProjectPath: tmpDir,
|
|
// UpdatedBy: username,
|
|
// GitConfig: &gittypes.RepoConfig{
|
|
// URL: "url",
|
|
// ReferenceName: "ref",
|
|
// ConfigHash: "oldHash",
|
|
// }}
|
|
// err = store.Stack().Create(&stack)
|
|
// assert.NoError(t, err, "failed to create a test stack")
|
|
|
|
// t.Run("can deploy docker compose stack", func(t *testing.T) {
|
|
// stack.Type = portainer.DockerComposeStack
|
|
// store.Stack().UpdateStack(stack.ID, &stack)
|
|
|
|
// err = RedeployWhenChanged(1, &noopDeployer{}, store, &gitService{nil, "newHash"})
|
|
// assert.NoError(t, err)
|
|
// })
|
|
|
|
// t.Run("can deploy docker swarm stack", func(t *testing.T) {
|
|
// stack.Type = portainer.DockerSwarmStack
|
|
// store.Stack().UpdateStack(stack.ID, &stack)
|
|
|
|
// err = RedeployWhenChanged(1, &noopDeployer{}, store, &gitService{nil, "newHash"})
|
|
// assert.NoError(t, err)
|
|
// })
|
|
|
|
// t.Run("can deploy kube app", func(t *testing.T) {
|
|
// stack.Type = portainer.KubernetesStack
|
|
// store.Stack().UpdateStack(stack.ID, &stack)
|
|
|
|
// err = RedeployWhenChanged(1, &noopDeployer{}, store, &gitService{nil, "newHash"})
|
|
// assert.NoError(t, err)
|
|
// })
|
|
// }
|
|
|
|
// func Test_getUserRegistries(t *testing.T) {
|
|
// _, store, teardown := datastore.MustNewTestStore(t, true, true)
|
|
// defer teardown()
|
|
|
|
// endpointID := 123
|
|
|
|
// admin := &portainer.User{ID: 1, Username: "admin", Role: portainer.AdministratorRole}
|
|
// err := store.User().Create(admin)
|
|
// assert.NoError(t, err, "error creating an admin")
|
|
|
|
// user := &portainer.User{ID: 2, Username: "user", Role: portainer.StandardUserRole}
|
|
// err = store.User().Create(user)
|
|
// assert.NoError(t, err, "error creating a user")
|
|
|
|
// team := portainer.Team{ID: 1, Name: "team"}
|
|
|
|
// store.TeamMembership().Create(&portainer.TeamMembership{
|
|
// ID: 1,
|
|
// UserID: user.ID,
|
|
// TeamID: team.ID,
|
|
// Role: portainer.TeamMember,
|
|
// })
|
|
|
|
// registryReachableByUser := portainer.Registry{
|
|
// ID: 1,
|
|
// Name: "registryReachableByUser",
|
|
// RegistryAccesses: portainer.RegistryAccesses{
|
|
// portainer.EndpointID(endpointID): {
|
|
// UserAccessPolicies: map[portainer.UserID]portainer.AccessPolicy{
|
|
// user.ID: {RoleID: portainer.RoleID(portainer.StandardUserRole)},
|
|
// },
|
|
// },
|
|
// },
|
|
// }
|
|
// err = store.Registry().Create(®istryReachableByUser)
|
|
// assert.NoError(t, err, "couldn't create a registry")
|
|
|
|
// registryReachableByTeam := portainer.Registry{
|
|
// ID: 2,
|
|
// Name: "registryReachableByTeam",
|
|
// RegistryAccesses: portainer.RegistryAccesses{
|
|
// portainer.EndpointID(endpointID): {
|
|
// TeamAccessPolicies: map[portainer.TeamID]portainer.AccessPolicy{
|
|
// team.ID: {RoleID: portainer.RoleID(portainer.StandardUserRole)},
|
|
// },
|
|
// },
|
|
// },
|
|
// }
|
|
// err = store.Registry().Create(®istryReachableByTeam)
|
|
// assert.NoError(t, err, "couldn't create a registry")
|
|
|
|
// registryRestricted := portainer.Registry{
|
|
// ID: 3,
|
|
// Name: "registryRestricted",
|
|
// RegistryAccesses: portainer.RegistryAccesses{
|
|
// portainer.EndpointID(endpointID): {
|
|
// UserAccessPolicies: map[portainer.UserID]portainer.AccessPolicy{
|
|
// user.ID + 100: {RoleID: portainer.RoleID(portainer.StandardUserRole)},
|
|
// },
|
|
// },
|
|
// },
|
|
// }
|
|
// err = store.Registry().Create(®istryRestricted)
|
|
// assert.NoError(t, err, "couldn't create a registry")
|
|
|
|
// t.Run("admin should has access to all registries", func(t *testing.T) {
|
|
// registries, err := getUserRegistries(store, admin, portainer.EndpointID(endpointID))
|
|
// assert.NoError(t, err)
|
|
// assert.ElementsMatch(t, []portainer.Registry{registryReachableByUser, registryReachableByTeam, registryRestricted}, registries)
|
|
// })
|
|
|
|
// t.Run("regular user has access to registries allowed to him and/or his team", func(t *testing.T) {
|
|
// registries, err := getUserRegistries(store, user, portainer.EndpointID(endpointID))
|
|
// assert.NoError(t, err)
|
|
// assert.ElementsMatch(t, []portainer.Registry{registryReachableByUser, registryReachableByTeam}, registries)
|
|
// })
|
|
// }
|