mirror of https://github.com/portainer/portainer
Merge branch 'develop' of github.com:portainer/portainer into develop
commit
7bf708faab
|
@ -15,11 +15,12 @@ import (
|
||||||
type Service struct{}
|
type Service struct{}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
errInvalidEnpointProtocol = portainer.Error("Invalid endpoint protocol: Portainer only supports unix:// or tcp://")
|
errInvalidEndpointProtocol = portainer.Error("Invalid endpoint protocol: Portainer only supports unix:// or tcp://")
|
||||||
errSocketNotFound = portainer.Error("Unable to locate Unix socket")
|
errSocketNotFound = portainer.Error("Unable to locate Unix socket")
|
||||||
errEndpointsFileNotFound = portainer.Error("Unable to locate external endpoints file")
|
errEndpointsFileNotFound = portainer.Error("Unable to locate external endpoints file")
|
||||||
errInvalidSyncInterval = portainer.Error("Invalid synchronization interval")
|
errInvalidSyncInterval = portainer.Error("Invalid synchronization interval")
|
||||||
errEndpointExcludeExternal = portainer.Error("Cannot use the -H flag mutually with --external-endpoints")
|
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
|
// 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(),
|
TLSCacert: kingpin.Flag("tlscacert", "Path to the CA").Default(defaultTLSCACertPath).String(),
|
||||||
TLSCert: kingpin.Flag("tlscert", "Path to the TLS certificate file").Default(defaultTLSCertPath).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(),
|
TLSKey: kingpin.Flag("tlskey", "Path to the TLS key").Default(defaultTLSKeyPath).String(),
|
||||||
|
AdminPassword: kingpin.Flag("admin-password", "Hashed admin password").String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
|
@ -70,13 +72,17 @@ func (*Service) ValidateFlags(flags *portainer.CLIFlags) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *flags.NoAuth && (*flags.AdminPassword != "") {
|
||||||
|
return errNoAuthExcludeAdminPassword
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateEndpoint(endpoint string) error {
|
func validateEndpoint(endpoint string) error {
|
||||||
if endpoint != "" {
|
if endpoint != "" {
|
||||||
if !strings.HasPrefix(endpoint, "unix://") && !strings.HasPrefix(endpoint, "tcp://") {
|
if !strings.HasPrefix(endpoint, "unix://") && !strings.HasPrefix(endpoint, "tcp://") {
|
||||||
return errInvalidEnpointProtocol
|
return errInvalidEndpointProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(endpoint, "unix://") {
|
if strings.HasPrefix(endpoint, "unix://") {
|
||||||
|
|
|
@ -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{
|
var server portainer.Server = &http.Server{
|
||||||
BindAddress: *flags.Addr,
|
BindAddress: *flags.Addr,
|
||||||
AssetsPath: *flags.Assets,
|
AssetsPath: *flags.Assets,
|
||||||
|
|
|
@ -26,6 +26,7 @@ type (
|
||||||
TLSCacert *string
|
TLSCacert *string
|
||||||
TLSCert *string
|
TLSCert *string
|
||||||
TLSKey *string
|
TLSKey *string
|
||||||
|
AdminPassword *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings represents Portainer settings.
|
// Settings represents Portainer settings.
|
||||||
|
|
|
@ -31,7 +31,8 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai
|
||||||
Binds: [],
|
Binds: [],
|
||||||
NetworkMode: 'bridge',
|
NetworkMode: 'bridge',
|
||||||
Privileged: false,
|
Privileged: false,
|
||||||
ExtraHosts: []
|
ExtraHosts: [],
|
||||||
|
Devices:[]
|
||||||
},
|
},
|
||||||
Labels: {}
|
Labels: {}
|
||||||
};
|
};
|
||||||
|
@ -75,7 +76,14 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai
|
||||||
$scope.removeExtraHost = function(index) {
|
$scope.removeExtraHost = function(index) {
|
||||||
$scope.formValues.ExtraHosts.splice(index, 1);
|
$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) {
|
Config.$promise.then(function (c) {
|
||||||
var containersToHideLabels = c.hiddenLabels;
|
var containersToHideLabels = c.hiddenLabels;
|
||||||
|
@ -275,6 +283,19 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai
|
||||||
});
|
});
|
||||||
config.Labels = labels;
|
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() {
|
function prepareConfiguration() {
|
||||||
var config = angular.copy($scope.config);
|
var config = angular.copy($scope.config);
|
||||||
|
@ -286,6 +307,7 @@ function ($scope, $state, $stateParams, $filter, Config, Info, Container, Contai
|
||||||
prepareEnvironmentVariables(config);
|
prepareEnvironmentVariables(config);
|
||||||
prepareVolumes(config);
|
prepareVolumes(config);
|
||||||
prepareLabels(config);
|
prepareLabels(config);
|
||||||
|
prepareDevices(config);
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -485,8 +485,38 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- !privileged-mode -->
|
<!-- !privileged-mode -->
|
||||||
</form>
|
</form>
|
||||||
|
<form class="form-horizontal" style="margin-top: 15px;">
|
||||||
|
<!-- devices -->
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-12" style="margin-top: 5px;">
|
||||||
|
<label class="control-label text-left">Devices</label>
|
||||||
|
<span class="label label-default interactive" style="margin-left: 10px;" ng-click="addDevice()">
|
||||||
|
<i class="fa fa-plus-circle" aria-hidden="true"></i> add device
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- devices-input-list -->
|
||||||
|
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
||||||
|
<div ng-repeat="device in config.HostConfig.Devices" style="margin-top: 2px;">
|
||||||
|
<div class="input-group col-sm-5 input-group-sm">
|
||||||
|
<span class="input-group-addon">host</span>
|
||||||
|
<input type="text" class="form-control" ng-model="device.pathOnHost" placeholder="e.g. /dev/tty0">
|
||||||
|
</div>
|
||||||
|
<div class="input-group col-sm-5 input-group-sm">
|
||||||
|
<span class="input-group-addon">container</span>
|
||||||
|
<input type="text" class="form-control" ng-model="device.pathInContainer" placeholder="e.g. /dev/tty0">
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-sm btn-danger" type="button" ng-click="removeDevice($index)">
|
||||||
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- !devices-input-list -->
|
||||||
|
</div>
|
||||||
|
<!-- !devices-->
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- !tab-runtime -->
|
<!-- !tab-runtime -->
|
||||||
</div>
|
</div>
|
||||||
</rd-widget-body>
|
</rd-widget-body>
|
||||||
</rd-widget>
|
</rd-widget>
|
||||||
|
|
Loading…
Reference in New Issue