From 247f358b94e959e035e5f319fe4428009b987779 Mon Sep 17 00:00:00 2001 From: andres-portainer <91705312+andres-portainer@users.noreply.github.com> Date: Fri, 27 Oct 2023 17:33:04 -0300 Subject: [PATCH] fix(code): revert omitempty optimization EE-6269 (#10548) --- .../test_data/output_24_to_latest.json | 110 ++++++++-- .../handler/endpoints/endpoint_list_test.go | 4 +- api/http/handler/endpoints/filter_test.go | 4 +- api/portainer.go | 206 +++++++++--------- .../EdgeComputeSettings.validation.ts | 4 +- 5 files changed, 205 insertions(+), 123 deletions(-) diff --git a/api/datastore/test_data/output_24_to_latest.json b/api/datastore/test_data/output_24_to_latest.json index 9cd35f833..6f1aa6e5b 100644 --- a/api/datastore/test_data/output_24_to_latest.json +++ b/api/datastore/test_data/output_24_to_latest.json @@ -27,7 +27,9 @@ ], "endpoints": [ { - "Agent": {}, + "Agent": { + "Version": "" + }, "AuthorizedTeams": null, "AuthorizedUsers": null, "AzureCredentials": { @@ -36,36 +38,62 @@ "TenantID": "" }, "ComposeSyntaxMaxVersion": "", - "Edge": {}, + "Edge": { + "AsyncMode": false, + "CommandInterval": 0, + "PingInterval": 0, + "SnapshotInterval": 0 + }, "EdgeCheckinInterval": 0, + "EdgeKey": "", "Gpus": [], "GroupId": 1, + "Heartbeat": false, "Id": 1, "Kubernetes": { "Configuration": { + "AllowNoneIngressClass": false, + "EnableResourceOverCommit": false, "IngressAvailabilityPerNamespace": true, "IngressClasses": null, - "StorageClasses": null + "ResourceOverCommitPercentage": 0, + "RestrictDefaultNamespace": false, + "StorageClasses": null, + "UseLoadBalancer": false, + "UseServerMetrics": false + }, + "Flags": { + "IsServerIngressClassDetected": false, + "IsServerMetricsDetected": false, + "IsServerStorageDetected": false }, - "Flags": {}, "Snapshots": [] }, + "LastCheckInDate": 0, "Name": "local", "PostInitMigrations": { "MigrateGPUs": true, "MigrateIngresses": true }, + "PublicURL": "", + "QueryDate": 0, "SecuritySettings": { "allowBindMountsForRegularUsers": true, "allowContainerCapabilitiesForRegularUsers": true, "allowDeviceMappingForRegularUsers": true, "allowHostNamespaceForRegularUsers": true, "allowPrivilegedModeForRegularUsers": true, - "allowStackManagementForRegularUsers": true + "allowStackManagementForRegularUsers": true, + "allowSysctlSettingForRegularUsers": false, + "allowVolumeBrowserForRegularUsers": false, + "enableHostManagementFeatures": false }, "Snapshots": [], "Status": 1, - "TLSConfig": {}, + "TLSConfig": { + "TLS": false, + "TLSSkipVerify": false + }, "TagIds": [], "Tags": null, "TeamAccessPolicies": {}, @@ -79,6 +107,7 @@ "Authentication": true, "AuthorizedTeams": null, "AuthorizedUsers": null, + "BaseURL": "", "Ecr": { "Region": "" }, @@ -121,28 +150,34 @@ "UserAccesses": [] }, { + "AdministratorsOnly": false, "Id": 3, "Public": true, "ResourceId": "1_alpine", "SubResourceIds": [], + "System": false, "TeamAccesses": [], "Type": 6, "UserAccesses": [] }, { + "AdministratorsOnly": false, "Id": 4, "Public": true, "ResourceId": "1_redis", "SubResourceIds": [], + "System": false, "TeamAccesses": [], "Type": 6, "UserAccesses": [] }, { + "AdministratorsOnly": false, "Id": 5, "Public": false, "ResourceId": "1_nginx", "SubResourceIds": [], + "System": false, "TeamAccesses": [ { "AccessLevel": 1, @@ -538,6 +573,7 @@ } ], "settings": { + "AgentSecret": "", "AllowBindMountsForRegularUsers": true, "AllowContainerCapabilitiesForRegularUsers": true, "AllowDeviceMappingForRegularUsers": true, @@ -553,9 +589,14 @@ "SnapshotInterval": 0 }, "EdgeAgentCheckinInterval": 5, + "EdgePortainerUrl": "", + "EnableEdgeComputeFeatures": false, "EnableTelemetry": true, + "EnforceEdgeID": false, "FeatureFlagSettings": null, - "GlobalDeploymentOptions": {}, + "GlobalDeploymentOptions": { + "hideStacksFunctionality": false + }, "HelmRepositoryURL": "https://charts.bitnami.com/bitnami", "InternalAuthSettings": { "RequiredPasswordLength": 12 @@ -568,7 +609,8 @@ "GroupSearchSettings": [ { "GroupAttribute": "", - "GroupBaseDN": "" + "GroupBaseDN": "", + "GroupFilter": "" } ], "ReaderDN": "", @@ -579,9 +621,14 @@ "UserNameAttribute": "" } ], - "TLSConfig": {}, + "StartTLS": false, + "TLSConfig": { + "TLS": false, + "TLSSkipVerify": false + }, "URL": "" }, + "LogoURL": "", "OAuthSettings": { "AccessTokenURI": "", "AuthorizationURI": "", @@ -596,8 +643,10 @@ "Scopes": "", "UserIdentifier": "" }, + "ShowKomposeBuildOption": false, "SnapshotInterval": "5m", "TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json", + "TrustOnFirstConnect": false, "UserSessionTimeout": "8h", "fdoConfiguration": { "enabled": false, @@ -736,23 +785,34 @@ "UnhealthyContainerCount": 0, "VolumeCount": 10 }, - "EndpointId": 1 + "EndpointId": 1, + "Kubernetes": null } ], "ssl": { - "httpEnabled": true + "certPath": "", + "httpEnabled": true, + "keyPath": "", + "selfSigned": false }, "stacks": [ { "AdditionalFiles": null, + "AutoUpdate": null, "CreatedBy": "", "CreationDate": 0, "EndpointId": 1, "EntryPoint": "docker/alpine37-compose.yml", "Env": [], + "FromAppTemplate": false, + "GitConfig": null, "Id": 2, + "IsComposeFormat": false, "Name": "alpine", + "Namespace": "", + "Option": null, "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/2", + "ResourceControl": null, "Status": 1, "SwarmId": "s3fd604zdba7z13tbq2x6lyue", "Type": 1, @@ -761,30 +821,46 @@ }, { "AdditionalFiles": null, + "AutoUpdate": null, "CreatedBy": "", "CreationDate": 0, "EndpointId": 1, "EntryPoint": "docker-compose.yml", "Env": [], + "FromAppTemplate": false, + "GitConfig": null, "Id": 5, + "IsComposeFormat": false, "Name": "redis", + "Namespace": "", + "Option": null, "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/5", + "ResourceControl": null, "Status": 1, + "SwarmId": "", "Type": 2, "UpdateDate": 0, "UpdatedBy": "" }, { "AdditionalFiles": null, + "AutoUpdate": null, "CreatedBy": "", "CreationDate": 0, "EndpointId": 1, "EntryPoint": "docker-compose.yml", "Env": [], + "FromAppTemplate": false, + "GitConfig": null, "Id": 6, + "IsComposeFormat": false, "Name": "nginx", + "Namespace": "", + "Option": null, "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/6", + "ResourceControl": null, "Status": 1, + "SwarmId": "", "Type": 2, "UpdateDate": 0, "UpdatedBy": "" @@ -796,7 +872,9 @@ "Name": "hello" } ], - "tunnel_server": {}, + "tunnel_server": { + "PrivateKeySeed": "" + }, "users": [ { "EndpointAuthorizations": null, @@ -821,7 +899,9 @@ "PortainerUserRevokeToken": true }, "Role": 1, - "ThemeSettings": {}, + "ThemeSettings": { + "color": "" + }, "TokenIssueAt": 0, "Username": "admin" }, @@ -848,7 +928,9 @@ "PortainerUserRevokeToken": true }, "Role": 1, - "ThemeSettings": {}, + "ThemeSettings": { + "color": "" + }, "TokenIssueAt": 0, "Username": "prabhat" } diff --git a/api/http/handler/endpoints/endpoint_list_test.go b/api/http/handler/endpoints/endpoint_list_test.go index cd53091b4..6db7de3b1 100644 --- a/api/http/handler/endpoints/endpoint_list_test.go +++ b/api/http/handler/endpoints/endpoint_list_test.go @@ -28,13 +28,13 @@ func Test_EndpointList_AgentVersion(t *testing.T) { GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct { - Version string `json:"Version,omitempty" example:"1.0.0"` + Version string `example:"1.0.0"` }{ Version: "1.0.0", }, } version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct { - Version string `json:"Version,omitempty" example:"1.0.0"` + Version string `example:"1.0.0"` }{Version: "2.0.0"}} noVersionEndpoint := portainer.Endpoint{ID: 3, Type: portainer.AgentOnDockerEnvironment, GroupID: 1} notAgentEnvironments := portainer.Endpoint{ID: 4, Type: portainer.DockerEnvironment, GroupID: 1} diff --git a/api/http/handler/endpoints/filter_test.go b/api/http/handler/endpoints/filter_test.go index 27f4aa216..aa530a7a2 100644 --- a/api/http/handler/endpoints/filter_test.go +++ b/api/http/handler/endpoints/filter_test.go @@ -22,12 +22,12 @@ func Test_Filter_AgentVersion(t *testing.T) { version1Endpoint := portainer.Endpoint{ID: 1, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct { - Version string `json:"Version,omitempty" example:"1.0.0"` + Version string `example:"1.0.0"` }{Version: "1.0.0"}} version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct { - Version string `json:"Version,omitempty" example:"1.0.0"` + Version string `example:"1.0.0"` }{Version: "2.0.0"}} noVersionEndpoint := portainer.Endpoint{ID: 3, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, diff --git a/api/portainer.go b/api/portainer.go index f483ae871..347fd168d 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -171,7 +171,7 @@ type ( // User identifier who created this template CreatedByUserID UserID `json:"CreatedByUserId" example:"3"` // A note that will be displayed in the UI. Supports HTML content - Note string `json:"Note,omitempty" example:"This is my custom template"` + Note string `json:"Note" example:"This is my custom template"` // Platform associated to the template. // Valid values are: 1 - 'linux', 2 - 'windows' Platform CustomTemplatePlatform `json:"Platform" example:"1" enums:"1,2"` @@ -182,11 +182,11 @@ type ( // * 2 - compose // * 3 - kubernetes Type StackType `json:"Type" example:"1" enums:"1,2,3"` - ResourceControl *ResourceControl `json:"ResourceControl,omitempty"` + ResourceControl *ResourceControl `json:"ResourceControl"` Variables []CustomTemplateVariableDefinition - GitConfig *gittypes.RepoConfig `json:"GitConfig,omitempty"` + GitConfig *gittypes.RepoConfig `json:"GitConfig"` // IsComposeFormat indicates if the Kubernetes template is created from a Docker Compose file - IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"` + IsComposeFormat bool `example:"false"` } // CustomTemplateID represents a custom template identifier @@ -249,10 +249,10 @@ type ( // EdgeGroup Identifier ID EdgeGroupID `json:"Id" example:"1"` Name string `json:"Name"` - Dynamic bool `json:"Dynamic,omitempty"` + Dynamic bool `json:"Dynamic"` TagIDs []TagID `json:"TagIds"` Endpoints []EndpointID `json:"Endpoints"` - PartialMatch bool `json:"PartialMatch,omitempty"` + PartialMatch bool `json:"PartialMatch"` } // EdgeGroupID represents an Edge group identifier @@ -268,7 +268,7 @@ type ( EdgeGroups []EdgeGroupID `json:"EdgeGroups"` Name string `json:"Name"` ScriptPath string `json:"ScriptPath"` - Recurring bool `json:"Recurring,omitempty"` + Recurring bool `json:"Recurring"` Version int `json:"Version"` // Field used for log collection of Endpoints belonging to EdgeGroups @@ -278,7 +278,7 @@ type ( // EdgeJobEndpointMeta represents a meta data object for an Edge job and Environment(Endpoint) relation EdgeJobEndpointMeta struct { LogsStatus EdgeJobLogsStatus - CollectLogs bool `json:"CollectLogs,omitempty"` + CollectLogs bool } // EdgeJobID represents an Edge job identifier @@ -325,7 +325,7 @@ type ( ManifestPath string DeploymentType EdgeStackDeploymentType // Uses the manifest's namespaces instead of the default one - UseManifestNamespaces bool `json:"UseManifestNamespaces,omitempty"` + UseManifestNamespaces bool // Deprecated Prune bool `json:"Prune,omitempty"` @@ -392,11 +392,11 @@ type ( // Environment(Endpoint) environment(endpoint) type. 1 for a Docker environment(endpoint), 2 for an agent on Docker environment(endpoint) or 3 for an Azure environment(endpoint). Type EndpointType `json:"Type" example:"1"` // URL or IP address of the Docker host associated to this environment(endpoint) - URL string `json:"URL,omitempty" example:"docker.mydomain.tld:2375"` + URL string `json:"URL" example:"docker.mydomain.tld:2375"` // Environment(Endpoint) group identifier GroupID EndpointGroupID `json:"GroupId" example:"1"` // URL or IP address where exposed containers will be reachable - PublicURL string `json:"PublicURL,omitempty" example:"docker.mydomain.tld:2375"` + PublicURL string `json:"PublicURL" example:"docker.mydomain.tld:2375"` Gpus []Pair `json:"Gpus"` TLSConfig TLSConfiguration `json:"TLSConfig"` AzureCredentials AzureCredentials `json:"AzureCredentials,omitempty"` @@ -413,7 +413,7 @@ type ( // The identifier of the edge agent associated with this environment(endpoint) EdgeID string `json:"EdgeID,omitempty"` // The key which is used to map the agent to Portainer - EdgeKey string `json:"EdgeKey,omitempty"` + EdgeKey string `json:"EdgeKey"` // The check in interval for edge agent (in seconds) EdgeCheckinInterval int `json:"EdgeCheckinInterval" example:"5"` // Associated Kubernetes data @@ -425,11 +425,11 @@ type ( // The identifier of the AMT Device associated with this environment(endpoint) AMTDeviceGUID string `json:"AMTDeviceGUID,omitempty" example:"4c4c4544-004b-3910-8037-b6c04f504633"` // LastCheckInDate mark last check-in date on checkin - LastCheckInDate int64 `json:"LastCheckInDate,omitempty"` + LastCheckInDate int64 // QueryDate of each query with the endpoints list - QueryDate int64 `json:"QueryDate,omitempty"` + QueryDate int64 // Heartbeat indicates the heartbeat status of an edge environment - Heartbeat bool `json:"Heartbeat,omitempty" example:"true"` + Heartbeat bool `json:"Heartbeat" example:"true"` // Whether the device has been trusted or not by the user UserTrusted bool `json:"UserTrusted,omitempty"` @@ -440,7 +440,7 @@ type ( Edge EnvironmentEdgeSettings Agent struct { - Version string `json:"Version,omitempty" example:"1.0.0"` + Version string `example:"1.0.0"` } EnableGPUManagement bool `json:"EnableGPUManagement,omitempty"` @@ -465,13 +465,13 @@ type ( EnvironmentEdgeSettings struct { // Whether the device has been started in edge async mode - AsyncMode bool `json:"AsyncMode,omitempty"` + AsyncMode bool // The ping interval for edge agent - used in edge async mode [seconds] - PingInterval int `json:"PingInterval,omitempty" example:"60"` + PingInterval int `json:"PingInterval" example:"60"` // The snapshot interval for edge agent - used in edge async mode [seconds] - SnapshotInterval int `json:"SnapshotInterval,omitempty" example:"60"` + SnapshotInterval int `json:"SnapshotInterval" example:"60"` // The command list interval for edge agent - used in edge async mode [seconds] - CommandInterval int `json:"CommandInterval,omitempty" example:"60"` + CommandInterval int `json:"CommandInterval" example:"60"` } // EndpointAuthorizations represents the authorizations associated to a set of environments(endpoints) @@ -486,7 +486,7 @@ type ( // Environment(Endpoint) group name Name string `json:"Name" example:"my-environment-group"` // Description associated to the environment(endpoint) group - Description string `json:"Description,omitempty" example:"Environment(Endpoint) group description"` + Description string `json:"Description" example:"Environment(Endpoint) group description"` UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"` TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"` // List of tags associated to this environment(endpoint) group @@ -519,23 +519,23 @@ type ( // EndpointSecuritySettings represents settings for an environment(endpoint) EndpointSecuritySettings struct { // Whether non-administrator should be able to use bind mounts when creating containers - AllowBindMountsForRegularUsers bool `json:"allowBindMountsForRegularUsers,omitempty" example:"false"` + AllowBindMountsForRegularUsers bool `json:"allowBindMountsForRegularUsers" example:"false"` // Whether non-administrator should be able to use privileged mode when creating containers - AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers,omitempty" example:"false"` + AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers" example:"false"` // Whether non-administrator should be able to browse volumes - AllowVolumeBrowserForRegularUsers bool `json:"allowVolumeBrowserForRegularUsers,omitempty" example:"true"` + AllowVolumeBrowserForRegularUsers bool `json:"allowVolumeBrowserForRegularUsers" example:"true"` // Whether non-administrator should be able to use the host pid - AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers,omitempty" example:"true"` + AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers" example:"true"` // Whether non-administrator should be able to use device mapping - AllowDeviceMappingForRegularUsers bool `json:"allowDeviceMappingForRegularUsers,omitempty" example:"true"` + AllowDeviceMappingForRegularUsers bool `json:"allowDeviceMappingForRegularUsers" example:"true"` // Whether non-administrator should be able to manage stacks - AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers,omitempty" example:"true"` + AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers" example:"true"` // Whether non-administrator should be able to use container capabilities - AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers,omitempty" example:"true"` + AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers" example:"true"` // Whether non-administrator should be able to use sysctl settings - AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers,omitempty" example:"true"` + AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers" example:"true"` // Whether host management features are enabled - EnableHostManagementFeatures bool `json:"enableHostManagementFeatures,omitempty" example:"true"` + EnableHostManagementFeatures bool `json:"enableHostManagementFeatures" example:"true"` } // EndpointType represents the type of an environment(endpoint) @@ -549,15 +549,15 @@ type ( // EndpointPostInitMigrations EndpointPostInitMigrations struct { - MigrateIngresses bool `json:"MigrateIngresses,omitempty"` - MigrateGPUs bool `json:"MigrateGPUs,omitempty"` + MigrateIngresses bool `json:"MigrateIngresses"` + MigrateGPUs bool `json:"MigrateGPUs"` } // Extension represents a deprecated Portainer extension Extension struct { // Extension Identifier ID ExtensionID `json:"Id" example:"1"` - Enabled bool `json:"Enabled,omitempty"` + Enabled bool `json:"Enabled"` Name string `json:"Name,omitempty"` ShortDescription string `json:"ShortDescription,omitempty"` Description string `json:"Description,omitempty"` @@ -611,13 +611,13 @@ type ( JobType int K8sNamespaceInfo struct { - IsSystem bool `json:"IsSystem,omitempty"` - IsDefault bool `json:"IsDefault,omitempty"` + IsSystem bool `json:"IsSystem"` + IsDefault bool `json:"IsDefault"` } K8sNodeLimits struct { - CPU int64 `json:"CPU,omitempty"` - Memory int64 `json:"Memory,omitempty"` + CPU int64 `json:"CPU"` + Memory int64 `json:"Memory"` } K8sNodesLimits map[string]*K8sNodeLimits @@ -637,9 +637,9 @@ type ( // KubernetesFlags are used to detect if we need to run initial cluster // detection again. KubernetesFlags struct { - IsServerMetricsDetected bool `json:"IsServerMetricsDetected,omitempty"` - IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected,omitempty"` - IsServerStorageDetected bool `json:"IsServerStorageDetected,omitempty"` + IsServerMetricsDetected bool `json:"IsServerMetricsDetected"` + IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected"` + IsServerStorageDetected bool `json:"IsServerStorageDetected"` } // KubernetesSnapshot represents a snapshot of a specific Kubernetes environment(endpoint) at a specific time @@ -653,15 +653,15 @@ type ( // KubernetesConfiguration represents the configuration of a Kubernetes environment(endpoint) KubernetesConfiguration struct { - UseLoadBalancer bool `json:"UseLoadBalancer,omitempty"` - UseServerMetrics bool `json:"UseServerMetrics,omitempty"` - EnableResourceOverCommit bool `json:"EnableResourceOverCommit,omitempty"` - ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage,omitempty"` + UseLoadBalancer bool `json:"UseLoadBalancer"` + UseServerMetrics bool `json:"UseServerMetrics"` + EnableResourceOverCommit bool `json:"EnableResourceOverCommit"` + ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage"` StorageClasses []KubernetesStorageClassConfig `json:"StorageClasses"` IngressClasses []KubernetesIngressClassConfig `json:"IngressClasses"` - RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace,omitempty"` - IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace,omitempty"` - AllowNoneIngressClass bool `json:"AllowNoneIngressClass,omitempty"` + RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace"` + IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace"` + AllowNoneIngressClass bool `json:"AllowNoneIngressClass"` } // KubernetesStorageClassConfig represents a Kubernetes Storage Class configuration @@ -669,14 +669,14 @@ type ( Name string `json:"Name"` AccessModes []string `json:"AccessModes"` Provisioner string `json:"Provisioner"` - AllowVolumeExpansion bool `json:"AllowVolumeExpansion,omitempty"` + AllowVolumeExpansion bool `json:"AllowVolumeExpansion"` } // KubernetesIngressClassConfig represents a Kubernetes Ingress Class configuration KubernetesIngressClassConfig struct { Name string `json:"Name"` Type string `json:"Type"` - GloballyBlocked bool `json:"Blocked,omitempty"` + GloballyBlocked bool `json:"Blocked"` BlockedNamespaces []string `json:"BlockedNamespaces"` } @@ -690,7 +690,7 @@ type ( // InternalAuthSettings represents settings used for the default 'internal' authentication InternalAuthSettings struct { - RequiredPasswordLength int `json:"RequiredPasswordLength,omitempty"` + RequiredPasswordLength int } // LDAPGroupSearchSettings represents settings used to search for groups in a LDAP server @@ -698,7 +698,7 @@ type ( // The distinguished name of the element from which the LDAP server will search for groups GroupBaseDN string `json:"GroupBaseDN" example:"dc=ldap,dc=domain,dc=tld"` // The LDAP search filter used to select group elements, optional - GroupFilter string `json:"GroupFilter,omitempty" example:"(objectClass=account"` + GroupFilter string `json:"GroupFilter" example:"(objectClass=account"` // LDAP attribute which denotes the group membership GroupAttribute string `json:"GroupAttribute" example:"member"` } @@ -716,7 +716,7 @@ type ( // LDAPSettings represents the settings used to connect to a LDAP server LDAPSettings struct { // Enable this option if the server is configured for Anonymous access. When enabled, ReaderDN and Password will not be used - AnonymousMode bool `json:"AnonymousMode,omitempty" example:"true" validate:"validate_bool"` + AnonymousMode bool `json:"AnonymousMode" example:"true" validate:"validate_bool"` // Account that will be used to search for users ReaderDN string `json:"ReaderDN" example:"cn=readonly-account,dc=ldap,dc=domain,dc=tld" validate:"required_if=AnonymousMode false"` // Password of the account that will be used to search users @@ -725,11 +725,11 @@ type ( URL string `json:"URL" example:"myldap.domain.tld:389" validate:"hostname_port"` TLSConfig TLSConfiguration `json:"TLSConfig"` // Whether LDAP connection should use StartTLS - StartTLS bool `json:"StartTLS,omitempty" example:"true"` + StartTLS bool `json:"StartTLS" example:"true"` SearchSettings []LDAPSearchSettings `json:"SearchSettings"` GroupSearchSettings []LDAPGroupSearchSettings `json:"GroupSearchSettings"` // Automatically provision users and assign them to matching LDAP group names - AutoCreateUsers bool `json:"AutoCreateUsers,omitempty" example:"true"` + AutoCreateUsers bool `json:"AutoCreateUsers" example:"true"` } // LDAPUser represents a LDAP user @@ -769,7 +769,7 @@ type ( // Pair defines a key/value string pair Pair struct { Name string `json:"name" example:"name"` - Value string `json:"value,omitempty" example:"value"` + Value string `json:"value" example:"value"` } // Registry represents a Docker registry with all the info required @@ -782,13 +782,13 @@ type ( // Registry Name Name string `json:"Name" example:"my-registry"` // URL or IP address of the Docker registry - URL string `json:"URL,omitempty" example:"registry.mydomain.tld:2375"` + URL string `json:"URL" example:"registry.mydomain.tld:2375"` // Base URL, introduced for ProGet registry - BaseURL string `json:"BaseURL,omitempty" example:"registry.mydomain.tld:2375"` + BaseURL string `json:"BaseURL" example:"registry.mydomain.tld:2375"` // Is authentication against this registry enabled - Authentication bool `json:"Authentication,omitempty" example:"true"` + Authentication bool `json:"Authentication" example:"true"` // Username or AccessKeyID used to authenticate against this registry - Username string `json:"Username,omitempty" example:"registry user"` + Username string `json:"Username" example:"registry user"` // Password or SecretAccessKey used to authenticate against this registry Password string `json:"Password,omitempty" example:"registry_password"` ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"` @@ -828,9 +828,9 @@ type ( // the registry API via the registry management extension. RegistryManagementConfiguration struct { Type RegistryType `json:"Type"` - Authentication bool `json:"Authentication,omitempty"` - Username string `json:"Username,omitempty"` - Password string `json:"Password,omitempty"` + Authentication bool `json:"Authentication"` + Username string `json:"Username"` + Password string `json:"Password"` TLSConfig TLSConfiguration `json:"TLSConfig"` Ecr EcrData `json:"Ecr"` AccessToken string `json:"AccessToken,omitempty"` @@ -860,8 +860,8 @@ type ( // Permit access to the associated resource to any user Public bool `json:"Public" example:"true"` // Permit access to resource only to admins - AdministratorsOnly bool `json:"AdministratorsOnly,omitempty" example:"true"` - System bool `json:"System,omitempty"` + AdministratorsOnly bool `json:"AdministratorsOnly" example:"true"` + System bool `json:"System"` // Deprecated fields // Deprecated in DBVersion == 2 @@ -883,10 +883,10 @@ type ( // Role name Name string `json:"Name" example:"HelpDesk"` // Role description - Description string `json:"Description,omitempty" example:"Read-only access of all resources in an environment(endpoint)"` + Description string `json:"Description" example:"Read-only access of all resources in an environment(endpoint)"` // Authorizations associated to a role Authorizations Authorizations `json:"Authorizations"` - Priority int `json:"Priority,omitempty"` + Priority int `json:"Priority"` } // RoleID represents a role identifier @@ -899,7 +899,7 @@ type ( APIKey struct { ID APIKeyID `json:"id" example:"1"` UserID UserID `json:"userId" example:"1"` - Description string `json:"description,omitempty" example:"portainer-api-key"` + Description string `json:"description" example:"portainer-api-key"` Prefix string `json:"prefix"` // API key identifier (7 char prefix) DateCreated int64 `json:"dateCreated"` // Unix timestamp (UTC) when the API key was created LastUsed int64 `json:"lastUsed"` // Unix timestamp (UTC) when the API key was last used @@ -916,10 +916,10 @@ type ( ID ScheduleID `json:"Id" example:"1"` Name string CronExpression string - Recurring bool `json:"Recurring,omitempty"` + Recurring bool Created int64 JobType JobType - EdgeSchedule *EdgeSchedule `json:"EdgeSchedule,omitempty"` + EdgeSchedule *EdgeSchedule } // ScheduleID represents a schedule identifier. @@ -931,18 +931,18 @@ type ( Endpoints []EndpointID Image string ScriptPath string - RetryCount int `json:"RetryCount,omitempty"` - RetryInterval int `json:"RetryInterval,omitempty"` + RetryCount int + RetryInterval int } GlobalDeploymentOptions struct { - HideStacksFunctionality bool `json:"hideStacksFunctionality,omitempty" example:"false"` + HideStacksFunctionality bool `json:"hideStacksFunctionality" example:"false"` } // Settings represents the application settings Settings 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 `json:"LogoURL,omitempty" example:"https://mycompany.mydomain.tld/logo.png"` + 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"` // Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth @@ -962,27 +962,27 @@ type ( // The default check in interval for edge agent (in seconds) EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"` // Show the Kompose build option (discontinued in 2.18) - ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption,omitempty" example:"false"` + ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption" example:"false"` // Whether edge compute features are enabled - EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures,omitempty"` + EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"` // The duration of a user session UserSessionTimeout string `json:"UserSessionTimeout" example:"5m"` // The expiry of a Kubeconfig KubeconfigExpiry string `json:"KubeconfigExpiry" example:"24h"` // Whether telemetry is enabled - EnableTelemetry bool `json:"EnableTelemetry,omitempty" example:"false"` + EnableTelemetry bool `json:"EnableTelemetry" example:"false"` // Helm repository URL, defaults to "https://charts.bitnami.com/bitnami" HelmRepositoryURL string `json:"HelmRepositoryURL" example:"https://charts.bitnami.com/bitnami"` // KubectlImage, defaults to portainer/kubectl-shell KubectlShellImage string `json:"KubectlShellImage" example:"portainer/kubectl-shell"` // TrustOnFirstConnect makes Portainer accepting edge agent connection by default - TrustOnFirstConnect bool `json:"TrustOnFirstConnect,omitempty" example:"false"` + TrustOnFirstConnect bool `json:"TrustOnFirstConnect" example:"false"` // EnforceEdgeID makes Portainer store the Edge ID instead of accepting anyone - EnforceEdgeID bool `json:"EnforceEdgeID,omitempty" example:"false"` + EnforceEdgeID bool `json:"EnforceEdgeID" example:"false"` // Container environment parameter AGENT_SECRET - AgentSecret string `json:"AgentSecret,omitempty"` + AgentSecret string `json:"AgentSecret"` // EdgePortainerURL is the URL that is exposed to edge agents - EdgePortainerURL string `json:"EdgePortainerUrl,omitempty"` + EdgePortainerURL string `json:"EdgePortainerUrl"` Edge struct { // The command list interval for edge agent - used in edge async mode (in seconds) @@ -1021,10 +1021,10 @@ type ( // SSLSettings represents a pair of SSL certificate and key SSLSettings struct { - CertPath string `json:"certPath,omitempty"` - KeyPath string `json:"keyPath,omitempty"` - SelfSigned bool `json:"selfSigned,omitempty"` - HTTPEnabled bool `json:"httpEnabled,omitempty"` + CertPath string `json:"certPath"` + KeyPath string `json:"keyPath"` + SelfSigned bool `json:"selfSigned"` + HTTPEnabled bool `json:"httpEnabled"` } // Stack represents a Docker stack created via docker stack deploy @@ -1038,13 +1038,13 @@ type ( // Environment(Endpoint) identifier. Reference the environment(endpoint) that will be used for deployment EndpointID EndpointID `json:"EndpointId" example:"1"` // Cluster identifier of the Swarm cluster where the stack is deployed - SwarmID string `json:"SwarmId,omitempty" example:"jpofkc0i9uo9wtx1zesuk649w"` + 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"` // - ResourceControl *ResourceControl `json:"ResourceControl,omitempty"` + ResourceControl *ResourceControl `json:"ResourceControl"` // Stack status (1 - active, 2 - inactive) Status StackStatus `json:"Status" example:"1"` // Path on disk to the repository hosting the Stack file @@ -1060,23 +1060,23 @@ type ( // Only applies when deploying stack with multiple files AdditionalFiles []string `json:"AdditionalFiles"` // The GitOps update settings of a git stack - AutoUpdate *AutoUpdateSettings `json:"AutoUpdate,omitempty"` + AutoUpdate *AutoUpdateSettings `json:"AutoUpdate"` // The stack deployment option - Option *StackOption `json:"Option,omitempty"` + Option *StackOption `json:"Option"` // The git config of this stack - GitConfig *gittypes.RepoConfig `json:"GitConfig,omitempty"` + GitConfig *gittypes.RepoConfig // Whether the stack is from a app template - FromAppTemplate bool `json:"FromAppTemplate,omitempty" example:"false"` + FromAppTemplate bool `example:"false"` // Kubernetes namespace if stack is a kube application - Namespace string `json:"Namespace,omitempty" example:"default"` + Namespace string `example:"default"` // IsComposeFormat indicates if the Kubernetes stack is created from a Docker Compose file - IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"` + IsComposeFormat bool `example:"false"` } // StackOption represents the options for stack deployment StackOption struct { // Prune services that are no longer referenced - Prune bool `json:"Prune,omitempty" example:"false"` + Prune bool `example:"false"` } // StackID represents a stack identifier (it must be composed of Name + "_" + SwarmID to create a unique identifier) @@ -1159,9 +1159,9 @@ type ( // Title of the template Title string `json:"title" example:"Nginx"` // Description of the template - Description string `json:"description,omitempty" example:"High performance web server"` + Description string `json:"description" example:"High performance web server"` // Whether the template should be available to administrators only - AdministratorOnly bool `json:"administrator_only,omitempty" example:"true"` + AdministratorOnly bool `json:"administrator_only" example:"true"` // Mandatory container fields // Image associated to a container template. Mandatory for a container template @@ -1237,7 +1237,7 @@ type ( // A value that will be associated to the choice Value string `json:"value" example:"value"` // Will set this choice as the default choice - Default bool `json:"default,omitempty" example:"false"` + Default bool `json:"default" example:"false"` } // TemplateID represents a template identifier @@ -1267,9 +1267,9 @@ type ( // TLSConfiguration represents a TLS configuration TLSConfiguration struct { // Use TLS - TLS bool `json:"TLS,omitempty" example:"true"` + TLS bool `json:"TLS" example:"true"` // Skip the verification of the server TLS certificate - TLSSkipVerify bool `json:"TLSSkipVerify,omitempty" example:"false"` + TLSSkipVerify bool `json:"TLSSkipVerify" example:"false"` // Path to the TLS CA certificate file TLSCACertPath string `json:"TLSCACert,omitempty" example:"/data/tls/ca.pem"` // Path to the TLS client certificate file @@ -1287,7 +1287,7 @@ type ( ID UserID Username string Role UserRole - ForceChangePassword bool `json:"ForceChangePassword,omitempty"` + ForceChangePassword bool Token string } @@ -1302,7 +1302,7 @@ type ( // TunnelServerInfo represents information associated to the tunnel server TunnelServerInfo struct { - PrivateKeySeed string `json:"PrivateKeySeed,omitempty"` + PrivateKeySeed string `json:"PrivateKeySeed"` } // User represents a user account @@ -1345,7 +1345,7 @@ type ( // UserThemeSettings represents the theme settings for a user UserThemeSettings struct { // Color represents the color theme of the UI - Color string `json:"color,omitempty" example:"dark" enums:"dark,light,highcontrast,auto"` + Color string `json:"color" example:"dark" enums:"dark,light,highcontrast,auto"` } // Webhook represents a url webhook that can be used to update a service @@ -1368,8 +1368,8 @@ type ( Snapshot struct { EndpointID EndpointID `json:"EndpointId"` - Docker *DockerSnapshot `json:"Docker,omitempty"` - Kubernetes *KubernetesSnapshot `json:"Kubernetes,omitempty"` + Docker *DockerSnapshot `json:"Docker"` + Kubernetes *KubernetesSnapshot `json:"Kubernetes"` } // CLIService represents a service for managing CLI diff --git a/app/react/portainer/settings/EdgeComputeView/EdgeComputeSettings/EdgeComputeSettings.validation.ts b/app/react/portainer/settings/EdgeComputeView/EdgeComputeSettings/EdgeComputeSettings.validation.ts index c4461034b..b1eee135a 100644 --- a/app/react/portainer/settings/EdgeComputeView/EdgeComputeSettings/EdgeComputeSettings.validation.ts +++ b/app/react/portainer/settings/EdgeComputeView/EdgeComputeSettings/EdgeComputeSettings.validation.ts @@ -9,8 +9,8 @@ import { FormValues } from './types'; export function validationSchema(): SchemaOf { return object() .shape({ - EnableEdgeComputeFeatures: boolean().default(false), - EnforceEdgeID: boolean().default(false), + EnableEdgeComputeFeatures: boolean().required('This field is required.'), + EnforceEdgeID: boolean().required('This field is required.'), }) .concat( isBE