From bbb096412d2d049ad3017fbe5399b7ab5c006dbc Mon Sep 17 00:00:00 2001 From: Chaim Lev-Ari Date: Tue, 26 Apr 2022 14:25:20 +0300 Subject: [PATCH] fix(edge): show edge environment in edge views [EE-2997] (#6795) --- api/datastore/migrator/migrate_ce.go | 3 + api/datastore/migrator/migrate_dbversion40.go | 31 +++++++++ api/http/handler/endpoints/endpoint_list.go | 14 +++-- .../handler/endpoints/endpoint_list_test.go | 63 ++++++++++++------- .../edgeDevicesViewController.js | 7 ++- .../environments/environment.service/index.ts | 2 +- .../home/EnvironmentList/EnvironmentList.tsx | 1 + 7 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 api/datastore/migrator/migrate_dbversion40.go diff --git a/api/datastore/migrator/migrate_ce.go b/api/datastore/migrator/migrate_ce.go index 1004af53a..5536eb673 100644 --- a/api/datastore/migrator/migrate_ce.go +++ b/api/datastore/migrator/migrate_ce.go @@ -97,6 +97,9 @@ func (m *Migrator) Migrate() error { newMigration(35, m.migrateDBVersionToDB35), newMigration(36, m.migrateDBVersionToDB36), + + // Portainer 2.13 + newMigration(40, m.migrateDBVersionToDB40), } var lastDbVersion int diff --git a/api/datastore/migrator/migrate_dbversion40.go b/api/datastore/migrator/migrate_dbversion40.go new file mode 100644 index 000000000..e024d43d8 --- /dev/null +++ b/api/datastore/migrator/migrate_dbversion40.go @@ -0,0 +1,31 @@ +package migrator + +import "github.com/portainer/portainer/api/internal/endpointutils" + +func (m *Migrator) migrateDBVersionToDB40() error { + if err := m.trustCurrentEdgeEndpointsDB40(); err != nil { + return err + } + + return nil +} + +func (m *Migrator) trustCurrentEdgeEndpointsDB40() error { + migrateLog.Info("- trusting current edge endpoints") + endpoints, err := m.endpointService.Endpoints() + if err != nil { + return err + } + + for _, endpoint := range endpoints { + if endpointutils.IsEdgeEndpoint(&endpoint) { + endpoint.UserTrusted = true + err = m.endpointService.UpdateEndpoint(endpoint.ID, &endpoint) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/api/http/handler/endpoints/endpoint_list.go b/api/http/handler/endpoints/endpoint_list.go index 4bd51ab6a..d2084b8ed 100644 --- a/api/http/handler/endpoints/endpoint_list.go +++ b/api/http/handler/endpoints/endpoint_list.go @@ -21,6 +21,7 @@ const ( EdgeDeviceFilterAll = "all" EdgeDeviceFilterTrusted = "trusted" EdgeDeviceFilterUntrusted = "untrusted" + EdgeDeviceFilterNone = "none" ) var endpointGroupNames map[portainer.EndpointGroupID]string @@ -43,7 +44,7 @@ var endpointGroupNames map[portainer.EndpointGroupID]string // @param tagIds query []int false "search environments(endpoints) with these tags (depends on tagsPartialMatch)" // @param tagsPartialMatch query bool false "If true, will return environment(endpoint) which has one of tagIds, if false (or missing) will return only environments(endpoints) that has all the tags" // @param endpointIds query []int false "will return only these environments(endpoints)" -// @param edgeDeviceFilter query string false "will return only these edge devices" Enum("all", "trusted", "untrusted") +// @param edgeDeviceFilter query string false "will return only these edge environments, none will return only regular edge environments" Enum("all", "trusted", "untrusted", "none") // @success 200 {array} portainer.Endpoint "Endpoints" // @failure 500 "Server error" // @router /endpoints [get] @@ -334,10 +335,6 @@ func filterEndpointsByTypes(endpoints []portainer.Endpoint, endpointTypes []int) func filterEndpointsByEdgeDevice(endpoints []portainer.Endpoint, edgeDeviceFilter string) []portainer.Endpoint { filteredEndpoints := make([]portainer.Endpoint, 0) - if edgeDeviceFilter != EdgeDeviceFilterAll && edgeDeviceFilter != EdgeDeviceFilterTrusted && edgeDeviceFilter != EdgeDeviceFilterUntrusted { - return endpoints - } - for _, endpoint := range endpoints { if shouldReturnEdgeDevice(endpoint, edgeDeviceFilter) { filteredEndpoints = append(filteredEndpoints, endpoint) @@ -347,7 +344,12 @@ func filterEndpointsByEdgeDevice(endpoints []portainer.Endpoint, edgeDeviceFilte } func shouldReturnEdgeDevice(endpoint portainer.Endpoint, edgeDeviceFilter string) bool { - if !endpoint.IsEdgeDevice { + // none - return all endpoints that are not edge devices + if edgeDeviceFilter == EdgeDeviceFilterNone && !endpoint.IsEdgeDevice { + return true + } + + if !endpointutils.IsEdgeEndpoint(&endpoint) { return false } diff --git a/api/http/handler/endpoints/endpoint_list_test.go b/api/http/handler/endpoints/endpoint_list_test.go index 183f47976..269897687 100644 --- a/api/http/handler/endpoints/endpoint_list_test.go +++ b/api/http/handler/endpoints/endpoint_list_test.go @@ -17,27 +17,36 @@ import ( ) type endpointListEdgeDeviceTest struct { + title string expected []portainer.EndpointID filter string } func Test_endpointList(t *testing.T) { + var err error is := assert.New(t) _, store, teardown := datastore.MustNewTestStore(true, true) defer teardown() - trustedEndpoint := portainer.Endpoint{ID: 1, UserTrusted: true, IsEdgeDevice: true, GroupID: 1} - err := store.Endpoint().Create(&trustedEndpoint) - is.NoError(err, "error creating environment") + trustedEndpoint := portainer.Endpoint{ID: 1, UserTrusted: true, IsEdgeDevice: true, GroupID: 1, Type: portainer.EdgeAgentOnDockerEnvironment} + untrustedEndpoint := portainer.Endpoint{ID: 2, UserTrusted: false, IsEdgeDevice: true, GroupID: 1, Type: portainer.EdgeAgentOnDockerEnvironment} + regularUntrustedEdgeEndpoint := portainer.Endpoint{ID: 3, UserTrusted: false, IsEdgeDevice: false, GroupID: 1, Type: portainer.EdgeAgentOnDockerEnvironment} + regularTrustedEdgeEndpoint := portainer.Endpoint{ID: 4, UserTrusted: true, IsEdgeDevice: false, GroupID: 1, Type: portainer.EdgeAgentOnDockerEnvironment} + regularEndpoint := portainer.Endpoint{ID: 5, UserTrusted: false, IsEdgeDevice: false, GroupID: 1, Type: portainer.DockerEnvironment} - untrustedEndpoint := portainer.Endpoint{ID: 2, UserTrusted: false, IsEdgeDevice: true, GroupID: 1} - err = store.Endpoint().Create(&untrustedEndpoint) - is.NoError(err, "error creating environment") + endpoints := []portainer.Endpoint{ + trustedEndpoint, + untrustedEndpoint, + regularUntrustedEdgeEndpoint, + regularTrustedEdgeEndpoint, + regularEndpoint, + } - regularEndpoint := portainer.Endpoint{ID: 3, IsEdgeDevice: false, GroupID: 1} - err = store.Endpoint().Create(®ularEndpoint) - is.NoError(err, "error creating environment") + for _, endpoint := range endpoints { + err = store.Endpoint().Create(&endpoint) + is.NoError(err, "error creating environment") + } err = store.User().Create(&portainer.User{Username: "admin", Role: portainer.AdministratorRole}) is.NoError(err, "error creating a user") @@ -49,33 +58,45 @@ func Test_endpointList(t *testing.T) { tests := []endpointListEdgeDeviceTest{ { - []portainer.EndpointID{trustedEndpoint.ID, untrustedEndpoint.ID}, + "should show all edge endpoints", + []portainer.EndpointID{trustedEndpoint.ID, untrustedEndpoint.ID, regularUntrustedEdgeEndpoint.ID, regularTrustedEdgeEndpoint.ID}, EdgeDeviceFilterAll, }, { - []portainer.EndpointID{trustedEndpoint.ID}, + "should show only trusted edge devices", + []portainer.EndpointID{trustedEndpoint.ID, regularTrustedEdgeEndpoint.ID}, EdgeDeviceFilterTrusted, }, { - []portainer.EndpointID{untrustedEndpoint.ID}, + "should show only untrusted edge devices", + []portainer.EndpointID{untrustedEndpoint.ID, regularUntrustedEdgeEndpoint.ID}, EdgeDeviceFilterUntrusted, }, + { + "should show no edge devices", + []portainer.EndpointID{regularEndpoint.ID, regularUntrustedEdgeEndpoint.ID, regularTrustedEdgeEndpoint.ID}, + EdgeDeviceFilterNone, + }, } for _, test := range tests { - req := buildEndpointListRequest(test.filter) - resp, err := doEndpointListRequest(req, h, is) - is.NoError(err) + t.Run(test.title, func(t *testing.T) { + is := assert.New(t) - is.Equal(len(test.expected), len(resp)) + req := buildEndpointListRequest(test.filter) + resp, err := doEndpointListRequest(req, h, is) + is.NoError(err) - respIds := []portainer.EndpointID{} + is.Equal(len(test.expected), len(resp)) - for _, endpoint := range resp { - respIds = append(respIds, endpoint.ID) - } + respIds := []portainer.EndpointID{} - is.Equal(test.expected, respIds, "response should contain all edge devices") + for _, endpoint := range resp { + respIds = append(respIds, endpoint.ID) + } + + is.ElementsMatch(test.expected, respIds) + }) } } diff --git a/app/edge/views/edge-devices/edgeDevicesView/edgeDevicesViewController.js b/app/edge/views/edge-devices/edgeDevicesView/edgeDevicesViewController.js index f6892f234..a12f5c9e2 100644 --- a/app/edge/views/edge-devices/edgeDevicesView/edgeDevicesViewController.js +++ b/app/edge/views/edge-devices/edgeDevicesView/edgeDevicesViewController.js @@ -10,7 +10,12 @@ export function EdgeDevicesViewController($q, $async, EndpointService, GroupServ this.getEnvironments = function () { return $async(async () => { try { - const [endpointsResponse, groups] = await Promise.all([getEndpoints(0, 100, { edgeDeviceFilter: 'trusted' }), GroupService.groups()]); + const [endpointsResponse, groups] = await Promise.all([ + getEndpoints(0, 100, { + edgeDeviceFilter: 'trusted', + }), + GroupService.groups(), + ]); ctrl.groups = groups; ctrl.edgeDevices = endpointsResponse.value; } catch (err) { diff --git a/app/portainer/environments/environment.service/index.ts b/app/portainer/environments/environment.service/index.ts index 1a1dfdc17..bea2cfa0f 100644 --- a/app/portainer/environments/environment.service/index.ts +++ b/app/portainer/environments/environment.service/index.ts @@ -21,10 +21,10 @@ export interface EnvironmentsQueryParams { endpointIds?: EnvironmentId[]; tagsPartialMatch?: boolean; groupIds?: EnvironmentGroupId[]; - edgeDeviceFilter?: 'all' | 'trusted' | 'untrusted'; status?: EnvironmentStatus[]; sort?: string; order?: 'asc' | 'desc'; + edgeDeviceFilter?: 'all' | 'trusted' | 'untrusted' | 'none'; } export async function getEndpoints( diff --git a/app/portainer/home/EnvironmentList/EnvironmentList.tsx b/app/portainer/home/EnvironmentList/EnvironmentList.tsx index ad5ddec88..f95b1e628 100644 --- a/app/portainer/home/EnvironmentList/EnvironmentList.tsx +++ b/app/portainer/home/EnvironmentList/EnvironmentList.tsx @@ -132,6 +132,7 @@ export function EnvironmentList({ onClickItem, onRefresh }: Props) { groupIds: groupFilter, sort: sortByFilter, order: sortByDescending ? 'desc' : 'asc', + edgeDeviceFilter: 'none', }, true );