2016-12-18 05:21:29 +00:00
package cli
import (
2020-07-07 21:57:52 +00:00
"errors"
2020-08-06 22:46:25 +00:00
"log"
2017-02-06 05:29:34 +00:00
"time"
2021-08-03 23:26:22 +00:00
portainer "github.com/portainer/portainer/api"
2016-12-18 05:21:29 +00:00
"os"
2017-10-26 09:17:45 +00:00
"path/filepath"
2016-12-18 05:21:29 +00:00
"strings"
2016-12-25 20:34:02 +00:00
"gopkg.in/alecthomas/kingpin.v2"
2016-12-18 05:21:29 +00:00
)
// Service implements the CLIService interface
type Service struct { }
2020-07-07 21:57:52 +00:00
var (
2021-09-08 08:42:17 +00:00
errInvalidEndpointProtocol = errors . New ( "Invalid environment protocol: Portainer only supports unix://, npipe:// or tcp://" )
2020-07-07 21:57:52 +00:00
errSocketOrNamedPipeNotFound = errors . New ( "Unable to locate Unix socket or named pipe" )
errInvalidSnapshotInterval = errors . New ( "Invalid snapshot interval" )
errAdminPassExcludeAdminPassFile = errors . New ( "Cannot use --admin-password with --admin-password-file" )
2016-12-18 05:21:29 +00:00
)
// ParseFlags parse the CLI flags and return a portainer.Flags struct
func ( * Service ) ParseFlags ( version string ) ( * portainer . CLIFlags , error ) {
kingpin . Version ( version )
flags := & portainer . CLIFlags {
2020-06-16 07:55:45 +00:00
Addr : kingpin . Flag ( "bind" , "Address and port to serve Portainer" ) . Default ( defaultBindAddress ) . Short ( 'p' ) . String ( ) ,
2021-08-10 04:59:47 +00:00
AddrHTTPS : kingpin . Flag ( "bind-https" , "Address and port to serve Portainer via https" ) . Default ( defaultHTTPSBindAddress ) . String ( ) ,
2020-06-16 07:55:45 +00:00
TunnelAddr : kingpin . Flag ( "tunnel-addr" , "Address to serve the tunnel server" ) . Default ( defaultTunnelServerAddress ) . String ( ) ,
TunnelPort : kingpin . Flag ( "tunnel-port" , "Port to serve the tunnel server" ) . Default ( defaultTunnelServerPort ) . String ( ) ,
Assets : kingpin . Flag ( "assets" , "Path to the assets" ) . Default ( defaultAssetsDirectory ) . Short ( 'a' ) . String ( ) ,
Data : kingpin . Flag ( "data" , "Path to the folder where the data is stored" ) . Default ( defaultDataDirectory ) . Short ( 'd' ) . String ( ) ,
2021-09-08 08:42:17 +00:00
EndpointURL : kingpin . Flag ( "host" , "Environment URL" ) . Short ( 'H' ) . String ( ) ,
2021-11-14 23:00:25 +00:00
FeatureFlags : BoolPairs ( kingpin . Flag ( "feat" , "List of feature flags" ) . Hidden ( ) ) ,
2020-06-16 07:55:45 +00:00
EnableEdgeComputeFeatures : kingpin . Flag ( "edge-compute" , "Enable Edge Compute features" ) . Bool ( ) ,
2020-08-26 11:58:19 +00:00
NoAnalytics : kingpin . Flag ( "no-analytics" , "Disable Analytics in app (deprecated)" ) . Bool ( ) ,
2020-06-16 07:55:45 +00:00
TLS : kingpin . Flag ( "tlsverify" , "TLS support" ) . Default ( defaultTLS ) . Bool ( ) ,
TLSSkipVerify : kingpin . Flag ( "tlsskipverify" , "Disable TLS server verification" ) . Default ( defaultTLSSkipVerify ) . Bool ( ) ,
TLSCacert : kingpin . Flag ( "tlscacert" , "Path to the CA" ) . Default ( defaultTLSCACertPath ) . String ( ) ,
TLSCert : kingpin . Flag ( "tlscert" , "Path to the TLS certificate file" ) . Default ( defaultTLSCertPath ) . String ( ) ,
TLSKey : kingpin . Flag ( "tlskey" , "Path to the TLS key" ) . Default ( defaultTLSKeyPath ) . String ( ) ,
2021-08-10 04:59:47 +00:00
HTTPDisabled : kingpin . Flag ( "http-disabled" , "Serve portainer only on https" ) . Default ( defaultHTTPDisabled ) . Bool ( ) ,
2021-12-14 00:40:44 +00:00
HTTPEnabled : kingpin . Flag ( "http-enabled" , "Serve portainer on http" ) . Default ( defaultHTTPEnabled ) . Bool ( ) ,
2021-08-10 04:59:47 +00:00
SSL : kingpin . Flag ( "ssl" , "Secure Portainer instance using SSL (deprecated)" ) . Default ( defaultSSL ) . Bool ( ) ,
SSLCert : kingpin . Flag ( "sslcert" , "Path to the SSL certificate used to secure the Portainer instance" ) . String ( ) ,
SSLKey : kingpin . Flag ( "sslkey" , "Path to the SSL key used to secure the Portainer instance" ) . String ( ) ,
2021-09-27 00:52:50 +00:00
Rollback : kingpin . Flag ( "rollback" , "Rollback the database store to the previous version" ) . Bool ( ) ,
2022-01-28 12:28:34 +00:00
SnapshotInterval : kingpin . Flag ( "snapshot-interval" , "Duration between each environment snapshot job" ) . String ( ) ,
2020-06-16 07:55:45 +00:00
AdminPassword : kingpin . Flag ( "admin-password" , "Hashed admin password" ) . String ( ) ,
AdminPasswordFile : kingpin . Flag ( "admin-password-file" , "Path to the file containing the password for the admin user" ) . String ( ) ,
Labels : pairs ( kingpin . Flag ( "hide-label" , "Hide containers with a specific label in the UI" ) . Short ( 'l' ) ) ,
Logo : kingpin . Flag ( "logo" , "URL for the logo displayed in the UI" ) . String ( ) ,
Templates : kingpin . Flag ( "templates" , "URL to the templates definitions." ) . Short ( 't' ) . String ( ) ,
2021-12-03 01:34:45 +00:00
BaseURL : kingpin . Flag ( "base-url" , "Base URL parameter such as portainer if running portainer as http://yourdomain.com/portainer/." ) . Short ( 'b' ) . Default ( defaultBaseURL ) . String ( ) ,
2022-01-17 22:25:29 +00:00
InitialMmapSize : kingpin . Flag ( "initial-mmap-size" , "Initial mmap size of the database in bytes" ) . Int ( ) ,
MaxBatchSize : kingpin . Flag ( "max-batch-size" , "Maximum size of a batch" ) . Int ( ) ,
MaxBatchDelay : kingpin . Flag ( "max-batch-delay" , "Maximum delay before a batch starts" ) . Duration ( ) ,
2022-01-17 03:40:02 +00:00
SecretKeyName : kingpin . Flag ( "secret-key-name" , "Secret key name for encryption and will be used as /run/secrets/<secret-key-name>." ) . Default ( defaultSecretKeyName ) . String ( ) ,
2016-12-18 05:21:29 +00:00
}
kingpin . Parse ( )
2017-10-26 09:17:45 +00:00
if ! filepath . IsAbs ( * flags . Assets ) {
ex , err := os . Executable ( )
if err != nil {
panic ( err )
}
* flags . Assets = filepath . Join ( filepath . Dir ( ex ) , * flags . Assets )
}
2016-12-18 05:21:29 +00:00
return flags , nil
}
// ValidateFlags validates the values of the flags.
func ( * Service ) ValidateFlags ( flags * portainer . CLIFlags ) error {
2017-02-07 03:26:12 +00:00
2020-05-13 04:21:17 +00:00
displayDeprecationWarnings ( flags )
2020-04-15 05:49:34 +00:00
err := validateEndpointURL ( * flags . EndpointURL )
2017-02-07 03:26:12 +00:00
if err != nil {
return err
}
2018-07-11 08:39:20 +00:00
err = validateSnapshotInterval ( * flags . SnapshotInterval )
if err != nil {
return err
}
2017-09-25 16:13:56 +00:00
if * flags . AdminPassword != "" && * flags . AdminPasswordFile != "" {
return errAdminPassExcludeAdminPassFile
}
2017-02-07 03:26:12 +00:00
return nil
}
2020-05-13 04:21:17 +00:00
func displayDeprecationWarnings ( flags * portainer . CLIFlags ) {
2020-08-26 11:58:19 +00:00
if * flags . NoAnalytics {
log . Println ( "Warning: The --no-analytics flag has been kept to allow migration of instances running a previous version of Portainer with this flag enabled, to version 2.0 where enabling this flag will have no effect." )
2020-08-06 22:46:25 +00:00
}
2021-08-10 04:59:47 +00:00
if * flags . SSL {
log . Println ( "Warning: SSL is enabled by default and there is no need for the --ssl flag. It has been kept to allow migration of instances running a previous version of Portainer with this flag enabled" )
}
2020-05-13 04:21:17 +00:00
}
2018-05-19 14:25:11 +00:00
func validateEndpointURL ( endpointURL string ) error {
if endpointURL != "" {
2018-07-20 09:02:06 +00:00
if ! strings . HasPrefix ( endpointURL , "unix://" ) && ! strings . HasPrefix ( endpointURL , "tcp://" ) && ! strings . HasPrefix ( endpointURL , "npipe://" ) {
2017-04-16 07:54:51 +00:00
return errInvalidEndpointProtocol
2016-12-25 20:34:02 +00:00
}
2016-12-18 05:21:29 +00:00
2018-07-20 09:02:06 +00:00
if strings . HasPrefix ( endpointURL , "unix://" ) || strings . HasPrefix ( endpointURL , "npipe://" ) {
2018-05-19 14:25:11 +00:00
socketPath := strings . TrimPrefix ( endpointURL , "unix://" )
2018-07-20 09:02:06 +00:00
socketPath = strings . TrimPrefix ( socketPath , "npipe://" )
2016-12-25 20:34:02 +00:00
if _ , err := os . Stat ( socketPath ) ; err != nil {
if os . IsNotExist ( err ) {
2018-07-20 09:02:06 +00:00
return errSocketOrNamedPipeNotFound
2016-12-25 20:34:02 +00:00
}
return err
2016-12-18 05:21:29 +00:00
}
}
}
2017-02-07 03:26:12 +00:00
return nil
}
2016-12-18 05:21:29 +00:00
2018-07-11 08:39:20 +00:00
func validateSnapshotInterval ( snapshotInterval string ) error {
2022-01-28 12:28:34 +00:00
if snapshotInterval != "" {
2018-07-11 08:39:20 +00:00
_ , err := time . ParseDuration ( snapshotInterval )
if err != nil {
return errInvalidSnapshotInterval
}
}
return nil
}