1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 15:55:23 +02:00

fixed structs and auto migrate is working

This commit is contained in:
Prabhat Khera 2023-05-12 15:44:16 +12:00
parent 4ff7135b73
commit 3396f1ca91
21 changed files with 71 additions and 69 deletions

View file

@ -9,7 +9,7 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
)
type pairList []portainer.Pair
type pairList portainer.MultiPair
// Set implementation for a list of portainer.Pair
func (l *pairList) Set(value string) error {
@ -34,8 +34,8 @@ func (l *pairList) IsCumulative() bool {
return true
}
func pairs(s kingpin.Settings) (target *[]portainer.Pair) {
target = new([]portainer.Pair)
func pairs(s kingpin.Settings) (target *portainer.MultiPair) {
target = new(portainer.MultiPair)
s.SetValue((*pairList)(target))
return
}

View file

@ -8,7 +8,7 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
)
type pairListBool []portainer.Pair
type pairListBool portainer.MultiPair
// Set implementation for a list of portainer.Pair
func (l *pairListBool) Set(value string) error {
@ -38,8 +38,8 @@ func (l *pairListBool) IsCumulative() bool {
return true
}
func BoolPairs(s kingpin.Settings) (target *[]portainer.Pair) {
target = new([]portainer.Pair)
func BoolPairs(s kingpin.Settings) (target *portainer.MultiPair) {
target = new(portainer.MultiPair)
s.SetValue((*pairListBool)(target))
return
}

View file

@ -62,7 +62,8 @@ func (service *Service) Endpoint(ID portainer.EndpointID) (*portainer.Endpoint,
// UpdateEndpoint updates an environment(endpoint).
func (service *Service) UpdateEndpoint(ID portainer.EndpointID, endpoint *portainer.Endpoint) error {
db := service.connection.GetDB()
tx := db.Model(&portainer.Endpoint{}).Where("id = ?", ID).UpdateColumns(&endpoint)
endpoint.ID = ID
tx := db.Save(&endpoint)
if tx.Error != nil {
return tx.Error
}

View file

@ -58,7 +58,7 @@ func (b *stackBuilder) createNewStack(webhookID string) portainer.Stack {
Type: portainer.DockerComposeStack,
EndpointID: 2,
EntryPoint: filesystem.ComposeFileDefaultName,
Env: []portainer.Pair{{Name: "Name1", Value1: "Value1"}},
Env: portainer.MultiPair{{Name: "Name1", Value1: "Value1"}},
Status: portainer.StackStatusActive,
CreationDate: time.Now().Unix(),
ProjectPath: "/tmp/project",

View file

@ -73,7 +73,8 @@ func (service *Service) UsersByRole(role portainer.UserRole) ([]portainer.User,
func (service *Service) UpdateUser(ID portainer.UserID, user *portainer.User) error {
db := service.connection.GetDB()
tx := db.Model(&portainer.User{}).Where("id = ?", ID).UpdateColumns(&user)
user.ID = ID
tx := db.Save(&user)
if tx.Error != nil {
return tx.Error
}
@ -84,7 +85,7 @@ func (service *Service) UpdateUser(ID portainer.UserID, user *portainer.User) er
// CreateUser creates a new user.
func (service *Service) Create(user *portainer.User) error {
db := service.connection.GetDB()
tx := db.Model(&portainer.User{}).Create(&user)
tx := db.Create(&user)
if tx.Error != nil {
return tx.Error
}

View file

@ -37,7 +37,7 @@ func (store *Store) checkOrCreateDefaultSettings() error {
defaultSettings := &portainer.Settings{
EnableTelemetry: false,
AuthenticationMethod: portainer.AuthenticationInternal,
BlackListedLabels: make([]portainer.Pair, 0),
BlackListedLabels: make(portainer.MultiPair, 0),
InternalAuthSettings: portainer.InternalAuthSettings{
RequiredPasswordLength: 12,
},
@ -102,7 +102,7 @@ func (store *Store) checkOrCreateDefaultData() error {
unassignedGroup := &portainer.EndpointGroup{
Name: "Unassigned",
Description: "Unassigned environments",
Labels: []portainer.Pair{},
Labels: portainer.MultiPair{},
UserAccessPolicies: portainer.UserAccessPolicies{},
TeamAccessPolicies: portainer.TeamAccessPolicies{},
TagIDs: []portainer.TagID{},

View file

@ -20,7 +20,7 @@ func (m *Migrator) addGpuInputFieldDB60() error {
for _, endpoint := range endpoints {
if endpoint.Gpus == nil {
endpoint.Gpus = []portainer.Pair{}
endpoint.Gpus = portainer.MultiPair{}
err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint)
if err != nil {
return err

View file

@ -30,7 +30,7 @@ func Test_createEnvFile(t *testing.T) {
name: "should not add env file option if stack's env variables are empty",
stack: &portainer.Stack{
ProjectPath: dir,
Env: []portainer.Pair{},
Env: portainer.MultiPair{},
},
expected: "",
},
@ -38,7 +38,7 @@ func Test_createEnvFile(t *testing.T) {
name: "should add env file option if stack has env variables",
stack: &portainer.Stack{
ProjectPath: dir,
Env: []portainer.Pair{
Env: portainer.MultiPair{
{Name: "var1", Value1: "value1"},
{Name: "var2", Value1: "value2"},
},
@ -70,7 +70,7 @@ func Test_createEnvFile_mergesDefultAndInplaceEnvVars(t *testing.T) {
os.WriteFile(path.Join(dir, ".env"), []byte("VAR1=VAL1\nVAR2=VAL2\n"), 0600)
stack := &portainer.Stack{
ProjectPath: dir,
Env: []portainer.Pair{
Env: portainer.MultiPair{
{Name: "VAR1", Value1: "NEW_VAL1"},
{Name: "VAR3", Value1: "VAL3"},
},

View file

@ -25,7 +25,7 @@ type endpointCreatePayload struct {
URL string
EndpointCreationType endpointCreationEnum
PublicURL string
Gpus []portainer.Pair
Gpus portainer.MultiPair
GroupID int
TLS bool
TLSSkipVerify bool
@ -153,7 +153,7 @@ func (payload *endpointCreatePayload) Validate(r *http.Request) error {
payload.PublicURL = publicURL
}
gpus := make([]portainer.Pair, 0)
gpus := make(portainer.MultiPair, 0)
err = request.RetrieveMultiPartFormJSONValue(r, "Gpus", &gpus, true)
if err != nil {
return errors.New("invalid Gpus parameter")

View file

@ -31,7 +31,7 @@ type endpointSettingsUpdatePayload struct {
EnableGPUManagement *bool `json:"enableGPUManagement" example:"false"`
Gpus []portainer.Pair `json:"gpus"`
Gpus portainer.MultiPair `json:"gpus"`
}
func (payload *endpointSettingsUpdatePayload) Validate(r *http.Request) error {

View file

@ -22,7 +22,7 @@ type endpointUpdatePayload struct {
// Defaults to URL if not specified
PublicURL *string `example:"docker.mydomain.tld:2375"`
// GPUs information
Gpus []portainer.Pair
Gpus portainer.MultiPair
// Group identifier
GroupID *int `example:"1"`
// Require TLS to connect against this environment(endpoint)

View file

@ -23,7 +23,7 @@ type settingsUpdatePayload struct {
// URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string
LogoURL *string `example:"https://mycompany.mydomain.tld/logo.png"`
// A list of label name & value that will be used to hide containers when querying containers
BlackListedLabels []portainer.Pair
BlackListedLabels portainer.MultiPair
// Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth
AuthenticationMethod *int `example:"1"`
InternalAuthSettings *portainer.InternalAuthSettings

View file

@ -25,7 +25,7 @@ type composeStackFromFileContentPayload struct {
// Content of the Stack file
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx" validate:"required"`
// A list of environment variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Whether the stack is from a app template
FromAppTemplate bool `example:"false"`
}
@ -41,7 +41,7 @@ func (payload *composeStackFromFileContentPayload) Validate(r *http.Request) err
return nil
}
func createStackPayloadFromComposeFileContentPayload(name string, fileContent string, env []portainer.Pair, fromAppTemplate bool) stackbuilders.StackPayload {
func createStackPayloadFromComposeFileContentPayload(name string, fileContent string, env portainer.MultiPair, fromAppTemplate bool) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
StackFileContent: fileContent,
@ -174,14 +174,14 @@ type composeStackFromGitRepositoryPayload struct {
// Optional auto update configuration
AutoUpdate *portainer.AutoUpdateSettings
// A list of environment variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Whether the stack is from a app template
FromAppTemplate bool `example:"false"`
// TLSSkipVerify skips SSL verification when cloning the Git repository
TLSSkipVerify bool `example:"false"`
}
func createStackPayloadFromComposeGitPayload(name, repoUrl, repoReference, repoUsername, repoPassword string, repoAuthentication bool, composeFile string, additionalFiles []string, autoUpdate *portainer.AutoUpdateSettings, env []portainer.Pair, fromAppTemplate bool, repoSkipSSLVerify bool) stackbuilders.StackPayload {
func createStackPayloadFromComposeGitPayload(name, repoUrl, repoReference, repoUsername, repoPassword string, repoAuthentication bool, composeFile string, additionalFiles []string, autoUpdate *portainer.AutoUpdateSettings, env portainer.MultiPair, fromAppTemplate bool, repoSkipSSLVerify bool) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
RepositoryConfigPayload: stackbuilders.RepositoryConfigPayload{
@ -314,10 +314,10 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
type composeStackFromFileUploadPayload struct {
Name string
StackFileContent []byte
Env []portainer.Pair
Env portainer.MultiPair
}
func createStackPayloadFromComposeFileUploadPayload(name string, fileContentBytes []byte, env []portainer.Pair) stackbuilders.StackPayload {
func createStackPayloadFromComposeFileUploadPayload(name string, fileContentBytes []byte, env portainer.MultiPair) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
StackFileContentBytes: fileContentBytes,
@ -339,7 +339,7 @@ func decodeRequestForm(r *http.Request) (*composeStackFromFileUploadPayload, err
}
payload.StackFileContent = composeFileContent
var env []portainer.Pair
var env portainer.MultiPair
err = request.RetrieveMultiPartFormJSONValue(r, "Env", &env, true)
if err != nil {
return nil, errors.New("Invalid Env parameter")

View file

@ -24,7 +24,7 @@ type swarmStackFromFileContentPayload struct {
// Content of the Stack file
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx" validate:"required"`
// A list of environment variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Whether the stack is from a app template
FromAppTemplate bool `example:"false"`
}
@ -42,7 +42,7 @@ func (payload *swarmStackFromFileContentPayload) Validate(r *http.Request) error
return nil
}
func createStackPayloadFromSwarmFileContentPayload(name string, swarmID string, fileContent string, env []portainer.Pair, fromAppTemplate bool) stackbuilders.StackPayload {
func createStackPayloadFromSwarmFileContentPayload(name string, swarmID string, fileContent string, env portainer.MultiPair, fromAppTemplate bool) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
SwarmID: swarmID,
@ -112,7 +112,7 @@ type swarmStackFromGitRepositoryPayload struct {
// Swarm cluster identifier
SwarmID string `example:"jpofkc0i9uo9wtx1zesuk649w" validate:"required"`
// A list of environment variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// URL of a Git repository hosting the Stack file
RepositoryURL string `example:"https://github.com/openfaas/faas" validate:"required"`
@ -155,7 +155,7 @@ func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) err
return nil
}
func createStackPayloadFromSwarmGitPayload(name, swarmID, repoUrl, repoReference, repoUsername, repoPassword string, repoAuthentication bool, composeFile string, additionalFiles []string, autoUpdate *portainer.AutoUpdateSettings, env []portainer.Pair, fromAppTemplate bool, repoSkipSSLVerify bool) stackbuilders.StackPayload {
func createStackPayloadFromSwarmGitPayload(name, swarmID, repoUrl, repoReference, repoUsername, repoPassword string, repoAuthentication bool, composeFile string, additionalFiles []string, autoUpdate *portainer.AutoUpdateSettings, env portainer.MultiPair, fromAppTemplate bool, repoSkipSSLVerify bool) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
SwarmID: swarmID,
@ -258,10 +258,10 @@ type swarmStackFromFileUploadPayload struct {
Name string
SwarmID string
StackFileContent []byte
Env []portainer.Pair
Env portainer.MultiPair
}
func createStackPayloadFromSwarmFileUploadPayload(name, swarmID string, fileContentBytes []byte, env []portainer.Pair) stackbuilders.StackPayload {
func createStackPayloadFromSwarmFileUploadPayload(name, swarmID string, fileContentBytes []byte, env portainer.MultiPair) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
SwarmID: swarmID,
@ -289,7 +289,7 @@ func (payload *swarmStackFromFileUploadPayload) Validate(r *http.Request) error
}
payload.StackFileContent = composeFileContent
var env []portainer.Pair
var env portainer.MultiPair
err = request.RetrieveMultiPartFormJSONValue(r, "Env", &env, true)
if err != nil {
return errors.New("Invalid Env parameter")

View file

@ -23,7 +23,7 @@ type updateComposeStackPayload struct {
// New content of the Stack file
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx"`
// A list of environment(endpoint) variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Force a pulling to current image with the original tag though the image is already the latest
PullImage bool `example:"false"`
}
@ -39,7 +39,7 @@ type updateSwarmStackPayload struct {
// New content of the Stack file
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx"`
// A list of environment(endpoint) variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Prune services that are no longer referenced (only available for Swarm stacks)
Prune bool `example:"true"`
// Force a pulling to current image with the original tag though the image is already the latest

View file

@ -19,7 +19,7 @@ import (
type stackGitUpdatePayload struct {
AutoUpdate *portainer.AutoUpdateSettings
Env []portainer.Pair
Env portainer.MultiPair
Prune bool
RepositoryReferenceName string
RepositoryAuthentication bool

View file

@ -22,7 +22,7 @@ type stackGitRedployPayload struct {
RepositoryAuthentication bool
RepositoryUsername string
RepositoryPassword string
Env []portainer.Pair
Env portainer.MultiPair
Prune bool
// Force a pulling to current image with the original tag though the image is already the latest
PullImage bool `example:"false"`

View file

@ -123,7 +123,7 @@ func selectorContainerLabelsFromContainerListOperation(responseObject map[string
// filterContainersWithLabels loops through a list of containers, and filters containers that do not contains
// any labels in the labels black list.
func filterContainersWithBlackListedLabels(containerData []interface{}, labelBlackList []portainer.Pair) ([]interface{}, error) {
func filterContainersWithBlackListedLabels(containerData []interface{}, labelBlackList portainer.MultiPair) ([]interface{}, error) {
filteredContainerData := make([]interface{}, 0)
for _, container := range containerData {
@ -142,7 +142,7 @@ func filterContainersWithBlackListedLabels(containerData []interface{}, labelBla
return filteredContainerData, nil
}
func containerHasBlackListedLabel(containerLabels map[string]interface{}, labelBlackList []portainer.Pair) bool {
func containerHasBlackListedLabel(containerLabels map[string]interface{}, labelBlackList portainer.MultiPair) bool {
for key, value := range containerLabels {
labelName := key
labelValue := value.(string)

View file

@ -56,7 +56,7 @@ type (
operationExecutor struct {
operationContext *restrictedDockerOperationContext
labelBlackList []portainer.Pair
labelBlackList portainer.MultiPair
}
restrictedOperationRequest func(*http.Response, *operationExecutor) error
operationRequest func(*http.Request) error

View file

@ -127,7 +127,7 @@ type (
DemoEnvironment *bool
EnableEdgeComputeFeatures *bool
EndpointURL *string
Labels *[]Pair
Labels *MultiPair
Logo *string
NoAnalytics *bool
Templates *string
@ -173,7 +173,7 @@ type (
// Path to the Stack file
EntryPoint string `json:"EntryPoint" example:"docker-compose.yml"`
// User identifier who created this template
CreatedByUserID UserID `json:"CreatedByUserId" example:"3"`
CreatedByUserID UserID `json:"CreatedByUserId" example:"3" gorm:"foreignKey=ID"`
// A note that will be displayed in the UI. Supports HTML content
Note string `json:"Note" example:"This is my <b>custom</b> template"`
// Platform associated to the template.
@ -186,9 +186,9 @@ type (
// * 2 - compose
// * 3 - kubernetes
Type StackType `json:"Type" example:"1"`
ResourceControl *ResourceControl `json:"ResourceControl" gorm:"foreignKey"`
Variables []CustomTemplateVariableDefinition `json:"Variables" gorm:"serialize:json"`
GitConfig *gittypes.RepoConfig `json:"GitConfig" gorm:"serialize:json"`
ResourceControl *ResourceControl `json:"ResourceControl" gorm:"serializer:json"`
Variables []CustomTemplateVariableDefinition `json:"Variables" gorm:"serializer:json"`
GitConfig *gittypes.RepoConfig `json:"GitConfig" gorm:"serializer:json"`
// IsComposeFormat indicates if the Kubernetes template is created from a Docker Compose file
IsComposeFormat bool `example:"false"`
}
@ -276,7 +276,7 @@ type (
Version int `json:"Version"`
// Field used for log collection of Endpoints belonging to EdgeGroups
GroupLogsCollection map[EndpointID]EdgeJobEndpointMeta
GroupLogsCollection map[EndpointID]EdgeJobEndpointMeta `json:"GroupLogsCollection" gorm:"serializer:json"`
}
// EdgeJobEndpointMeta represents a meta data object for an Edge job and Environment(Endpoint) relation
@ -300,7 +300,7 @@ type (
CronExpression string `json:"CronExpression"`
Script string `json:"Script"`
Version int `json:"Version"`
Endpoints []EndpointID `json:"Endpoints" gorm:"serealize:json"`
Endpoints []EndpointID `json:"Endpoints" gorm:"serializer:json"`
}
//EdgeStack represents an edge stack
@ -308,9 +308,9 @@ type (
// EdgeStack Identifier
ID EdgeStackID `json:"Id" example:"1" gorm:"unique,primaryKey,autoIncrement"`
Name string `json:"Name"`
Status map[EndpointID]EdgeStackStatus `json:"Status" gorm:"serealize:json"`
Status map[EndpointID]EdgeStackStatus `json:"Status" gorm:"serializer:json"`
CreationDate int64 `json:"CreationDate"`
EdgeGroups []EdgeGroupID `json:"EdgeGroups" gorm:"serealize:json"`
EdgeGroups []EdgeGroupID `json:"EdgeGroups" gorm:"serializer:json"`
ProjectPath string `json:"ProjectPath"`
EntryPoint string `json:"EntryPoint"`
Version int `json:"Version"`
@ -343,7 +343,7 @@ type (
EdgeStackStatus struct {
Details EdgeStackStatusDetails `json:"Details"`
Error string `json:"Error"`
EndpointID EndpointID `json:"EndpointID"`
EndpointID EndpointID `json:"EndpointID" gorm:"foreignKey=ID"`
// Deprecated
Type EdgeStackStatusType `json:"Type"`
@ -352,7 +352,7 @@ type (
//EdgeStackStatusType represents an edge stack status type
EdgeStackStatusType int
GPUs []Pair
MultiPair []Pair
// Environment(Endpoint) represents a Docker environment(endpoint) with all the info required
// to connect to it
@ -369,7 +369,7 @@ type (
GroupID EndpointGroupID `json:"GroupId" example:"1"`
// URL or IP address where exposed containers will be reachable
PublicURL string `json:"PublicURL" example:"docker.mydomain.tld:2375"`
Gpus GPUs `json:"Gpus" gorm:"serializer:json"`
Gpus MultiPair `json:"Gpus" gorm:"serializer:json"`
TLSConfig TLSConfiguration `json:"TLSConfig" gorm:"serializer:json"`
AzureCredentials AzureCredentials `json:"AzureCredentials,omitempty" gorm:"serializer:json"`
// List of tag identifiers to which this environment(endpoint) is associated
@ -463,7 +463,7 @@ type (
TagIDs []TagID `json:"TagIds" gorm:"serializer:json"`
// Deprecated fields
Labels []Pair `json:"Labels" gorm:"serializer:json"`
Labels MultiPair `json:"Labels" gorm:"serializer:json"`
// Deprecated in DBVersion == 18
AuthorizedUsers []UserID `json:"AuthorizedUsers" gorm:"serializer:json"`
@ -513,8 +513,8 @@ type (
// EndpointRelation represents a environment(endpoint) relation object
EndpointRelation struct {
EndpointID EndpointID
EdgeStacks map[EdgeStackID]bool
EndpointID EndpointID `gorm:"foreignKey=ID"`
EdgeStacks map[EdgeStackID]bool `gorm:"serializer:json"`
}
// EndpointPostInitMigrations
@ -889,7 +889,7 @@ type (
Recurring bool
Created int64
JobType JobType
EdgeSchedule *EdgeSchedule `json:"EdgeSchedule,omitempty" gorm:"foreignKey:ScheduleID"`
EdgeSchedule *EdgeSchedule `json:"EdgeSchedule,omitempty" gorm:"serializer:json"`
}
// ScheduleID represents a schedule identifier.
@ -911,7 +911,7 @@ type (
// URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string
LogoURL string `json:"LogoURL" example:"https://mycompany.mydomain.tld/logo.png"`
// A list of label name & value that will be used to hide containers when querying containers
BlackListedLabels []Pair `json:"BlackListedLabels" gorm:"serializer:json"`
BlackListedLabels MultiPair `json:"BlackListedLabels" gorm:"serializer:json"`
// Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth
AuthenticationMethod AuthenticationMethod `json:"AuthenticationMethod" example:"1"`
InternalAuthSettings InternalAuthSettings `json:"InternalAuthSettings" gorm:"serializer:json"`
@ -1001,13 +1001,13 @@ type (
// Stack type. 1 for a Swarm stack, 2 for a Compose stack
Type StackType `json:"Type" example:"2"`
// Environment(Endpoint) identifier. Reference the environment(endpoint) that will be used for deployment
EndpointID EndpointID `json:"EndpointId" example:"1"`
EndpointID EndpointID `json:"EndpointId" example:"1" gorm:"foreignKey=ID"`
// Cluster identifier of the Swarm cluster where the stack is deployed
SwarmID string `json:"SwarmId" example:"jpofkc0i9uo9wtx1zesuk649w"`
// Path to the Stack file
EntryPoint string `json:"EntryPoint" example:"docker-compose.yml"`
// A list of environment(endpoint) variables used during stack deployment
Env []Pair `json:"Env"`
Env MultiPair `json:"Env"`
//
ResourceControl *ResourceControl `json:"ResourceControl" gorm:"serializer:json"`
// Stack status (1 - active, 2 - inactive)
@ -1023,7 +1023,7 @@ type (
// The username which last updated this stack
UpdatedBy string `example:"bob"`
// Only applies when deploying stack with multiple files
AdditionalFiles []string `json:"AdditionalFiles"`
AdditionalFiles []string `json:"AdditionalFiles" gorm:"serializer:json"`
// The auto update settings of a git stack
AutoUpdate *AutoUpdateSettings `json:"AutoUpdate" gorm:"serializer:json"`
// The stack deployment option
@ -1164,7 +1164,7 @@ type (
// A list of ports exposed by the container
Ports []string `json:"ports,omitempty" example:"8080:80/tcp" gorm:"serializer:json"`
// Container labels
Labels []Pair `json:"labels,omitempty" gorm:"serializer:json"`
Labels MultiPair `json:"labels,omitempty" gorm:"serializer:json"`
// Whether the container should be started in privileged mode
Privileged bool `json:"privileged,omitempty" example:"true"`
// Whether the container should be started in
@ -1316,7 +1316,7 @@ type (
ID WebhookID `json:"Id" example:"1" gorm:"unique,primaryKey,autoIncrement"`
Token string `json:"Token"`
ResourceID string `json:"ResourceId"`
EndpointID EndpointID `json:"EndpointId"`
EndpointID EndpointID `json:"EndpointId" gorm:"foreignKey=ID"`
RegistryID RegistryID `json:"RegistryId"`
WebhookType WebhookType `json:"Type"`
}
@ -1328,7 +1328,7 @@ type (
WebhookType int
Snapshot struct {
EndpointID EndpointID `json:"EndpointId"`
EndpointID EndpointID `json:"EndpointId" gorm:"foreignKey=ID"`
Docker *DockerSnapshot `json:"Docker" gorm:"serializer:json"`
Kubernetes *KubernetesSnapshot `json:"Kubernetes" gorm:"serializer:json"`
}
@ -2050,12 +2050,12 @@ func (j Pair) Value() (driver.Value, error) {
return json.Marshal(j)
}
func (GPUs) GormDataType() string {
func (MultiPair) GormDataType() string {
return "json"
}
// Scan scan value into Jsonb, implements sql.Scanner interface
func (j *GPUs) Scan(value interface{}) error {
func (j *MultiPair) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
@ -2066,7 +2066,7 @@ func (j *GPUs) Scan(value interface{}) error {
}
// Value return json value, implement driver.Valuer interface
func (j GPUs) Value() (driver.Value, error) {
func (j MultiPair) Value() (driver.Value, error) {
if len(j) == 0 {
return nil, nil
}

View file

@ -16,7 +16,7 @@ type StackPayload struct {
StackFileContent string
Webhook string
// A list of environment(endpoint) variables used during stack deployment
Env []portainer.Pair
Env portainer.MultiPair
// Optional auto update configuration
AutoUpdate *portainer.AutoUpdateSettings
// Whether the stack is from a app template