mirror of https://github.com/portainer/portainer
refactor(api): use a standard stack identifier (#1980)
parent
da5a430b8c
commit
b4c2820ad7
|
@ -31,6 +31,7 @@ type Store struct {
|
||||||
|
|
||||||
db *bolt.DB
|
db *bolt.DB
|
||||||
checkForDataMigration bool
|
checkForDataMigration bool
|
||||||
|
FileService portainer.FileService
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -50,7 +51,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewStore initializes a new Store and the associated services
|
// NewStore initializes a new Store and the associated services
|
||||||
func NewStore(storePath string) (*Store, error) {
|
func NewStore(storePath string, fileService portainer.FileService) (*Store, error) {
|
||||||
store := &Store{
|
store := &Store{
|
||||||
Path: storePath,
|
Path: storePath,
|
||||||
UserService: &UserService{},
|
UserService: &UserService{},
|
||||||
|
@ -65,6 +66,7 @@ func NewStore(storePath string) (*Store, error) {
|
||||||
DockerHubService: &DockerHubService{},
|
DockerHubService: &DockerHubService{},
|
||||||
StackService: &StackService{},
|
StackService: &StackService{},
|
||||||
TagService: &TagService{},
|
TagService: &TagService{},
|
||||||
|
FileService: fileService,
|
||||||
}
|
}
|
||||||
store.UserService.store = store
|
store.UserService.store = store
|
||||||
store.TeamService.store = store
|
store.TeamService.store = store
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
package bolt
|
package bolt
|
||||||
|
|
||||||
import "github.com/portainer/portainer"
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/boltdb/bolt"
|
||||||
|
"github.com/portainer/portainer"
|
||||||
|
"github.com/portainer/portainer/bolt/internal"
|
||||||
|
)
|
||||||
|
|
||||||
func (m *Migrator) updateEndpointsToVersion12() error {
|
func (m *Migrator) updateEndpointsToVersion12() error {
|
||||||
legacyEndpoints, err := m.EndpointService.Endpoints()
|
legacyEndpoints, err := m.EndpointService.Endpoints()
|
||||||
|
@ -38,16 +45,24 @@ func (m *Migrator) updateEndpointGroupsToVersion12() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type legacyStack struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
EndpointID portainer.EndpointID `json:"EndpointId"`
|
||||||
|
SwarmID string `json:"SwarmId"`
|
||||||
|
EntryPoint string `json:"EntryPoint"`
|
||||||
|
Env []portainer.Pair `json:"Env"`
|
||||||
|
ProjectPath string
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Migrator) updateStacksToVersion12() error {
|
func (m *Migrator) updateStacksToVersion12() error {
|
||||||
legacyStacks, err := m.StackService.Stacks()
|
legacyStacks, err := m.retrieveLegacyStacks()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, stack := range legacyStacks {
|
for _, legacyStack := range legacyStacks {
|
||||||
stack.Type = portainer.DockerSwarmStack
|
err := m.convertLegacyStack(&legacyStack)
|
||||||
|
|
||||||
err = m.StackService.UpdateStack(stack.ID, &stack)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -55,3 +70,64 @@ func (m *Migrator) updateStacksToVersion12() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) convertLegacyStack(s *legacyStack) error {
|
||||||
|
stackID := m.StackService.GetNextIdentifier()
|
||||||
|
stack := &portainer.Stack{
|
||||||
|
ID: portainer.StackID(stackID),
|
||||||
|
Name: s.Name,
|
||||||
|
Type: portainer.DockerSwarmStack,
|
||||||
|
SwarmID: s.SwarmID,
|
||||||
|
EndpointID: 0,
|
||||||
|
EntryPoint: s.EntryPoint,
|
||||||
|
Env: s.Env,
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.ProjectPath = strings.Replace(s.ProjectPath, s.ID, strconv.Itoa(stackID), 1)
|
||||||
|
err := m.store.FileService.Rename(s.ProjectPath, stack.ProjectPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = m.deleteLegacyStack(s.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return m.StackService.CreateStack(stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) deleteLegacyStack(legacyID string) error {
|
||||||
|
return m.store.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
|
err := bucket.Delete([]byte(legacyID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Migrator) retrieveLegacyStacks() ([]legacyStack, error) {
|
||||||
|
var legacyStacks = make([]legacyStack, 0)
|
||||||
|
err := m.store.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
|
cursor := bucket.Cursor()
|
||||||
|
|
||||||
|
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
|
||||||
|
var stack legacyStack
|
||||||
|
err := internal.UnmarshalObject(v, &stack)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
legacyStacks = append(legacyStacks, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return legacyStacks, nil
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ type Migrator struct {
|
||||||
StackService *StackService
|
StackService *StackService
|
||||||
UserService *UserService
|
UserService *UserService
|
||||||
VersionService *VersionService
|
VersionService *VersionService
|
||||||
|
FileService portainer.FileService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMigrator creates a new Migrator.
|
// NewMigrator creates a new Migrator.
|
||||||
|
|
|
@ -17,7 +17,7 @@ func (service *StackService) Stack(ID portainer.StackID) (*portainer.Stack, erro
|
||||||
var data []byte
|
var data []byte
|
||||||
err := service.store.db.View(func(tx *bolt.Tx) error {
|
err := service.store.db.View(func(tx *bolt.Tx) error {
|
||||||
bucket := tx.Bucket([]byte(stackBucketName))
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
value := bucket.Get([]byte(ID))
|
value := bucket.Get(internal.Itob(int(ID)))
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return portainer.ErrStackNotFound
|
return portainer.ErrStackNotFound
|
||||||
}
|
}
|
||||||
|
@ -92,17 +92,36 @@ func (service *StackService) Stacks() ([]portainer.Stack, error) {
|
||||||
return stacks, nil
|
return stacks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNextIdentifier returns the current bucket identifier incremented by 1.
|
||||||
|
func (service *StackService) GetNextIdentifier() int {
|
||||||
|
var identifier int
|
||||||
|
|
||||||
|
service.store.db.View(func(tx *bolt.Tx) error {
|
||||||
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
|
id := bucket.Sequence()
|
||||||
|
identifier = int(id)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
identifier++
|
||||||
|
return identifier
|
||||||
|
}
|
||||||
|
|
||||||
// CreateStack creates a new stack.
|
// CreateStack creates a new stack.
|
||||||
func (service *StackService) CreateStack(stack *portainer.Stack) error {
|
func (service *StackService) CreateStack(stack *portainer.Stack) error {
|
||||||
return service.store.db.Update(func(tx *bolt.Tx) error {
|
return service.store.db.Update(func(tx *bolt.Tx) error {
|
||||||
bucket := tx.Bucket([]byte(stackBucketName))
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
|
err := bucket.SetSequence(uint64(stack.ID))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
data, err := internal.MarshalObject(stack)
|
data, err := internal.MarshalObject(stack)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bucket.Put([]byte(stack.ID), data)
|
err = bucket.Put(internal.Itob(int(stack.ID)), data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -119,7 +138,7 @@ func (service *StackService) UpdateStack(ID portainer.StackID, stack *portainer.
|
||||||
|
|
||||||
return service.store.db.Update(func(tx *bolt.Tx) error {
|
return service.store.db.Update(func(tx *bolt.Tx) error {
|
||||||
bucket := tx.Bucket([]byte(stackBucketName))
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
err = bucket.Put([]byte(ID), data)
|
err = bucket.Put(internal.Itob(int(ID)), data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -131,7 +150,7 @@ func (service *StackService) UpdateStack(ID portainer.StackID, stack *portainer.
|
||||||
func (service *StackService) DeleteStack(ID portainer.StackID) error {
|
func (service *StackService) DeleteStack(ID portainer.StackID) error {
|
||||||
return service.store.db.Update(func(tx *bolt.Tx) error {
|
return service.store.db.Update(func(tx *bolt.Tx) error {
|
||||||
bucket := tx.Bucket([]byte(stackBucketName))
|
bucket := tx.Bucket([]byte(stackBucketName))
|
||||||
err := bucket.Delete([]byte(ID))
|
err := bucket.Delete(internal.Itob(int(ID)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,8 @@ func initFileService(dataStorePath string) portainer.FileService {
|
||||||
return fileService
|
return fileService
|
||||||
}
|
}
|
||||||
|
|
||||||
func initStore(dataStorePath string) *bolt.Store {
|
func initStore(dataStorePath string, fileService portainer.FileService) *bolt.Store {
|
||||||
store, err := bolt.NewStore(dataStorePath)
|
store, err := bolt.NewStore(dataStorePath, fileService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ func main() {
|
||||||
|
|
||||||
fileService := initFileService(*flags.Data)
|
fileService := initFileService(*flags.Data)
|
||||||
|
|
||||||
store := initStore(*flags.Data)
|
store := initStore(*flags.Data, fileService)
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
jwtService := initJWTService(!*flags.NoAuth)
|
jwtService := initJWTService(!*flags.NoAuth)
|
||||||
|
|
|
@ -186,6 +186,11 @@ func (service *Service) GetFileContent(filePath string) (string, error) {
|
||||||
return string(content), nil
|
return string(content), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rename renames a file or directory
|
||||||
|
func (service *Service) Rename(oldPath, newPath string) error {
|
||||||
|
return os.Rename(oldPath, newPath)
|
||||||
|
}
|
||||||
|
|
||||||
// WriteJSONToFile writes JSON to the specified file.
|
// WriteJSONToFile writes JSON to the specified file.
|
||||||
func (service *Service) WriteJSONToFile(path string, content interface{}) error {
|
func (service *Service) WriteJSONToFile(path string, content interface{}) error {
|
||||||
jsonContent, err := json.Marshal(content)
|
jsonContent, err := json.Marshal(content)
|
||||||
|
|
|
@ -46,9 +46,9 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerComposeStack,
|
Type: portainer.DockerComposeStack,
|
||||||
EndpointID: endpoint.ID,
|
EndpointID: endpoint.ID,
|
||||||
|
@ -126,9 +126,9 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerComposeStack,
|
Type: portainer.DockerComposeStack,
|
||||||
EndpointID: endpoint.ID,
|
EndpointID: endpoint.ID,
|
||||||
|
@ -211,9 +211,9 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerComposeStack,
|
Type: portainer.DockerComposeStack,
|
||||||
EndpointID: endpoint.ID,
|
EndpointID: endpoint.ID,
|
||||||
|
|
|
@ -51,9 +51,9 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerSwarmStack,
|
Type: portainer.DockerSwarmStack,
|
||||||
SwarmID: payload.SwarmID,
|
SwarmID: payload.SwarmID,
|
||||||
|
@ -138,9 +138,9 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerSwarmStack,
|
Type: portainer.DockerSwarmStack,
|
||||||
SwarmID: payload.SwarmID,
|
SwarmID: payload.SwarmID,
|
||||||
|
@ -239,9 +239,9 @@ func (handler *Handler) createSwarmStackFromFileUpload(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stackIdentifier := buildStackIdentifier(payload.Name, endpoint.ID)
|
stackID := handler.StackService.GetNextIdentifier()
|
||||||
stack := &portainer.Stack{
|
stack := &portainer.Stack{
|
||||||
ID: portainer.StackID(stackIdentifier),
|
ID: portainer.StackID(stackID),
|
||||||
Name: payload.Name,
|
Name: payload.Name,
|
||||||
Type: portainer.DockerSwarmStack,
|
Type: portainer.DockerSwarmStack,
|
||||||
SwarmID: payload.SwarmID,
|
SwarmID: payload.SwarmID,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package stacks
|
package stacks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer"
|
||||||
httperror "github.com/portainer/portainer/http/error"
|
httperror "github.com/portainer/portainer/http/error"
|
||||||
|
@ -14,14 +14,13 @@ func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.FileService.RemoveDirectory(stack.ProjectPath)
|
err := handler.FileService.RemoveDirectory(stack.ProjectPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("http error: Unable to cleanup stack creation (err=%s)\n", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildStackIdentifier(stackName string, endpointID portainer.EndpointID) string {
|
|
||||||
return stackName + "_" + strconv.Itoa(int(endpointID))
|
|
||||||
}
|
|
||||||
|
|
||||||
// POST request on /api/stacks?type=<type>&method=<method>&endpointId=<endpointId>
|
// POST request on /api/stacks?type=<type>&method=<method>&endpointId=<endpointId>
|
||||||
func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
stackType, err := request.RetrieveNumericQueryParameter(r, "type", false)
|
stackType, err := request.RetrieveNumericQueryParameter(r, "type", false)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package stacks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer"
|
||||||
httperror "github.com/portainer/portainer/http/error"
|
httperror "github.com/portainer/portainer/http/error"
|
||||||
|
@ -12,6 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DELETE request on /api/stacks/:id?external=<external>&endpointId=<endpointId>
|
// DELETE request on /api/stacks/:id?external=<external>&endpointId=<endpointId>
|
||||||
|
// If the external query parameter is set to true, the id route variable is expected to be
|
||||||
|
// the name of an external stack as a string.
|
||||||
func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -23,7 +26,12 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt
|
||||||
return handler.deleteExternalStack(r, w, stackID)
|
return handler.deleteExternalStack(r, w, stackID)
|
||||||
}
|
}
|
||||||
|
|
||||||
stack, err := handler.StackService.Stack(portainer.StackID(stackID))
|
id, err := strconv.Atoi(stackID)
|
||||||
|
if err != nil {
|
||||||
|
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack, err := handler.StackService.Stack(portainer.StackID(id))
|
||||||
if err == portainer.ErrStackNotFound {
|
if err == portainer.ErrStackNotFound {
|
||||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@ -71,7 +79,7 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, err.Error(), err}
|
return &httperror.HandlerError{http.StatusInternalServerError, err.Error(), err}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.StackService.DeleteStack(portainer.StackID(stackID))
|
err = handler.StackService.DeleteStack(portainer.StackID(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to remove the stack from the database", err}
|
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to remove the stack from the database", err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ type stackFileResponse struct {
|
||||||
|
|
||||||
// GET request on /api/stacks/:id/file
|
// GET request on /api/stacks/:id/file
|
||||||
func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
// GET request on /api/stacks/:id
|
// GET request on /api/stacks/:id
|
||||||
func (handler *Handler) stackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) stackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func (payload *updateSwarmStackPayload) Validate(r *http.Request) error {
|
||||||
|
|
||||||
// PUT request on /api/stacks/:id?endpointId=<endpointId>
|
// PUT request on /api/stacks/:id?endpointId=<endpointId>
|
||||||
func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackID represents a stack identifier (it must be composed of Name + "_" + SwarmID to create a unique identifier).
|
// StackID represents a stack identifier (it must be composed of Name + "_" + SwarmID to create a unique identifier).
|
||||||
StackID string
|
StackID int
|
||||||
|
|
||||||
// StackType represents the type of the stack (compose v2, stack deploy v3).
|
// StackType represents the type of the stack (compose v2, stack deploy v3).
|
||||||
StackType int
|
StackType int
|
||||||
|
@ -373,6 +373,7 @@ type (
|
||||||
CreateStack(stack *Stack) error
|
CreateStack(stack *Stack) error
|
||||||
UpdateStack(ID StackID, stack *Stack) error
|
UpdateStack(ID StackID, stack *Stack) error
|
||||||
DeleteStack(ID StackID) error
|
DeleteStack(ID StackID) error
|
||||||
|
GetNextIdentifier() int
|
||||||
}
|
}
|
||||||
|
|
||||||
// DockerHubService represents a service for managing the DockerHub object.
|
// DockerHubService represents a service for managing the DockerHub object.
|
||||||
|
@ -434,6 +435,7 @@ type (
|
||||||
// FileService represents a service for managing files.
|
// FileService represents a service for managing files.
|
||||||
FileService interface {
|
FileService interface {
|
||||||
GetFileContent(filePath string) (string, error)
|
GetFileContent(filePath string) (string, error)
|
||||||
|
Rename(oldPath, newPath string) error
|
||||||
RemoveDirectory(directoryPath string) error
|
RemoveDirectory(directoryPath string) error
|
||||||
StoreTLSFileFromBytes(folder string, fileType TLSFileType, data []byte) (string, error)
|
StoreTLSFileFromBytes(folder string, fileType TLSFileType, data []byte) (string, error)
|
||||||
GetPathForTLSFile(folder string, fileType TLSFileType) (string, error)
|
GetPathForTLSFile(folder string, fileType TLSFileType) (string, error)
|
||||||
|
|
Loading…
Reference in New Issue