package edgestacks import ( "os" "strconv" "testing" "time" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/apikey" "github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/filesystem" "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/internal/edge/edgestacks" "github.com/portainer/portainer/api/internal/testhelpers" "github.com/portainer/portainer/api/jwt" "github.com/pkg/errors" ) // Helpers func setupHandler(t *testing.T) (*Handler, string) { t.Helper() _, store := datastore.MustNewTestStore(t, true, true) jwtService, err := jwt.NewService("1h", store) if err != nil { t.Fatal(err) } user := &portainer.User{ID: 2, Username: "admin", Role: portainer.AdministratorRole} if err := store.User().Create(user); err != nil { t.Fatal(err) } apiKeyService := apikey.NewAPIKeyService(store.APIKeyRepository(), store.User()) rawAPIKey, _, err := apiKeyService.GenerateApiKey(*user, "test") if err != nil { t.Fatal(err) } tmpDir, err := os.MkdirTemp(t.TempDir(), "portainer-test") if err != nil { t.Fatal(err) } fs, err := filesystem.NewService(tmpDir, "") if err != nil { t.Fatal(err) } handler := NewHandler( security.NewRequestBouncer(store, jwtService, apiKeyService), store, edgestacks.NewService(store), ) handler.FileService = fs settings, err := handler.DataStore.Settings().Settings() if err != nil { t.Fatal(err) } settings.EnableEdgeComputeFeatures = true if err := handler.DataStore.Settings().UpdateSettings(settings); err != nil { t.Fatal(err) } handler.GitService = testhelpers.NewGitService(errors.New("Clone error"), "git-service-id") return handler, rawAPIKey } func createEndpointWithId(t *testing.T, store dataservices.DataStore, endpointID portainer.EndpointID) portainer.Endpoint { t.Helper() endpoint := portainer.Endpoint{ ID: endpointID, Name: "test-endpoint-" + strconv.Itoa(int(endpointID)), Type: portainer.EdgeAgentOnDockerEnvironment, URL: "https://portainer.io:9443", EdgeID: "edge-id", LastCheckInDate: time.Now().Unix(), } if err := store.Endpoint().Create(&endpoint); err != nil { t.Fatal(err) } return endpoint } func createEndpoint(t *testing.T, store dataservices.DataStore) portainer.Endpoint { return createEndpointWithId(t, store, 5) } func createEdgeStack(t *testing.T, store dataservices.DataStore, endpointID portainer.EndpointID) portainer.EdgeStack { t.Helper() edgeGroup := portainer.EdgeGroup{ ID: 1, Name: "EdgeGroup 1", Dynamic: false, TagIDs: nil, Endpoints: []portainer.EndpointID{endpointID}, PartialMatch: false, } if err := store.EdgeGroup().Create(&edgeGroup); err != nil { t.Fatal(err) } edgeStackID := portainer.EdgeStackID(14) edgeStack := portainer.EdgeStack{ ID: edgeStackID, Name: "test-edge-stack-" + strconv.Itoa(int(edgeStackID)), Status: map[portainer.EndpointID]portainer.EdgeStackStatus{}, CreationDate: time.Now().Unix(), EdgeGroups: []portainer.EdgeGroupID{edgeGroup.ID}, ProjectPath: "/project/path", EntryPoint: "entrypoint", Version: 237, ManifestPath: "/manifest/path", DeploymentType: portainer.EdgeStackDeploymentKubernetes, } endpointRelation := portainer.EndpointRelation{ EndpointID: endpointID, EdgeStacks: map[portainer.EdgeStackID]bool{ edgeStack.ID: true, }, } if err := store.EdgeStack().Create(edgeStack.ID, &edgeStack); err != nil { t.Fatal(err) } if err := store.EndpointRelation().Create(&endpointRelation); err != nil { t.Fatal(err) } return edgeStack }