mirror of https://github.com/portainer/portainer
feat(server): remove external endpoint feature (#3837)
* fix(prettier): auto format html files (#3836) * refactor(main): remove reference to external endpoints * refactor(cli): remove parsing of external endpoints param * refactor(portainer): remove types for external endpoints * refactor(endpoints): remove warning for external endpoints * refactor(endpoints): remove endpoint management setting * refactor(endpoints): remove ref to endpoint management * fix(main): remove endpoint management2.0
parent
d9665bc939
commit
c074a714cf
|
@ -20,9 +20,7 @@ const (
|
|||
errInvalidEndpointProtocol = portainer.Error("Invalid endpoint protocol: Portainer only supports unix://, npipe:// or tcp://")
|
||||
errSocketOrNamedPipeNotFound = portainer.Error("Unable to locate Unix socket or named pipe")
|
||||
errEndpointsFileNotFound = portainer.Error("Unable to locate external endpoints file")
|
||||
errInvalidSyncInterval = portainer.Error("Invalid synchronization interval")
|
||||
errInvalidSnapshotInterval = portainer.Error("Invalid snapshot interval")
|
||||
errEndpointExcludeExternal = portainer.Error("Cannot use the -H flag mutually with --external-endpoints")
|
||||
errNoAuthExcludeAdminPassword = portainer.Error("Cannot use --no-auth with --admin-password or --admin-password-file")
|
||||
errAdminPassExcludeAdminPassFile = portainer.Error("Cannot use --admin-password with --admin-password-file")
|
||||
)
|
||||
|
@ -38,7 +36,6 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
|
|||
Assets: kingpin.Flag("assets", "Path to the assets").Default(defaultAssetsDirectory).Short('a').String(),
|
||||
Data: kingpin.Flag("data", "Path to the folder where the data is stored").Default(defaultDataDirectory).Short('d').String(),
|
||||
EndpointURL: kingpin.Flag("host", "Endpoint URL").Short('H').String(),
|
||||
ExternalEndpoints: kingpin.Flag("external-endpoints", "Path to a file defining available endpoints (deprecated)").String(),
|
||||
NoAuth: kingpin.Flag("no-auth", "Disable authentication (deprecated)").Default(defaultNoAuth).Bool(),
|
||||
NoAnalytics: kingpin.Flag("no-analytics", "Disable Analytics in app").Default(defaultNoAnalytics).Bool(),
|
||||
TLS: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLS).Bool(),
|
||||
|
@ -49,7 +46,6 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
|
|||
SSL: kingpin.Flag("ssl", "Secure Portainer instance using SSL").Default(defaultSSL).Bool(),
|
||||
SSLCert: kingpin.Flag("sslcert", "Path to the SSL certificate used to secure the Portainer instance").Default(defaultSSLCertPath).String(),
|
||||
SSLKey: kingpin.Flag("sslkey", "Path to the SSL key used to secure the Portainer instance").Default(defaultSSLKeyPath).String(),
|
||||
SyncInterval: kingpin.Flag("sync-interval", "Duration between each synchronization via the external endpoints source (deprecated)").Default(defaultSyncInterval).String(),
|
||||
SnapshotInterval: kingpin.Flag("snapshot-interval", "Duration between each endpoint snapshot job").Default(defaultSnapshotInterval).String(),
|
||||
AdminPassword: kingpin.Flag("admin-password", "Hashed admin password").String(),
|
||||
AdminPasswordFile: kingpin.Flag("admin-password-file", "Path to the file containing the password for the admin user").String(),
|
||||
|
@ -76,25 +72,11 @@ func (*Service) ValidateFlags(flags *portainer.CLIFlags) error {
|
|||
|
||||
displayDeprecationWarnings(flags)
|
||||
|
||||
if *flags.EndpointURL != "" && *flags.ExternalEndpoints != "" {
|
||||
return errEndpointExcludeExternal
|
||||
}
|
||||
|
||||
err := validateEndpointURL(*flags.EndpointURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = validateExternalEndpoints(*flags.ExternalEndpoints)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = validateSyncInterval(*flags.SyncInterval)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = validateSnapshotInterval(*flags.SnapshotInterval)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -112,14 +94,6 @@ func (*Service) ValidateFlags(flags *portainer.CLIFlags) error {
|
|||
}
|
||||
|
||||
func displayDeprecationWarnings(flags *portainer.CLIFlags) {
|
||||
if *flags.ExternalEndpoints != "" {
|
||||
log.Println("Warning: the --external-endpoint flag is deprecated and will likely be removed in a future version of Portainer.")
|
||||
}
|
||||
|
||||
if *flags.SyncInterval != defaultSyncInterval {
|
||||
log.Println("Warning: the --sync-interval flag is deprecated and will likely be removed in a future version of Portainer.")
|
||||
}
|
||||
|
||||
if *flags.NoAuth {
|
||||
log.Println("Warning: the --no-auth flag is deprecated and will likely be removed in a future version of Portainer.")
|
||||
}
|
||||
|
@ -145,28 +119,6 @@ func validateEndpointURL(endpointURL string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func validateExternalEndpoints(externalEndpoints string) error {
|
||||
if externalEndpoints != "" {
|
||||
if _, err := os.Stat(externalEndpoints); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return errEndpointsFileNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateSyncInterval(syncInterval string) error {
|
||||
if syncInterval != defaultSyncInterval {
|
||||
_, err := time.ParseDuration(syncInterval)
|
||||
if err != nil {
|
||||
return errInvalidSyncInterval
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateSnapshotInterval(snapshotInterval string) error {
|
||||
if snapshotInterval != defaultSnapshotInterval {
|
||||
_, err := time.ParseDuration(snapshotInterval)
|
||||
|
|
|
@ -18,6 +18,5 @@ const (
|
|||
defaultSSL = "false"
|
||||
defaultSSLCertPath = "/certs/portainer.crt"
|
||||
defaultSSLKeyPath = "/certs/portainer.key"
|
||||
defaultSyncInterval = "60s"
|
||||
defaultSnapshotInterval = "5m"
|
||||
)
|
||||
|
|
|
@ -16,6 +16,5 @@ const (
|
|||
defaultSSL = "false"
|
||||
defaultSSLCertPath = "C:\\certs\\portainer.crt"
|
||||
defaultSSLKeyPath = "C:\\certs\\portainer.key"
|
||||
defaultSyncInterval = "60s"
|
||||
defaultSnapshotInterval = "5m"
|
||||
)
|
||||
|
|
|
@ -157,45 +157,6 @@ func loadSnapshotSystemSchedule(jobScheduler portainer.JobScheduler, snapshotter
|
|||
return nil
|
||||
}
|
||||
|
||||
func loadEndpointSyncSystemSchedule(jobScheduler portainer.JobScheduler, scheduleService portainer.ScheduleService, endpointService portainer.EndpointService, flags *portainer.CLIFlags) error {
|
||||
if *flags.ExternalEndpoints == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Println("Using external endpoint definition. Endpoint management via the API will be disabled.")
|
||||
|
||||
schedules, err := scheduleService.SchedulesByJobType(portainer.EndpointSyncJobType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(schedules) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
endpointSyncJob := &portainer.EndpointSyncJob{}
|
||||
|
||||
endpointSyncSchedule := &portainer.Schedule{
|
||||
ID: portainer.ScheduleID(scheduleService.GetNextIdentifier()),
|
||||
Name: "system_endpointsync",
|
||||
CronExpression: "@every " + *flags.SyncInterval,
|
||||
Recurring: true,
|
||||
JobType: portainer.EndpointSyncJobType,
|
||||
EndpointSyncJob: endpointSyncJob,
|
||||
Created: time.Now().Unix(),
|
||||
}
|
||||
|
||||
endpointSyncJobContext := cron.NewEndpointSyncJobContext(endpointService, *flags.ExternalEndpoints)
|
||||
endpointSyncJobRunner := cron.NewEndpointSyncJobRunner(endpointSyncSchedule, endpointSyncJobContext)
|
||||
|
||||
err = jobScheduler.ScheduleJob(endpointSyncJobRunner)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scheduleService.CreateSchedule(endpointSyncSchedule)
|
||||
}
|
||||
|
||||
func loadSchedulesFromDatabase(jobScheduler portainer.JobScheduler, jobService portainer.JobService, scheduleService portainer.ScheduleService, endpointService portainer.EndpointService, fileService portainer.FileService, reverseTunnelService portainer.ReverseTunnelService) error {
|
||||
schedules, err := scheduleService.Schedules()
|
||||
if err != nil {
|
||||
|
@ -225,12 +186,11 @@ func loadSchedulesFromDatabase(jobScheduler portainer.JobScheduler, jobService p
|
|||
return nil
|
||||
}
|
||||
|
||||
func initStatus(endpointManagement bool, flags *portainer.CLIFlags) *portainer.Status {
|
||||
func initStatus(flags *portainer.CLIFlags) *portainer.Status {
|
||||
return &portainer.Status{
|
||||
Analytics: !*flags.NoAnalytics,
|
||||
Authentication: !*flags.NoAuth,
|
||||
EndpointManagement: endpointManagement,
|
||||
Version: portainer.APIVersion,
|
||||
Analytics: !*flags.NoAnalytics,
|
||||
Authentication: !*flags.NoAuth,
|
||||
Version: portainer.APIVersion,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,11 +420,6 @@ func main() {
|
|||
|
||||
snapshotter := initSnapshotter(clientFactory)
|
||||
|
||||
endpointManagement := true
|
||||
if *flags.ExternalEndpoints != "" {
|
||||
endpointManagement = false
|
||||
}
|
||||
|
||||
swarmStackManager, err := initSwarmStackManager(*flags.Assets, *flags.Data, digitalSignatureService, fileService, reverseTunnelService)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -486,11 +441,6 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = loadEndpointSyncSystemSchedule(jobScheduler, store.ScheduleService, store.EndpointService, flags)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = loadSnapshotSystemSchedule(jobScheduler, snapshotter, store.ScheduleService, store.EndpointService, store.SettingsService)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -498,7 +448,7 @@ func main() {
|
|||
|
||||
jobScheduler.Start()
|
||||
|
||||
applicationStatus := initStatus(endpointManagement, flags)
|
||||
applicationStatus := initStatus(flags)
|
||||
|
||||
err = initEndpoint(flags, store.EndpointService, snapshotter)
|
||||
if err != nil {
|
||||
|
@ -557,7 +507,6 @@ func main() {
|
|||
BindAddress: *flags.Addr,
|
||||
AssetsPath: *flags.Assets,
|
||||
AuthDisabled: *flags.NoAuth,
|
||||
EndpointManagement: endpointManagement,
|
||||
RoleService: store.RoleService,
|
||||
UserService: store.UserService,
|
||||
TeamService: store.TeamService,
|
||||
|
|
|
@ -1,214 +0,0 @@
|
|||
package cron
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
// EndpointSyncJobRunner is used to run a EndpointSyncJob
|
||||
type EndpointSyncJobRunner struct {
|
||||
schedule *portainer.Schedule
|
||||
context *EndpointSyncJobContext
|
||||
}
|
||||
|
||||
// EndpointSyncJobContext represents the context of execution of a EndpointSyncJob
|
||||
type EndpointSyncJobContext struct {
|
||||
endpointService portainer.EndpointService
|
||||
endpointFilePath string
|
||||
}
|
||||
|
||||
// NewEndpointSyncJobContext returns a new context that can be used to execute a EndpointSyncJob
|
||||
func NewEndpointSyncJobContext(endpointService portainer.EndpointService, endpointFilePath string) *EndpointSyncJobContext {
|
||||
return &EndpointSyncJobContext{
|
||||
endpointService: endpointService,
|
||||
endpointFilePath: endpointFilePath,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEndpointSyncJobRunner returns a new runner that can be scheduled
|
||||
func NewEndpointSyncJobRunner(schedule *portainer.Schedule, context *EndpointSyncJobContext) *EndpointSyncJobRunner {
|
||||
return &EndpointSyncJobRunner{
|
||||
schedule: schedule,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
||||
type synchronization struct {
|
||||
endpointsToCreate []*portainer.Endpoint
|
||||
endpointsToUpdate []*portainer.Endpoint
|
||||
endpointsToDelete []*portainer.Endpoint
|
||||
}
|
||||
|
||||
type fileEndpoint struct {
|
||||
Name string `json:"Name"`
|
||||
URL string `json:"URL"`
|
||||
TLS bool `json:"TLS,omitempty"`
|
||||
TLSSkipVerify bool `json:"TLSSkipVerify,omitempty"`
|
||||
TLSCACert string `json:"TLSCACert,omitempty"`
|
||||
TLSCert string `json:"TLSCert,omitempty"`
|
||||
TLSKey string `json:"TLSKey,omitempty"`
|
||||
}
|
||||
|
||||
// GetSchedule returns the schedule associated to the runner
|
||||
func (runner *EndpointSyncJobRunner) GetSchedule() *portainer.Schedule {
|
||||
return runner.schedule
|
||||
}
|
||||
|
||||
// Run triggers the execution of the endpoint synchronization process.
|
||||
func (runner *EndpointSyncJobRunner) Run() {
|
||||
data, err := ioutil.ReadFile(runner.context.endpointFilePath)
|
||||
if endpointSyncError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
var fileEndpoints []fileEndpoint
|
||||
err = json.Unmarshal(data, &fileEndpoints)
|
||||
if endpointSyncError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(fileEndpoints) == 0 {
|
||||
log.Println("background job error (endpoint synchronization). External endpoint source is empty")
|
||||
return
|
||||
}
|
||||
|
||||
storedEndpoints, err := runner.context.endpointService.Endpoints()
|
||||
if endpointSyncError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
convertedFileEndpoints := convertFileEndpoints(fileEndpoints)
|
||||
|
||||
sync := prepareSyncData(storedEndpoints, convertedFileEndpoints)
|
||||
if sync.requireSync() {
|
||||
err = runner.context.endpointService.Synchronize(sync.endpointsToCreate, sync.endpointsToUpdate, sync.endpointsToDelete)
|
||||
if endpointSyncError(err) {
|
||||
return
|
||||
}
|
||||
log.Printf("Endpoint synchronization ended. [created: %v] [updated: %v] [deleted: %v]", len(sync.endpointsToCreate), len(sync.endpointsToUpdate), len(sync.endpointsToDelete))
|
||||
}
|
||||
}
|
||||
|
||||
func endpointSyncError(err error) bool {
|
||||
if err != nil {
|
||||
log.Printf("background job error (endpoint synchronization). Unable to synchronize endpoints (err=%s)\n", err)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isValidEndpoint(endpoint *portainer.Endpoint) bool {
|
||||
if endpoint.Name != "" && endpoint.URL != "" {
|
||||
if !strings.HasPrefix(endpoint.URL, "unix://") && !strings.HasPrefix(endpoint.URL, "tcp://") {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func convertFileEndpoints(fileEndpoints []fileEndpoint) []portainer.Endpoint {
|
||||
convertedEndpoints := make([]portainer.Endpoint, 0)
|
||||
|
||||
for _, e := range fileEndpoints {
|
||||
endpoint := portainer.Endpoint{
|
||||
Name: e.Name,
|
||||
URL: e.URL,
|
||||
TLSConfig: portainer.TLSConfiguration{},
|
||||
}
|
||||
if e.TLS {
|
||||
endpoint.TLSConfig.TLS = true
|
||||
endpoint.TLSConfig.TLSSkipVerify = e.TLSSkipVerify
|
||||
endpoint.TLSConfig.TLSCACertPath = e.TLSCACert
|
||||
endpoint.TLSConfig.TLSCertPath = e.TLSCert
|
||||
endpoint.TLSConfig.TLSKeyPath = e.TLSKey
|
||||
}
|
||||
convertedEndpoints = append(convertedEndpoints, endpoint)
|
||||
}
|
||||
|
||||
return convertedEndpoints
|
||||
}
|
||||
|
||||
func endpointExists(endpoint *portainer.Endpoint, endpoints []portainer.Endpoint) int {
|
||||
for idx, v := range endpoints {
|
||||
if endpoint.Name == v.Name && isValidEndpoint(&v) {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func mergeEndpointIfRequired(original, updated *portainer.Endpoint) *portainer.Endpoint {
|
||||
var endpoint *portainer.Endpoint
|
||||
if original.URL != updated.URL || original.TLSConfig.TLS != updated.TLSConfig.TLS ||
|
||||
(updated.TLSConfig.TLS && original.TLSConfig.TLSSkipVerify != updated.TLSConfig.TLSSkipVerify) ||
|
||||
(updated.TLSConfig.TLS && original.TLSConfig.TLSCACertPath != updated.TLSConfig.TLSCACertPath) ||
|
||||
(updated.TLSConfig.TLS && original.TLSConfig.TLSCertPath != updated.TLSConfig.TLSCertPath) ||
|
||||
(updated.TLSConfig.TLS && original.TLSConfig.TLSKeyPath != updated.TLSConfig.TLSKeyPath) {
|
||||
endpoint = original
|
||||
endpoint.URL = updated.URL
|
||||
if updated.TLSConfig.TLS {
|
||||
endpoint.TLSConfig.TLS = true
|
||||
endpoint.TLSConfig.TLSSkipVerify = updated.TLSConfig.TLSSkipVerify
|
||||
endpoint.TLSConfig.TLSCACertPath = updated.TLSConfig.TLSCACertPath
|
||||
endpoint.TLSConfig.TLSCertPath = updated.TLSConfig.TLSCertPath
|
||||
endpoint.TLSConfig.TLSKeyPath = updated.TLSConfig.TLSKeyPath
|
||||
} else {
|
||||
endpoint.TLSConfig.TLS = false
|
||||
endpoint.TLSConfig.TLSSkipVerify = false
|
||||
endpoint.TLSConfig.TLSCACertPath = ""
|
||||
endpoint.TLSConfig.TLSCertPath = ""
|
||||
endpoint.TLSConfig.TLSKeyPath = ""
|
||||
}
|
||||
}
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func (sync synchronization) requireSync() bool {
|
||||
if len(sync.endpointsToCreate) != 0 || len(sync.endpointsToUpdate) != 0 || len(sync.endpointsToDelete) != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func prepareSyncData(storedEndpoints, fileEndpoints []portainer.Endpoint) *synchronization {
|
||||
endpointsToCreate := make([]*portainer.Endpoint, 0)
|
||||
endpointsToUpdate := make([]*portainer.Endpoint, 0)
|
||||
endpointsToDelete := make([]*portainer.Endpoint, 0)
|
||||
|
||||
for idx := range storedEndpoints {
|
||||
fidx := endpointExists(&storedEndpoints[idx], fileEndpoints)
|
||||
if fidx != -1 {
|
||||
endpoint := mergeEndpointIfRequired(&storedEndpoints[idx], &fileEndpoints[fidx])
|
||||
if endpoint != nil {
|
||||
log.Printf("New definition for a stored endpoint found in file, updating database. [name: %v] [url: %v]\n", endpoint.Name, endpoint.URL)
|
||||
endpointsToUpdate = append(endpointsToUpdate, endpoint)
|
||||
}
|
||||
} else {
|
||||
log.Printf("Stored endpoint not found in file (definition might be invalid), removing from database. [name: %v] [url: %v]", storedEndpoints[idx].Name, storedEndpoints[idx].URL)
|
||||
endpointsToDelete = append(endpointsToDelete, &storedEndpoints[idx])
|
||||
}
|
||||
}
|
||||
|
||||
for idx, endpoint := range fileEndpoints {
|
||||
if !isValidEndpoint(&endpoint) {
|
||||
log.Printf("Invalid file endpoint definition, skipping. [name: %v] [url: %v]", endpoint.Name, endpoint.URL)
|
||||
continue
|
||||
}
|
||||
sidx := endpointExists(&fileEndpoints[idx], storedEndpoints)
|
||||
if sidx == -1 {
|
||||
log.Printf("File endpoint not found in database, adding to database. [name: %v] [url: %v]", fileEndpoints[idx].Name, fileEndpoints[idx].URL)
|
||||
endpointsToCreate = append(endpointsToCreate, &fileEndpoints[idx])
|
||||
}
|
||||
}
|
||||
|
||||
return &synchronization{
|
||||
endpointsToCreate: endpointsToCreate,
|
||||
endpointsToUpdate: endpointsToUpdate,
|
||||
endpointsToDelete: endpointsToDelete,
|
||||
}
|
||||
}
|
|
@ -131,10 +131,6 @@ func (payload *endpointCreatePayload) Validate(r *http.Request) error {
|
|||
|
||||
// POST request on /api/endpoints
|
||||
func (handler *Handler) endpointCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
if !handler.authorizeEndpointManagement {
|
||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Endpoint management is disabled", ErrEndpointManagementDisabled}
|
||||
}
|
||||
|
||||
payload := &endpointCreatePayload{}
|
||||
err := payload.Validate(r)
|
||||
if err != nil {
|
||||
|
|
|
@ -12,10 +12,6 @@ import (
|
|||
|
||||
// DELETE request on /api/endpoints/:id
|
||||
func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
if !handler.authorizeEndpointManagement {
|
||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Endpoint management is disabled", ErrEndpointManagementDisabled}
|
||||
}
|
||||
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid endpoint identifier route variable", err}
|
||||
|
|
|
@ -35,10 +35,6 @@ func (payload *endpointUpdatePayload) Validate(r *http.Request) error {
|
|||
|
||||
// PUT request on /api/endpoints/:id
|
||||
func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
if !handler.authorizeEndpointManagement {
|
||||
return &httperror.HandlerError{http.StatusServiceUnavailable, "Endpoint management is disabled", ErrEndpointManagementDisabled}
|
||||
}
|
||||
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid endpoint identifier route variable", err}
|
||||
|
|
|
@ -11,12 +11,6 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
const (
|
||||
// ErrEndpointManagementDisabled is an error raised when trying to access the endpoints management endpoints
|
||||
// when the server has been started with the --external-endpoints flag
|
||||
ErrEndpointManagementDisabled = portainer.Error("Endpoint management is disabled")
|
||||
)
|
||||
|
||||
func hideFields(endpoint *portainer.Endpoint) {
|
||||
endpoint.AzureCredentials = portainer.AzureCredentials{}
|
||||
if len(endpoint.Snapshots) > 0 {
|
||||
|
@ -27,7 +21,6 @@ func hideFields(endpoint *portainer.Endpoint) {
|
|||
// Handler is the HTTP handler used to handle endpoint operations.
|
||||
type Handler struct {
|
||||
*mux.Router
|
||||
authorizeEndpointManagement bool
|
||||
requestBouncer *security.RequestBouncer
|
||||
AuthorizationService *portainer.AuthorizationService
|
||||
EdgeGroupService portainer.EdgeGroupService
|
||||
|
@ -45,10 +38,9 @@ type Handler struct {
|
|||
}
|
||||
|
||||
// NewHandler creates a handler to manage endpoint operations.
|
||||
func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bool) *Handler {
|
||||
func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
||||
h := &Handler{
|
||||
Router: mux.NewRouter(),
|
||||
authorizeEndpointManagement: authorizeEndpointManagement,
|
||||
requestBouncer: bouncer,
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ type Server struct {
|
|||
BindAddress string
|
||||
AssetsPath string
|
||||
AuthDisabled bool
|
||||
EndpointManagement bool
|
||||
Status *portainer.Status
|
||||
ReverseTunnelService portainer.ReverseTunnelService
|
||||
ExtensionManager portainer.ExtensionManager
|
||||
|
@ -170,7 +169,7 @@ func (server *Server) Start() error {
|
|||
var edgeTemplatesHandler = edgetemplates.NewHandler(requestBouncer)
|
||||
edgeTemplatesHandler.SettingsService = server.SettingsService
|
||||
|
||||
var endpointHandler = endpoints.NewHandler(requestBouncer, server.EndpointManagement)
|
||||
var endpointHandler = endpoints.NewHandler(requestBouncer)
|
||||
endpointHandler.AuthorizationService = authorizationService
|
||||
endpointHandler.EdgeGroupService = server.EdgeGroupService
|
||||
endpointHandler.EdgeStackService = server.EdgeStackService
|
||||
|
|
|
@ -42,7 +42,6 @@ type (
|
|||
Assets *string
|
||||
Data *string
|
||||
EndpointURL *string
|
||||
ExternalEndpoints *string
|
||||
Labels *[]Pair
|
||||
Logo *string
|
||||
NoAuth *bool
|
||||
|
@ -56,7 +55,6 @@ type (
|
|||
SSL *bool
|
||||
SSLCert *string
|
||||
SSLKey *string
|
||||
SyncInterval *string
|
||||
SnapshotInterval *string
|
||||
}
|
||||
|
||||
|
@ -209,6 +207,8 @@ type (
|
|||
EndpointStatus int
|
||||
|
||||
// EndpointSyncJob represents a scheduled job that synchronize endpoints based on an external file
|
||||
//
|
||||
// Deprecated
|
||||
EndpointSyncJob struct{}
|
||||
|
||||
// EndpointType represents the type of an endpoint
|
||||
|
@ -402,7 +402,9 @@ type (
|
|||
EdgeSchedule *EdgeSchedule
|
||||
ScriptExecutionJob *ScriptExecutionJob
|
||||
SnapshotJob *SnapshotJob
|
||||
EndpointSyncJob *EndpointSyncJob
|
||||
|
||||
// Deprecated fields
|
||||
EndpointSyncJob *EndpointSyncJob
|
||||
}
|
||||
|
||||
// ScheduleID represents a schedule identifier.
|
||||
|
@ -490,10 +492,9 @@ type (
|
|||
|
||||
// Status represents the application status
|
||||
Status struct {
|
||||
Authentication bool `json:"Authentication"`
|
||||
EndpointManagement bool `json:"EndpointManagement"`
|
||||
Analytics bool `json:"Analytics"`
|
||||
Version string `json:"Version"`
|
||||
Authentication bool `json:"Authentication"`
|
||||
Analytics bool `json:"Analytics"`
|
||||
Version string `json:"Version"`
|
||||
}
|
||||
|
||||
// Tag represents a tag that can be associated to a resource
|
||||
|
@ -1097,7 +1098,7 @@ const (
|
|||
// SnapshotJobType is a system job used to create endpoint snapshots
|
||||
SnapshotJobType
|
||||
// EndpointSyncJobType is a system job used to synchronize endpoints from
|
||||
// an external definition store
|
||||
// an external definition store (Deprecated)
|
||||
EndpointSyncJobType
|
||||
)
|
||||
|
||||
|
|
|
@ -3164,10 +3164,6 @@ definitions:
|
|||
type: "boolean"
|
||||
example: true
|
||||
description: "Is authentication enabled"
|
||||
EndpointManagement:
|
||||
type: "boolean"
|
||||
example: true
|
||||
description: "Is endpoint management enabled"
|
||||
Analytics:
|
||||
type: "boolean"
|
||||
example: true
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div class="toolBar">
|
||||
<div class="toolBarTitle"> <i class="fa" ng-class="$ctrl.titleIcon" aria-hidden="true" style="margin-right: 2px;"></i> {{ $ctrl.titleText }} </div>
|
||||
</div>
|
||||
<div class="actionBar" ng-if="$ctrl.endpointManagement">
|
||||
<div class="actionBar">
|
||||
<button type="button" class="btn btn-sm btn-danger" ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
|
||||
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
|
||||
</button>
|
||||
|
@ -27,7 +27,7 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<span class="md-checkbox" ng-if="$ctrl.endpointManagement">
|
||||
<span class="md-checkbox">
|
||||
<input id="select_all" type="checkbox" ng-model="$ctrl.state.selectAll" ng-change="$ctrl.selectAll()" />
|
||||
<label for="select_all"></label>
|
||||
</span>
|
||||
|
@ -68,12 +68,11 @@
|
|||
ng-class="{ active: item.Checked }"
|
||||
>
|
||||
<td>
|
||||
<span class="md-checkbox" ng-if="$ctrl.endpointManagement">
|
||||
<span class="md-checkbox">
|
||||
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-click="$ctrl.selectItem(item, $event)" />
|
||||
<label for="select_{{ $index }}"></label>
|
||||
</span>
|
||||
<a ui-sref="portainer.endpoints.endpoint({id: item.Id})" ng-if="$ctrl.endpointManagement">{{ item.Name }}</a>
|
||||
<span ng-if="!$ctrl.endpointManagement">{{ item.Name }}</span>
|
||||
<a ui-sref="portainer.endpoints.endpoint({id: item.Id})">{{ item.Name }}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span>
|
||||
|
|
|
@ -7,7 +7,6 @@ angular.module('portainer.app').component('endpointsDatatable', {
|
|||
tableKey: '@',
|
||||
orderBy: '@',
|
||||
reverseOrder: '<',
|
||||
endpointManagement: '<',
|
||||
accessManagement: '<',
|
||||
removeAction: '<',
|
||||
retrievePage: '<',
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export function StatusViewModel(data) {
|
||||
this.Authentication = data.Authentication;
|
||||
this.Snapshot = data.Snapshot;
|
||||
this.EndpointManagement = data.EndpointManagement;
|
||||
this.Analytics = data.Analytics;
|
||||
this.Version = data.Version;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ angular.module('portainer.app').factory('StateManager', [
|
|||
function assignStateFromStatusAndSettings(status, settings) {
|
||||
state.application.authentication = status.Authentication;
|
||||
state.application.analytics = status.Analytics;
|
||||
state.application.endpointManagement = status.EndpointManagement;
|
||||
state.application.version = status.Version;
|
||||
state.application.logo = settings.LogoURL;
|
||||
state.application.snapshotInterval = settings.SnapshotInterval;
|
||||
|
|
|
@ -19,10 +19,6 @@ angular
|
|||
Notifications,
|
||||
Authentication
|
||||
) {
|
||||
if (!$scope.applicationState.application.endpointManagement) {
|
||||
$state.go('portainer.endpoints');
|
||||
}
|
||||
|
||||
$scope.state = {
|
||||
uploadInProgress: false,
|
||||
actionInProgress: false,
|
||||
|
|
|
@ -7,20 +7,6 @@
|
|||
<rd-header-content>Endpoint management</rd-header-content>
|
||||
</rd-header>
|
||||
|
||||
<div class="row" ng-if="!applicationState.application.endpointManagement">
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="fa-exclamation-triangle" title-text="Endpoint management is not available"> </rd-widget-header>
|
||||
<rd-widget-body>
|
||||
<span class="small text-muted"
|
||||
>Portainer has been started using the <code>--external-endpoints</code> flag. Endpoint management via the UI is disabled.
|
||||
<span ng-if="applicationState.application.authentication">You can still manage endpoint access.</span>
|
||||
</span>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<endpoints-datatable
|
||||
|
@ -28,7 +14,6 @@
|
|||
title-icon="fa-plug"
|
||||
table-key="endpoints"
|
||||
order-by="Name"
|
||||
endpoint-management="applicationState.application.endpointManagement"
|
||||
access-management="applicationState.application.authentication"
|
||||
remove-action="removeAction"
|
||||
retrieve-page="getPaginatedEndpoints"
|
||||
|
|
Loading…
Reference in New Issue