mirror of https://github.com/portainer/portainer
feat(endpoints) - Access exposed containers on endpoint public URL (#826)
parent
3d8eec2557
commit
7c6c9284f2
|
@ -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
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
|
@ -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;
|
||||
}]);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue