feat(endpoints) - Access exposed containers on endpoint public URL (#826)

pull/838/head
Thomas Krzero 2017-05-01 12:19:43 +02:00 committed by Anthony Lapenna
parent 3d8eec2557
commit 7c6c9284f2
13 changed files with 73 additions and 12 deletions

View File

@ -108,6 +108,7 @@ func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *ht
endpoint := &portainer.Endpoint{
Name: req.Name,
URL: req.URL,
PublicURL: req.PublicURL,
TLS: req.TLS,
AuthorizedUsers: []portainer.UserID{},
}
@ -136,9 +137,10 @@ func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *ht
}
type postEndpointsRequest struct {
Name string `valid:"required"`
URL string `valid:"required"`
TLS bool
Name string `valid:"required"`
URL string `valid:"required"`
PublicURL string `valid:"-"`
TLS bool
}
type postEndpointsResponse struct {
@ -262,6 +264,10 @@ func (handler *EndpointHandler) handlePutEndpoint(w http.ResponseWriter, r *http
endpoint.URL = req.URL
}
if req.PublicURL != "" {
endpoint.PublicURL = req.PublicURL
}
if req.TLS {
endpoint.TLS = true
caCertPath, _ := handler.FileService.GetPathForTLSFile(endpoint.ID, portainer.TLSFileCA)
@ -296,9 +302,10 @@ func (handler *EndpointHandler) handlePutEndpoint(w http.ResponseWriter, r *http
}
type putEndpointsRequest struct {
Name string `valid:"-"`
URL string `valid:"-"`
TLS bool `valid:"-"`
Name string `valid:"-"`
URL string `valid:"-"`
PublicURL string `valid:"-"`
TLS bool `valid:"-"`
}
// handleDeleteEndpoint handles DELETE requests on /endpoints/:id

View File

@ -72,6 +72,7 @@ type (
ID EndpointID `json:"Id"`
Name string `json:"Name"`
URL string `json:"URL"`
PublicURL string `json:"PublicURL"`
TLS bool `json:"TLS"`
TLSCACertPath string `json:"TLSCACert,omitempty"`
TLSCertPath string `json:"TLSCert,omitempty"`

View File

@ -112,7 +112,7 @@
<td ng-if="state.displayIP">{{ container.IP ? container.IP : '-' }}</td>
<td ng-if="applicationState.endpoint.mode.provider === 'DOCKER_SWARM'">{{ container.hostIP }}</td>
<td>
<a ng-if="container.Ports.length > 0" ng-repeat="p in container.Ports" class="image-tag" ng-href="http://{{p.host}}:{{p.public}}" target="_blank">
<a ng-if="container.Ports.length > 0" ng-repeat="p in container.Ports" class="image-tag" ng-href="http://{{ PublicURL || p.host }}:{{p.public}}" target="_blank">
<i class="fa fa-external-link" aria-hidden="true"></i> {{p.public}}:{{ p.private }}
</a>
<span ng-if="container.Ports.length == 0" >-</span>

View File

@ -1,6 +1,6 @@
angular.module('containers', [])
.controller('ContainersController', ['$q', '$scope', '$filter', 'Container', 'ContainerHelper', 'Info', 'Settings', 'Notifications', 'Config', 'Pagination', 'EntityListService', 'ModalService', 'Authentication', 'ResourceControlService', 'UserService',
function ($q, $scope, $filter, Container, ContainerHelper, Info, Settings, Notifications, Config, Pagination, EntityListService, ModalService, Authentication, ResourceControlService, UserService) {
.controller('ContainersController', ['$q', '$scope', '$filter', 'Container', 'ContainerHelper', 'Info', 'Settings', 'Notifications', 'Config', 'Pagination', 'EntityListService', 'ModalService', 'Authentication', 'ResourceControlService', 'UserService', 'EndpointProvider',
function ($q, $scope, $filter, Container, ContainerHelper, Info, Settings, Notifications, Config, Pagination, EntityListService, ModalService, Authentication, ResourceControlService, UserService, EndpointProvider) {
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('containers');
$scope.state.displayAll = Settings.displayAll;
@ -12,6 +12,7 @@ angular.module('containers', [])
$scope.sortReverse = ($scope.sortType === sortType) ? !$scope.sortReverse : false;
$scope.sortType = sortType;
};
$scope.PublicURL = EndpointProvider.endpointPublicURL();
$scope.changePaginationCount = function() {
Pagination.setPaginationCount('containers', $scope.state.pagination_count);

View File

@ -31,6 +31,17 @@
</div>
</div>
<!-- !endpoint-url-input -->
<!-- endpoint-public-url-input -->
<div class="form-group">
<label for="endpoint_public_url" class="col-sm-3 col-lg-2 control-label text-left">
Public IP
<portainer-tooltip position="bottom" message="URL or IP address where exposed containers will be reachable. This field is optional and will default to the endpoint URL."></portainer-tooltip>
</label>
<div class="col-sm-9 col-lg-10">
<input ng-disabled="endpointType === 'local'" type="text" class="form-control" id="endpoint_public_url" ng-model="endpoint.PublicURL" placeholder="e.g. 10.0.0.10 or mydocker.mydomain.com">
</div>
</div>
<!-- !endpoint-public-url-input -->
<!-- tls-checkbox -->
<div class="form-group" ng-if="endpointType === 'remote'">
<div class="col-sm-12">

View File

@ -22,6 +22,7 @@ function ($scope, $state, $stateParams, $filter, EndpointService, Notifications)
var endpointParams = {
name: $scope.endpoint.Name,
URL: $scope.endpoint.URL,
PublicURL: $scope.endpoint.PublicURL,
TLS: $scope.endpoint.TLS,
TLSCACert: $scope.formValues.TLSCACert !== $scope.endpoint.TLSCACert ? $scope.formValues.TLSCACert : null,
TLSCert: $scope.formValues.TLSCert !== $scope.endpoint.TLSCert ? $scope.formValues.TLSCert : null,

View File

@ -67,12 +67,13 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
$scope.state.error = '';
var name = $scope.formValues.Name;
var URL = $scope.formValues.URL;
var PublicURL = URL.split(':')[0];
var TLS = $scope.formValues.TLS;
var TLSCAFile = $scope.formValues.TLSCACert;
var TLSCertFile = $scope.formValues.TLSCert;
var TLSKeyFile = $scope.formValues.TLSKey;
EndpointService.createRemoteEndpoint(name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile)
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile)
.then(function success(data) {
var endpointID = data.Id;
updateEndpointState(endpointID);

View File

@ -46,6 +46,17 @@
</div>
</div>
<!-- !endpoint-url-input -->
<!-- endpoint-public-url-input -->
<div class="form-group">
<label for="endpoint_public_url" class="col-sm-3 col-lg-2 control-label text-left">
Public IP
<portainer-tooltip position="bottom" message="URL or IP address where exposed containers will be reachable. This field is optional and will default to the endpoint URL."></portainer-tooltip>
</label>
<div class="col-sm-9 col-lg-10">
<input type="text" class="form-control" id="endpoint_public_url" ng-model="formValues.PublicURL" placeholder="e.g. 10.0.0.10 or mydocker.mydomain.com">
</div>
</div>
<!-- !endpoint-public-url-input -->
<!-- tls-checkbox -->
<div class="form-group">
<div class="col-sm-12">

View File

@ -13,6 +13,7 @@ function ($scope, $state, EndpointService, EndpointProvider, Notifications, Pagi
$scope.formValues = {
Name: '',
URL: '',
PublicURL: '',
TLS: false,
TLSCACert: null,
TLSCert: null,
@ -49,11 +50,15 @@ function ($scope, $state, EndpointService, EndpointProvider, Notifications, Pagi
$scope.state.error = '';
var name = $scope.formValues.Name;
var URL = $scope.formValues.URL;
var PublicURL = $scope.formValues.PublicURL;
if (PublicURL === '') {
PublicURL = URL.split(':')[0];
}
var TLS = $scope.formValues.TLS;
var TLSCAFile = $scope.formValues.TLSCACert;
var TLSCertFile = $scope.formValues.TLSCert;
var TLSKeyFile = $scope.formValues.TLSKey;
EndpointService.createRemoteEndpoint(name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, false).then(function success(data) {
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile, false).then(function success(data) {
Notifications.success("Endpoint created", name);
$state.reload();
}, function error(err) {

View File

@ -11,7 +11,9 @@ function ($scope, $state, Settings, Config, EndpointService, StateManager, Endpo
$scope.switchEndpoint = function(endpoint) {
var activeEndpointID = EndpointProvider.endpointID();
var activeEndpointPublicURL = EndpointProvider.endpointPublicURL();
EndpointProvider.setEndpointID(endpoint.Id);
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
StateManager.updateEndpointState(true)
.then(function success() {
$state.go('dashboard');
@ -19,6 +21,7 @@ function ($scope, $state, Settings, Config, EndpointService, StateManager, Endpo
.catch(function error(err) {
Notifications.error("Failure", err, "Unable to connect to the Docker endpoint");
EndpointProvider.setEndpointID(activeEndpointID);
EndpointProvider.setEndpointPublicURL(activeEndpointPublicURL);
StateManager.updateEndpointState(true)
.then(function success() {});
});
@ -32,6 +35,7 @@ function ($scope, $state, Settings, Config, EndpointService, StateManager, Endpo
angular.forEach($scope.endpoints, function (endpoint) {
if (endpoint.Id === activeEndpointID) {
$scope.activeEndpoint = endpoint;
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
}
});
})

View File

@ -5,9 +5,13 @@ angular.module('portainer.services')
var service = {};
service.initialize = function() {
var endpointID = LocalStorage.getEndpointID();
var endpointPublicURL = LocalStorage.getEndpointPublicURL();
if (endpointID) {
endpoint.ID = endpointID;
}
if (endpointPublicURL) {
endpoint.PublicURL = endpointPublicURL;
}
};
service.clean = function() {
endpoint = {};
@ -19,5 +23,12 @@ angular.module('portainer.services')
endpoint.ID = id;
LocalStorage.storeEndpointID(id);
};
service.endpointPublicURL = function() {
return endpoint.PublicURL;
}
service.setEndpointPublicURL = function(publicURL) {
endpoint.PublicURL = publicURL;
LocalStorage.storeEndpointPublicURL(publicURL);
}
return service;
}]);

View File

@ -18,6 +18,7 @@ angular.module('portainer.services')
service.updateEndpoint = function(id, endpointParams) {
var query = {
name: endpointParams.name,
PublicURL: endpointParams.PublicURL,
TLS: endpointParams.TLS,
authorizedUsers: endpointParams.authorizedUsers
};
@ -54,10 +55,11 @@ angular.module('portainer.services')
return Endpoints.create({}, endpoint).$promise;
};
service.createRemoteEndpoint = function(name, URL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile) {
service.createRemoteEndpoint = function(name, URL, PublicURL, TLS, TLSCAFile, TLSCertFile, TLSKeyFile) {
var endpoint = {
Name: name,
URL: 'tcp://' + URL,
PublicURL: PublicURL,
TLS: TLS
};
var deferred = $q.defer();

View File

@ -8,6 +8,12 @@ angular.module('portainer.services')
getEndpointID: function() {
return localStorageService.get('ENDPOINT_ID');
},
storeEndpointPublicURL: function(publicURL) {
localStorageService.set('ENDPOINT_PUBLIC_URL', publicURL);
},
getEndpointPublicURL: function() {
return localStorageService.get('ENDPOINT_PUBLIC_URL');
},
storeEndpointState: function(state) {
localStorageService.set('ENDPOINT_STATE', state);
},