mirror of https://github.com/portainer/portainer
feat(api): ping the endpoint at creation time (#1817)
parent
031b428e0c
commit
05d6abf57b
|
@ -8,6 +8,27 @@ import (
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func CreateTLSConfig(caCert, cert, key []byte, skipClientVerification, skipServerVerification bool) (*tls.Config, error) {
|
||||||
|
config := &tls.Config{}
|
||||||
|
config.InsecureSkipVerify = skipServerVerification
|
||||||
|
|
||||||
|
if !skipClientVerification {
|
||||||
|
certificate, err := tls.X509KeyPair(cert, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Certificates = []tls.Certificate{certificate}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !skipServerVerification {
|
||||||
|
caCertPool := x509.NewCertPool()
|
||||||
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
config.RootCAs = caCertPool
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateTLSConfiguration initializes a tls.Config using a CA certificate, a certificate and a key
|
// CreateTLSConfiguration initializes a tls.Config using a CA certificate, a certificate and a key
|
||||||
func CreateTLSConfiguration(config *portainer.TLSConfiguration) (*tls.Config, error) {
|
func CreateTLSConfiguration(config *portainer.TLSConfiguration) (*tls.Config, error) {
|
||||||
TLSConfig := &tls.Config{}
|
TLSConfig := &tls.Config{}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/portainer/portainer"
|
"github.com/portainer/portainer"
|
||||||
|
"github.com/portainer/portainer/crypto"
|
||||||
httperror "github.com/portainer/portainer/http/error"
|
httperror "github.com/portainer/portainer/http/error"
|
||||||
"github.com/portainer/portainer/http/proxy"
|
"github.com/portainer/portainer/http/proxy"
|
||||||
"github.com/portainer/portainer/http/security"
|
"github.com/portainer/portainer/http/security"
|
||||||
|
@ -56,15 +62,6 @@ func NewEndpointHandler(bouncer *security.RequestBouncer, authorizeEndpointManag
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
postEndpointsRequest struct {
|
|
||||||
Name string `valid:"required"`
|
|
||||||
URL string `valid:"required"`
|
|
||||||
PublicURL string `valid:"-"`
|
|
||||||
TLS bool
|
|
||||||
TLSSkipVerify bool
|
|
||||||
TLSSkipClientVerify bool
|
|
||||||
}
|
|
||||||
|
|
||||||
postEndpointsResponse struct {
|
postEndpointsResponse struct {
|
||||||
ID int `json:"Id"`
|
ID int `json:"Id"`
|
||||||
}
|
}
|
||||||
|
@ -82,6 +79,18 @@ type (
|
||||||
TLSSkipVerify bool `valid:"-"`
|
TLSSkipVerify bool `valid:"-"`
|
||||||
TLSSkipClientVerify bool `valid:"-"`
|
TLSSkipClientVerify bool `valid:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postEndpointPayload struct {
|
||||||
|
name string
|
||||||
|
url string
|
||||||
|
publicURL string
|
||||||
|
useTLS bool
|
||||||
|
skipTLSServerVerification bool
|
||||||
|
skipTLSClientVerification bool
|
||||||
|
caCert []byte
|
||||||
|
cert []byte
|
||||||
|
key []byte
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// handleGetEndpoints handles GET requests on /endpoints
|
// handleGetEndpoints handles GET requests on /endpoints
|
||||||
|
@ -107,32 +116,48 @@ func (handler *EndpointHandler) handleGetEndpoints(w http.ResponseWriter, r *htt
|
||||||
encodeJSON(w, filteredEndpoints, handler.Logger)
|
encodeJSON(w, filteredEndpoints, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlePostEndpoints handles POST requests on /endpoints
|
func sendPingRequest(host string, tlsConfig *tls.Config) error {
|
||||||
func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *http.Request) {
|
transport := &http.Transport{}
|
||||||
if !handler.authorizeEndpointManagement {
|
|
||||||
httperror.WriteErrorResponse(w, ErrEndpointManagementDisabled, http.StatusServiceUnavailable, handler.Logger)
|
scheme := "http"
|
||||||
return
|
if tlsConfig != nil {
|
||||||
|
transport.TLSClientConfig = tlsConfig
|
||||||
|
scheme = "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
var req postEndpointsRequest
|
client := &http.Client{
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
Timeout: time.Second * 3,
|
||||||
httperror.WriteErrorResponse(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
Transport: transport,
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := govalidator.ValidateStruct(req)
|
pingOperationURL := strings.Replace(host, "tcp://", scheme+"://", 1) + "/_ping"
|
||||||
|
_, err := client.Get(pingOperationURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, ErrInvalidRequestFormat, http.StatusBadRequest, handler.Logger)
|
return err
|
||||||
return
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *EndpointHandler) createTLSSecuredEndpoint(payload *postEndpointPayload) (*portainer.Endpoint, error) {
|
||||||
|
|
||||||
|
tlsConfig, err := crypto.CreateTLSConfig(payload.caCert, payload.cert, payload.key, payload.skipTLSClientVerification, payload.skipTLSServerVerification)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sendPingRequest(payload.url, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint := &portainer.Endpoint{
|
endpoint := &portainer.Endpoint{
|
||||||
Name: req.Name,
|
Name: payload.name,
|
||||||
URL: req.URL,
|
URL: payload.url,
|
||||||
PublicURL: req.PublicURL,
|
PublicURL: payload.publicURL,
|
||||||
TLSConfig: portainer.TLSConfiguration{
|
TLSConfig: portainer.TLSConfiguration{
|
||||||
TLS: req.TLS,
|
TLS: payload.useTLS,
|
||||||
TLSSkipVerify: req.TLSSkipVerify,
|
TLSSkipVerify: payload.skipTLSServerVerification,
|
||||||
},
|
},
|
||||||
AuthorizedUsers: []portainer.UserID{},
|
AuthorizedUsers: []portainer.UserID{},
|
||||||
AuthorizedTeams: []portainer.TeamID{},
|
AuthorizedTeams: []portainer.TeamID{},
|
||||||
|
@ -141,30 +166,147 @@ func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *ht
|
||||||
|
|
||||||
err = handler.EndpointService.CreateEndpoint(endpoint)
|
err = handler.EndpointService.CreateEndpoint(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
return nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.TLS {
|
|
||||||
folder := strconv.Itoa(int(endpoint.ID))
|
folder := strconv.Itoa(int(endpoint.ID))
|
||||||
|
|
||||||
if !req.TLSSkipVerify {
|
if !payload.skipTLSServerVerification {
|
||||||
|
r := bytes.NewReader(payload.caCert)
|
||||||
|
// TODO: review the API exposed by the FileService to store
|
||||||
|
// a file from a byte slice and return the path to the stored file instead
|
||||||
|
// of using multiple legacy calls (StoreTLSFile, GetPathForTLSFile) here.
|
||||||
|
err = handler.FileService.StoreTLSFile(folder, portainer.TLSFileCA, r)
|
||||||
|
if err != nil {
|
||||||
|
handler.EndpointService.DeleteEndpoint(endpoint.ID)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
caCertPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileCA)
|
caCertPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileCA)
|
||||||
endpoint.TLSConfig.TLSCACertPath = caCertPath
|
endpoint.TLSConfig.TLSCACertPath = caCertPath
|
||||||
}
|
}
|
||||||
|
|
||||||
if !req.TLSSkipClientVerify {
|
if !payload.skipTLSClientVerification {
|
||||||
|
r := bytes.NewReader(payload.cert)
|
||||||
|
err = handler.FileService.StoreTLSFile(folder, portainer.TLSFileCert, r)
|
||||||
|
if err != nil {
|
||||||
|
handler.EndpointService.DeleteEndpoint(endpoint.ID)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
certPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileCert)
|
certPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileCert)
|
||||||
endpoint.TLSConfig.TLSCertPath = certPath
|
endpoint.TLSConfig.TLSCertPath = certPath
|
||||||
|
|
||||||
|
r = bytes.NewReader(payload.key)
|
||||||
|
err = handler.FileService.StoreTLSFile(folder, portainer.TLSFileKey, r)
|
||||||
|
if err != nil {
|
||||||
|
handler.EndpointService.DeleteEndpoint(endpoint.ID)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
keyPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileKey)
|
keyPath, _ := handler.FileService.GetPathForTLSFile(folder, portainer.TLSFileKey)
|
||||||
endpoint.TLSConfig.TLSKeyPath = keyPath
|
endpoint.TLSConfig.TLSKeyPath = keyPath
|
||||||
}
|
}
|
||||||
|
|
||||||
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *EndpointHandler) createUnsecuredEndpoint(payload *postEndpointPayload) (*portainer.Endpoint, error) {
|
||||||
|
|
||||||
|
if !strings.HasPrefix(payload.url, "unix://") {
|
||||||
|
err := sendPingRequest(payload.url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint := &portainer.Endpoint{
|
||||||
|
Name: payload.name,
|
||||||
|
URL: payload.url,
|
||||||
|
PublicURL: payload.publicURL,
|
||||||
|
TLSConfig: portainer.TLSConfiguration{
|
||||||
|
TLS: false,
|
||||||
|
},
|
||||||
|
AuthorizedUsers: []portainer.UserID{},
|
||||||
|
AuthorizedTeams: []portainer.TeamID{},
|
||||||
|
Extensions: []portainer.EndpointExtension{},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := handler.EndpointService.CreateEndpoint(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *EndpointHandler) createEndpoint(payload *postEndpointPayload) (*portainer.Endpoint, error) {
|
||||||
|
if payload.useTLS {
|
||||||
|
return handler.createTLSSecuredEndpoint(payload)
|
||||||
|
}
|
||||||
|
return handler.createUnsecuredEndpoint(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertPostEndpointRequestToPayload(r *http.Request) (*postEndpointPayload, error) {
|
||||||
|
payload := &postEndpointPayload{}
|
||||||
|
payload.name = r.FormValue("Name")
|
||||||
|
payload.url = r.FormValue("URL")
|
||||||
|
payload.publicURL = r.FormValue("PublicURL")
|
||||||
|
|
||||||
|
if payload.name == "" || payload.url == "" {
|
||||||
|
return nil, ErrInvalidRequestFormat
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.useTLS = r.FormValue("TLS") == "true"
|
||||||
|
|
||||||
|
if payload.useTLS {
|
||||||
|
payload.skipTLSServerVerification = r.FormValue("TLSSkipVerify") == "true"
|
||||||
|
payload.skipTLSClientVerification = r.FormValue("TLSSkipClientVerify") == "true"
|
||||||
|
|
||||||
|
if !payload.skipTLSServerVerification {
|
||||||
|
caCert, err := getUploadedFileContent(r, "TLSCACertFile")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload.caCert = caCert
|
||||||
|
}
|
||||||
|
|
||||||
|
if !payload.skipTLSClientVerification {
|
||||||
|
cert, err := getUploadedFileContent(r, "TLSCertFile")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload.cert = cert
|
||||||
|
key, err := getUploadedFileContent(r, "TLSKeyFile")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload.key = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePostEndpoints handles POST requests on /endpoints
|
||||||
|
func (handler *EndpointHandler) handlePostEndpoints(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !handler.authorizeEndpointManagement {
|
||||||
|
httperror.WriteErrorResponse(w, ErrEndpointManagementDisabled, http.StatusServiceUnavailable, handler.Logger)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
payload, err := convertPostEndpointRequestToPayload(r)
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusBadRequest, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoint, err := handler.createEndpoint(payload)
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeJSON(w, &postEndpointsResponse{ID: int(endpoint.ID)}, handler.Logger)
|
encodeJSON(w, &postEndpointsResponse{ID: int(endpoint.ID)}, handler.Logger)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -95,3 +96,19 @@ func encodeJSON(w http.ResponseWriter, v interface{}, logger *log.Logger) {
|
||||||
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, logger)
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, logger)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getUploadedFileContent retrieve the content of a file uploaded in the request.
|
||||||
|
// Uses requestParameter as the key to retrieve the file in the request payload.
|
||||||
|
func getUploadedFileContent(request *http.Request, requestParameter string) ([]byte, error) {
|
||||||
|
file, _, err := request.FormFile(requestParameter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
fileContent, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fileContent, nil
|
||||||
|
}
|
||||||
|
|
|
@ -84,7 +84,6 @@
|
||||||
{{ $ctrl.formData.TLSCACert.name }}
|
{{ $ctrl.formData.TLSCACert.name }}
|
||||||
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSCACert && $ctrl.formData.TLSCACert === $ctrl.endpoint.TLSConfig.TLSCACert" aria-hidden="true"></i>
|
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSCACert && $ctrl.formData.TLSCACert === $ctrl.endpoint.TLSConfig.TLSCACert" aria-hidden="true"></i>
|
||||||
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSCACert" aria-hidden="true"></i>
|
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSCACert" aria-hidden="true"></i>
|
||||||
<i class="fa fa-circle-notch fa-spin" ng-if="state.uploadInProgress"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,7 +99,6 @@
|
||||||
{{ $ctrl.formData.TLSCert.name }}
|
{{ $ctrl.formData.TLSCert.name }}
|
||||||
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSCert && $ctrl.formData.TLSCert === $ctrl.endpoint.TLSConfig.TLSCert" aria-hidden="true"></i>
|
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSCert && $ctrl.formData.TLSCert === $ctrl.endpoint.TLSConfig.TLSCert" aria-hidden="true"></i>
|
||||||
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSCert" aria-hidden="true"></i>
|
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSCert" aria-hidden="true"></i>
|
||||||
<i class="fa fa-circle-notch fa-spin" ng-if="state.uploadInProgress"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -114,7 +112,6 @@
|
||||||
{{ $ctrl.formData.TLSKey.name }}
|
{{ $ctrl.formData.TLSKey.name }}
|
||||||
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSKey && $ctrl.formData.TLSKey === $ctrl.endpoint.TLSConfig.TLSKey" aria-hidden="true"></i>
|
<i class="fa fa-check green-icon" ng-if="$ctrl.formData.TLSKey && $ctrl.formData.TLSKey === $ctrl.endpoint.TLSConfig.TLSKey" aria-hidden="true"></i>
|
||||||
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSKey" aria-hidden="true"></i>
|
<i class="fa fa-times red-icon" ng-if="!$ctrl.formData.TLSKey" aria-hidden="true"></i>
|
||||||
<i class="fa fa-circle-notch fa-spin" ng-if="state.uploadInProgress"></i>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,7 +2,6 @@ angular.module('portainer.app')
|
||||||
.factory('Endpoints', ['$resource', 'API_ENDPOINT_ENDPOINTS', function EndpointsFactory($resource, API_ENDPOINT_ENDPOINTS) {
|
.factory('Endpoints', ['$resource', 'API_ENDPOINT_ENDPOINTS', function EndpointsFactory($resource, API_ENDPOINT_ENDPOINTS) {
|
||||||
'use strict';
|
'use strict';
|
||||||
return $resource(API_ENDPOINT_ENDPOINTS + '/:id/:action', {}, {
|
return $resource(API_ENDPOINT_ENDPOINTS + '/:id/:action', {}, {
|
||||||
create: { method: 'POST', ignoreLoadingBar: true },
|
|
||||||
query: { method: 'GET', isArray: true },
|
query: { method: 'GET', isArray: true },
|
||||||
get: { method: 'GET', params: { id: '@id' } },
|
get: { method: 'GET', params: { id: '@id' } },
|
||||||
update: { method: 'PUT', params: { id: '@id' } },
|
update: { method: 'PUT', params: { id: '@id' } },
|
||||||
|
|
|
@ -50,42 +50,28 @@ function EndpointServiceFactory($q, Endpoints, FileUploadService) {
|
||||||
};
|
};
|
||||||
|
|
||||||
service.createLocalEndpoint = function(name, URL, TLS, active) {
|
service.createLocalEndpoint = function(name, URL, TLS, active) {
|
||||||
var endpoint = {
|
var deferred = $q.defer();
|
||||||
Name: 'local',
|
|
||||||
URL: 'unix:///var/run/docker.sock',
|
FileUploadService.createEndpoint('local', 'unix:///var/run/docker.sock', '', false)
|
||||||
TLS: false
|
.then(function success(response) {
|
||||||
};
|
deferred.resolve(response.data);
|
||||||
return Endpoints.create({}, endpoint).$promise;
|
})
|
||||||
|
.catch(function error(err) {
|
||||||
|
deferred.reject({msg: 'Unable to create endpoint', err: err});
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
service.createRemoteEndpoint = function(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile) {
|
service.createRemoteEndpoint = function(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile) {
|
||||||
var endpoint = {
|
|
||||||
Name: name,
|
|
||||||
URL: 'tcp://' + URL,
|
|
||||||
PublicURL: PublicURL,
|
|
||||||
TLS: TLS,
|
|
||||||
TLSSkipVerify: TLSSkipVerify,
|
|
||||||
TLSSkipClientVerify: TLSSkipClientVerify
|
|
||||||
};
|
|
||||||
|
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
Endpoints.create({}, endpoint).$promise
|
|
||||||
.then(function success(data) {
|
FileUploadService.createEndpoint(name, 'tcp://' + URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile)
|
||||||
var endpointID = data.Id;
|
.then(function success(response) {
|
||||||
if (!TLSSkipVerify || !TLSSkipClientVerify) {
|
deferred.resolve(response.data);
|
||||||
deferred.notify({upload: true});
|
|
||||||
FileUploadService.uploadTLSFilesForEndpoint(endpointID, TLSCAFile, TLSCertFile, TLSKeyFile)
|
|
||||||
.then(function success() {
|
|
||||||
deferred.notify({upload: false});
|
|
||||||
deferred.resolve(data);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
deferred.resolve(data);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
deferred.notify({upload: false});
|
deferred.reject({msg: 'Unable to create endpoint', err: err});
|
||||||
deferred.reject({msg: 'Unable to upload TLS certs', err: err});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
|
|
@ -42,6 +42,24 @@ angular.module('portainer.app')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
service.createEndpoint = function(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile) {
|
||||||
|
return Upload.upload({
|
||||||
|
url: 'api/endpoints',
|
||||||
|
data: {
|
||||||
|
Name: name,
|
||||||
|
URL: URL,
|
||||||
|
PublicURL: PublicURL,
|
||||||
|
TLS: TLS,
|
||||||
|
TLSSkipVerify: TLSSkipVerify,
|
||||||
|
TLSSkipClientVerify: TLSSkipClientVerify,
|
||||||
|
TLSCACertFile: TLSCAFile,
|
||||||
|
TLSCertFile: TLSCertFile,
|
||||||
|
TLSKeyFile: TLSKeyFile
|
||||||
|
},
|
||||||
|
ignoreLoadingBar: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
service.uploadLDAPTLSFiles = function(TLSCAFile, TLSCertFile, TLSKeyFile) {
|
service.uploadLDAPTLSFiles = function(TLSCAFile, TLSCertFile, TLSKeyFile) {
|
||||||
var queue = [];
|
var queue = [];
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.controller('EndpointsController', ['$scope', '$state', '$filter', 'EndpointService', 'Notifications', 'SystemService', 'EndpointProvider',
|
.controller('EndpointsController', ['$scope', '$state', '$filter', 'EndpointService', 'Notifications',
|
||||||
function ($scope, $state, $filter, EndpointService, Notifications, SystemService, EndpointProvider) {
|
function ($scope, $state, $filter, EndpointService, Notifications) {
|
||||||
$scope.state = {
|
$scope.state = {
|
||||||
uploadInProgress: false,
|
uploadInProgress: false,
|
||||||
actionInProgress: false
|
actionInProgress: false
|
||||||
|
@ -30,34 +30,17 @@ function ($scope, $state, $filter, EndpointService, Notifications, SystemService
|
||||||
var TLSCertFile = TLSSkipClientVerify ? null : securityData.TLSCert;
|
var TLSCertFile = TLSSkipClientVerify ? null : securityData.TLSCert;
|
||||||
var TLSKeyFile = TLSSkipClientVerify ? null : securityData.TLSKey;
|
var TLSKeyFile = TLSSkipClientVerify ? null : securityData.TLSKey;
|
||||||
|
|
||||||
var endpointId;
|
|
||||||
$scope.state.actionInProgress = true;
|
$scope.state.actionInProgress = true;
|
||||||
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile)
|
EndpointService.createRemoteEndpoint(name, URL, PublicURL, TLS, TLSSkipVerify, TLSSkipClientVerify, TLSCAFile, TLSCertFile, TLSKeyFile)
|
||||||
.then(function success(data) {
|
|
||||||
endpointId = data.Id;
|
|
||||||
var currentEndpointId = EndpointProvider.endpointID();
|
|
||||||
EndpointProvider.setEndpointID(endpointId);
|
|
||||||
SystemService.info()
|
|
||||||
.then(function success() {
|
.then(function success() {
|
||||||
Notifications.success('Endpoint created', name);
|
Notifications.success('Endpoint created', name);
|
||||||
$state.reload();
|
$state.reload();
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to create endpoint');
|
Notifications.error('Failure', err, 'Unable to create endpoint');
|
||||||
EndpointService.deleteEndpoint(endpointId);
|
|
||||||
})
|
})
|
||||||
.finally(function final() {
|
.finally(function final() {
|
||||||
$scope.state.actionInProgress = false;
|
$scope.state.actionInProgress = false;
|
||||||
EndpointProvider.setEndpointID(currentEndpointId);
|
|
||||||
});
|
|
||||||
}, function error(err) {
|
|
||||||
$scope.state.uploadInProgress = false;
|
|
||||||
$scope.state.actionInProgress = false;
|
|
||||||
Notifications.error('Failure', err, 'Unable to create endpoint');
|
|
||||||
}, function update(evt) {
|
|
||||||
if (evt.upload) {
|
|
||||||
$scope.state.uploadInProgress = evt.upload;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to connect to the Docker environment');
|
Notifications.error('Failure', err, 'Unable to connect to the Docker environment');
|
||||||
EndpointService.deleteEndpoint(endpointID);
|
|
||||||
})
|
})
|
||||||
.finally(function final() {
|
.finally(function final() {
|
||||||
$scope.state.actionInProgress = false;
|
$scope.state.actionInProgress = false;
|
||||||
|
@ -81,7 +80,6 @@ function ($scope, $state, EndpointService, StateManager, EndpointProvider, Notif
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to connect to the Docker environment');
|
Notifications.error('Failure', err, 'Unable to connect to the Docker environment');
|
||||||
EndpointService.deleteEndpoint(endpointID);
|
|
||||||
})
|
})
|
||||||
.finally(function final() {
|
.finally(function final() {
|
||||||
$scope.state.actionInProgress = false;
|
$scope.state.actionInProgress = false;
|
||||||
|
|
Loading…
Reference in New Issue