diff --git a/api/cli/cli.go b/api/cli/cli.go index 6148fdc95..afb1814b4 100644 --- a/api/cli/cli.go +++ b/api/cli/cli.go @@ -15,11 +15,12 @@ import ( type Service struct{} const ( - errInvalidEnpointProtocol = portainer.Error("Invalid endpoint protocol: Portainer only supports unix:// or tcp://") - errSocketNotFound = portainer.Error("Unable to locate Unix socket") - errEndpointsFileNotFound = portainer.Error("Unable to locate external endpoints file") - errInvalidSyncInterval = portainer.Error("Invalid synchronization interval") - errEndpointExcludeExternal = portainer.Error("Cannot use the -H flag mutually with --external-endpoints") + errInvalidEndpointProtocol = portainer.Error("Invalid endpoint protocol: Portainer only supports unix:// or tcp://") + errSocketNotFound = portainer.Error("Unable to locate Unix socket") + errEndpointsFileNotFound = portainer.Error("Unable to locate external endpoints file") + errInvalidSyncInterval = portainer.Error("Invalid synchronization interval") + errEndpointExcludeExternal = portainer.Error("Cannot use the -H flag mutually with --external-endpoints") + errNoAuthExcludeAdminPassword = portainer.Error("Cannot use --no-auth with --admin-password") ) // ParseFlags parse the CLI flags and return a portainer.Flags struct @@ -42,6 +43,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) { 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(), + AdminPassword: kingpin.Flag("admin-password", "Hashed admin password").String(), } kingpin.Parse() @@ -70,13 +72,17 @@ func (*Service) ValidateFlags(flags *portainer.CLIFlags) error { return err } + if *flags.NoAuth && (*flags.AdminPassword != "") { + return errNoAuthExcludeAdminPassword + } + return nil } func validateEndpoint(endpoint string) error { if endpoint != "" { if !strings.HasPrefix(endpoint, "unix://") && !strings.HasPrefix(endpoint, "tcp://") { - return errInvalidEnpointProtocol + return errInvalidEndpointProtocol } if strings.HasPrefix(endpoint, "unix://") { diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index 6ebdf1ee1..775f76718 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -140,6 +140,19 @@ func main() { } } + if *flags.AdminPassword != "" { + log.Printf("Creating admin user with password hash %s", *flags.AdminPassword) + user := &portainer.User{ + Username: "admin", + Role: portainer.AdministratorRole, + Password: *flags.AdminPassword, + } + err := store.UserService.CreateUser(user) + if err != nil { + log.Fatal(err) + } + } + var server portainer.Server = &http.Server{ BindAddress: *flags.Addr, AssetsPath: *flags.Assets, diff --git a/api/portainer.go b/api/portainer.go index fe02d6732..9d7fb3096 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -26,6 +26,7 @@ type ( TLSCacert *string TLSCert *string TLSKey *string + AdminPassword *string } // Settings represents Portainer settings. diff --git a/app/components/createContainer/createContainerController.js b/app/components/createContainer/createContainerController.js index f7b58efc6..0cb2a76dd 100644 --- a/app/components/createContainer/createContainerController.js +++ b/app/components/createContainer/createContainerController.js @@ -31,7 +31,8 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai Binds: [], NetworkMode: 'bridge', Privileged: false, - ExtraHosts: [] + ExtraHosts: [], + Devices:[] }, Labels: {} }; @@ -75,7 +76,14 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai $scope.removeExtraHost = function(index) { $scope.formValues.ExtraHosts.splice(index, 1); }; + + $scope.addDevice = function() { + $scope.config.HostConfig.Devices.push({ pathOnHost: '', pathInContainer: '' }); + }; + $scope.removeDevice = function(index) { + $scope.config.HostConfig.Devices.splice(index, 1); + }; Config.$promise.then(function (c) { var containersToHideLabels = c.hiddenLabels; @@ -275,6 +283,19 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai }); config.Labels = labels; } + + function prepareDevices(config) { + var path = []; + config.HostConfig.Devices.forEach(function (p) { + if (p.pathOnHost) { + if(p.pathInContainer === '') { + p.pathInContainer = p.pathOnHost; + } + path.push({PathOnHost:p.pathOnHost,PathInContainer:p.pathInContainer,CgroupPermissions:'rwm'}); + } + }); + config.HostConfig.Devices = path; + } function prepareConfiguration() { var config = angular.copy($scope.config); @@ -286,6 +307,7 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai prepareEnvironmentVariables(config); prepareVolumes(config); prepareLabels(config); + prepareDevices(config); return config; } diff --git a/app/components/createContainer/createcontainer.html b/app/components/createContainer/createcontainer.html index 3b5b13f30..cef979453 100644 --- a/app/components/createContainer/createcontainer.html +++ b/app/components/createContainer/createcontainer.html @@ -485,8 +485,38 @@ +
+ +
+
+ + + add device + +
+ +
+
+
+ host + +
+
+ container + +
+ +
+
+ +
+ +
+ - +