From 9b255fc4cfb1963e2b7eaa6c6198d11375b3586c Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Wed, 10 May 2023 09:28:05 -0300 Subject: [PATCH 001/115] add go reference badge (#2364) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fb6a7cb0d..f442e6353 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/orb-community/orb)](https://goreportcard.com/report/github.com/orb-community/orb) [![CodeCov](https://codecov.io/gh/orb-community/orb/branch/develop/graph/badge.svg)](https://app.codecov.io/gh/orb-community/orb/tree/develop) +[![Go Reference](https://pkg.go.dev/badge/github.com/orb-community/orb.svg)](https://pkg.go.dev/github.com/orb-community/orb) **Orb** is a modern network observability platform built to provide critical visibility into increasingly complex and distributed networks. It can analyze network traffic, run synthetic network probes, and connect the resulting telemetry directly to your existing observability stacks with OpenTelemetry. Orb differentiates from other solutions by pushing analysis close to the traffic sources (reducing inactionable metrics and processing costs), and allows for dynamic reconfiguration of remote agents in real time. From 0262fa254d571825c0ea66bf71a2d21f26fd2e74 Mon Sep 17 00:00:00 2001 From: manrodrigues Date: Wed, 10 May 2023 10:28:26 -0300 Subject: [PATCH 002/115] Avoid network error when erroring (#2366) * increasing the time to wait until next request to avoid connection problems --- python-test/features/steps/control_dataset_ui.py | 3 +-- python-test/features/steps/control_plane_agents.py | 2 +- python-test/features/steps/local_agent.py | 3 +-- python-test/features/steps/utils.py | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/python-test/features/steps/control_dataset_ui.py b/python-test/features/steps/control_dataset_ui.py index d424b7018..eaa72e373 100644 --- a/python-test/features/steps/control_dataset_ui.py +++ b/python-test/features/steps/control_dataset_ui.py @@ -60,8 +60,7 @@ def create_dataset_through_ui(context): break assert_that(context.dataset, is_not(None), "Unable to find dataset on orb backend") amount_of_datasets_after = wait_until_expected_amount_of_datasets_in_policy_view_page(context.driver, - amount_of_datasets_before + 1, - wait_time=1) + amount_of_datasets_before + 1) assert_that(amount_of_datasets_after, equal_to(amount_of_datasets_before + 1), f"Incorrect number of datasets.") diff --git a/python-test/features/steps/control_plane_agents.py b/python-test/features/steps/control_plane_agents.py index 37e44064f..4f7d4c1ec 100644 --- a/python-test/features/steps/control_plane_agents.py +++ b/python-test/features/steps/control_plane_agents.py @@ -752,7 +752,7 @@ def create_agent(token, name, tags, expected_status_code=201): :param expected_status_code: status code to be returned on response :returns: (dict) a dictionary containing the created agent data """ - response, response_json = wait_until_agent_being_created(token, name, tags, expected_status_code, wait_time=1) + response, response_json = wait_until_agent_being_created(token, name, tags, expected_status_code) assert_that(response.status_code, equal_to(expected_status_code), 'Request to create agent failed with status=' + str(response.status_code) + ":" + str(response_json)) diff --git a/python-test/features/steps/local_agent.py b/python-test/features/steps/local_agent.py index 18f72e0b3..29460d7fa 100644 --- a/python-test/features/steps/local_agent.py +++ b/python-test/features/steps/local_agent.py @@ -24,8 +24,7 @@ def check_metrics_by_handler(context, handler_type): policy_name = context.policy['name'] local_prometheus_endpoint = f"http://localhost:{context.port}/api/v1/policies/{policy_name}/metrics/prometheus" correct_metrics, metrics_dif, metrics_present = wait_until_metrics_scraped(local_prometheus_endpoint, - expected_metrics, timeout=60, - wait_time=5) + expected_metrics, timeout=60) expected_metrics_not_present = expected_metrics.difference(metrics_present) if expected_metrics_not_present == set(): expected_metrics_not_present = None diff --git a/python-test/features/steps/utils.py b/python-test/features/steps/utils.py index 96bda49ef..409c7f84b 100644 --- a/python-test/features/steps/utils.py +++ b/python-test/features/steps/utils.py @@ -175,7 +175,7 @@ def remove_key_from_json(json_file, key_to_be_removed): def threading_wait_until(func): - def wait_event(*args, wait_time=0.5, timeout=30, start_func_value=False, **kwargs): + def wait_event(*args, wait_time=5, timeout=35, start_func_value=False, **kwargs): event = threading.Event() func_value = start_func_value start = datetime.now().timestamp() From f906dbf7c23b23e0624922ba792ca7dc9d19ecfd Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 10 May 2023 14:26:10 -0300 Subject: [PATCH 003/115] fix(orb-ui): #767, Matching Agents, color of the state with conflict (#2363) --- .../agents/match/agent.match.component.html | 10 ++++++--- .../agents/match/agent.match.component.scss | 4 ++-- .../agents/match/agent.match.component.ts | 21 ++++++++++++------- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/ui/src/app/pages/fleet/agents/match/agent.match.component.html b/ui/src/app/pages/fleet/agents/match/agent.match.component.html index 3d1ed1cd3..9dbd339fa 100644 --- a/ui/src/app/pages/fleet/agents/match/agent.match.component.html +++ b/ui/src/app/pages/fleet/agents/match/agent.match.component.html @@ -62,8 +62,12 @@ - - - {{ value | titlecase }} + + {{ value | titlecase }} + + + {{ value | titlecase }} + \ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/match/agent.match.component.scss b/ui/src/app/pages/fleet/agents/match/agent.match.component.scss index f1375c70f..ad7b3c14a 100644 --- a/ui/src/app/pages/fleet/agents/match/agent.match.component.scss +++ b/ui/src/app/pages/fleet/agents/match/agent.match.component.scss @@ -32,13 +32,13 @@ nb-card { &new { color: #9b51e0; } - &online { + &online, &running { color: #6fcf97; } &stale { color: #f2994a; } - &error { + &error, &failed_to_apply { color: #df316f; } &offline { diff --git a/ui/src/app/pages/fleet/agents/match/agent.match.component.ts b/ui/src/app/pages/fleet/agents/match/agent.match.component.ts index 2a6659c6f..f2273ad6c 100644 --- a/ui/src/app/pages/fleet/agents/match/agent.match.component.ts +++ b/ui/src/app/pages/fleet/agents/match/agent.match.component.ts @@ -3,11 +3,11 @@ import { NbDialogRef } from '@nebular/theme'; import { STRINGS } from 'assets/text/strings'; import { ColumnMode, TableColumn } from '@swimlane/ngx-datatable'; import { DropdownFilterItem } from 'app/common/interfaces/mainflux.interface'; -import { Agent } from 'app/common/interfaces/orb/agent.interface'; +import { Agent, AgentPolicyAggStates } from 'app/common/interfaces/orb/agent.interface'; import { AgentGroup } from 'app/common/interfaces/orb/agent.group.interface'; import { AgentsService } from 'app/common/services/agents/agents.service'; import { Router } from '@angular/router'; -import { AgentPolicy } from 'app/common/interfaces/orb/agent.policy.interface'; +import { AgentPolicy, AgentPolicyStates } from 'app/common/interfaces/orb/agent.policy.interface'; @Component({ selector: 'ngx-agent-match-component', @@ -32,6 +32,10 @@ export class AgentMatchComponent implements OnInit, AfterViewInit { columns: TableColumn[]; + statePolicy: AgentPolicyAggStates; + + specificPolicy: boolean; + // templates @ViewChild('agentNameTemplateCell') agentNameTemplateCell: TemplateRef; @@ -39,7 +43,7 @@ export class AgentMatchComponent implements OnInit, AfterViewInit { @ViewChild('agentStateTemplateCell') agentStateTemplateRef: TemplateRef; - @ViewChild('agentEspecificPolicyStateTemplateCell') agentEspecificPolicyStateTemplateRef: TemplateRef; + @ViewChild('agentSpecificPolicyStateTemplateCell') agentSpecificPolicyStateTemplateRef: TemplateRef; tableFilters: DropdownFilterItem[] = [ { @@ -61,6 +65,7 @@ export class AgentMatchComponent implements OnInit, AfterViewInit { protected agentsService: AgentsService, protected router: Router, ) { + this.specificPolicy = false; } ngOnInit() { @@ -116,7 +121,7 @@ export class AgentMatchComponent implements OnInit, AfterViewInit { flexGrow: 3, canAutoResize: true, minWidth: 150, - cellTemplate: this.agentEspecificPolicyStateTemplateRef, + cellTemplate: this.agentSpecificPolicyStateTemplateRef, }, ]; } @@ -131,11 +136,11 @@ export class AgentMatchComponent implements OnInit, AfterViewInit { const tagsList = Object.keys(tags).map(key => ({ [key]: tags[key] })); this.agentsService.getAllAgents(tagsList).subscribe( resp => { - if(!!this.policy){ - this.agents = resp.map((agent)=>{ + if(!!this.policy) { + this.specificPolicy = true; + this.agents = resp.map((agent) => { const {policy_state} = agent; - const policy_agg_info = !!policy_state && policy_state[this.policy.id].state || "Not Applied"; - + const policy_agg_info = !!policy_state && policy_state[this.policy.id].state || AgentPolicyStates.failedToApply; return {...agent, policy_agg_info }; }) } else { From 0850d491d13e9b8f2b0f987e46dd001d1d8c865f Mon Sep 17 00:00:00 2001 From: brnvalenca <79707831+brnvalenca@users.noreply.github.com> Date: Wed, 10 May 2023 14:51:12 -0300 Subject: [PATCH 004/115] If format "json" is specified on sinks body, POST and PUT request fails with "error": "malformed entity specification" (ORB-725) (#2367) If format "json" is specified on sinks body, POST and PUT request fails with "error": "malformed entity specification" (ORB-725) (#2367) --- sinks/api/http/endpoint.go | 7 ++--- sinks/api/http/requests.go | 5 ++-- sinks/api/http/transport.go | 8 +++--- sinks/backend/prometheus/configuration.go | 33 +++++++++++------------ 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index 8a1101a2e..4d6d5334b 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -10,13 +10,14 @@ package http import ( "context" + "time" + "github.com/go-kit/kit/endpoint" "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks" "github.com/orb-community/orb/sinks/backend" "go.uber.org/zap" - "time" ) var restrictiveKeyPrefixes = []string{backend.ConfigFeatureTypePassword} @@ -57,7 +58,7 @@ func addEndpoint(svc sinks.SinkService) endpoint.Endpoint { } var config types.Metadata reqBackend := backend.GetBackend(req.Backend) - if req.Format != "" { + if req.Format == "yaml" { config, err = reqBackend.ParseConfig(req.Format, req.ConfigData) if err != nil { svc.GetLogger().Error("got error in parsing configuration", zap.Error(err)) @@ -125,7 +126,7 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { return nil, err } var config types.Metadata - if req.Format != "" { + if req.Format == "yaml" { config, err = sinkBackend.ParseConfig(req.Format, req.ConfigData) if err != nil { svc.GetLogger().Error("got error in parsing configuration", zap.Error(err)) diff --git a/sinks/api/http/requests.go b/sinks/api/http/requests.go index f9f5bfda0..675edee33 100644 --- a/sinks/api/http/requests.go +++ b/sinks/api/http/requests.go @@ -50,7 +50,7 @@ func (req addReq) validate() (err error) { } var config types.Metadata - if req.Format != "" { + if req.Format == "yaml" { config, err = reqBackend.ParseConfig(req.Format, req.ConfigData) if err != nil { return errors.Wrap(errors.ErrMalformedEntity, errors.New("invalid config")) @@ -72,7 +72,6 @@ func (req addReq) validate() (err error) { if err != nil { return errors.Wrap(errors.ErrMalformedEntity, errors.New("identifier duplicated")) } - return nil } @@ -100,7 +99,7 @@ func (req updateSinkReq) validate(sinkBackend backend.Backend) error { if req.ConfigData != "" || req.Config != nil { var config types.Metadata var err error - if req.Format != "" { + if req.Format == "yaml" { config, err = sinkBackend.ParseConfig(req.Format, req.ConfigData) if err != nil { return errors.Wrap(errors.ErrMalformedEntity, err) diff --git a/sinks/api/http/transport.go b/sinks/api/http/transport.go index 3a364926c..2fd7a444c 100644 --- a/sinks/api/http/transport.go +++ b/sinks/api/http/transport.go @@ -7,6 +7,10 @@ package http import ( "context" "encoding/json" + "io" + "net/http" + "strings" + kitot "github.com/go-kit/kit/tracing/opentracing" kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" @@ -18,9 +22,6 @@ import ( "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks" "github.com/prometheus/client_golang/prometheus/promhttp" - "io" - "net/http" - "strings" ) const ( @@ -104,7 +105,6 @@ func decodeAddRequest(_ context.Context, r *http.Request) (interface{}, error) { if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, errors.Wrap(errors.ErrMalformedEntity, err) } - return req, nil } diff --git a/sinks/backend/prometheus/configuration.go b/sinks/backend/prometheus/configuration.go index 96c58832b..f64067256 100644 --- a/sinks/backend/prometheus/configuration.go +++ b/sinks/backend/prometheus/configuration.go @@ -1,12 +1,13 @@ package prometheus import ( + "net/url" + "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks/backend" "golang.org/x/exp/maps" "gopkg.in/yaml.v3" - "net/url" ) func (p *Backend) ConfigToFormat(format string, metadata types.Metadata) (string, error) { @@ -29,23 +30,21 @@ func (p *Backend) ConfigToFormat(format string, metadata types.Metadata) (string } func (p *Backend) ParseConfig(format string, config string) (configReturn types.Metadata, err error) { - if format == "yaml" { - configAsByte := []byte(config) - // Parse the YAML data into a Config struct - var configUtil configParseUtility - err = yaml.Unmarshal(configAsByte, &configUtil) - if err != nil { - return nil, errors.Wrap(errors.New("failed to parse config YAML"), err) - } - configReturn = make(types.Metadata) - // Check for Token Auth - configReturn[RemoteHostURLConfigFeature] = configUtil.RemoteHost - configReturn[UsernameConfigFeature] = configUtil.Username - configReturn[PasswordConfigFeature] = configUtil.Password - return - } else { - return nil, errors.New("unsupported format") + + configAsByte := []byte(config) + // Parse the YAML data into a Config struct + var configUtil configParseUtility + err = yaml.Unmarshal(configAsByte, &configUtil) + if err != nil { + return nil, errors.Wrap(errors.New("failed to parse config YAML"), err) } + configReturn = make(types.Metadata) + // Check for Token Auth + configReturn[RemoteHostURLConfigFeature] = configUtil.RemoteHost + configReturn[UsernameConfigFeature] = configUtil.Username + configReturn[PasswordConfigFeature] = configUtil.Password + return + } func (p *Backend) ValidateConfiguration(config types.Metadata) error { From 8db3105b88e3bdd9870c40516b264033a754686a Mon Sep 17 00:00:00 2001 From: manrodrigues Date: Fri, 12 May 2023 11:51:05 -0300 Subject: [PATCH 005/115] Reverting orb 727 (#2371) * Revert "fix(sinks): fix sink errors. (#2270)" This reverts commit c4ec40b31c4f8b554fba6ea7f9345a424339f692. --- sinks/api/http/endpoint.go | 1 + sinks/postgres/sinks.go | 18 ++++-------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index 4d6d5334b..fbd2c45c4 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -201,6 +201,7 @@ func listSinksEndpoint(svc sinks.SinkService) endpoint.Endpoint { }, Sinks: []sinkRes{}, } + svc.GetLogger().Info("got sinks", zap.Int("length", len(page.Sinks))) for _, sink := range page.Sinks { reqBackend := backend.GetBackend(sink.Backend) omittedConfig, omittedConfigData := omitSecretInformation(reqBackend, sink.Format, sink.Config) diff --git a/sinks/postgres/sinks.go b/sinks/postgres/sinks.go index 67ed295b9..8516f7218 100644 --- a/sinks/postgres/sinks.go +++ b/sinks/postgres/sinks.go @@ -311,8 +311,8 @@ type dbSink struct { Name types.Identifier `db:"name"` MFOwnerID string `db:"mf_owner_id"` Metadata db.Metadata `db:"metadata"` - ConfigData *string `db:"config_data"` - Format *string `db:"format"` + ConfigData string `db:"config_data"` + Format string `db:"format"` Backend string `db:"backend"` Description string `db:"description"` Created time.Time `db:"ts_created"` @@ -341,8 +341,8 @@ func toDBSink(sink sinks.Sink) (dbSink, error) { Name: sink.Name, MFOwnerID: uID.String(), Metadata: db.Metadata(sink.Config), - ConfigData: &sink.ConfigData, - Format: &sink.Format, + ConfigData: sink.ConfigData, + Format: sink.Format, Backend: sink.Backend, Description: description, Created: sink.Created, @@ -354,14 +354,6 @@ func toDBSink(sink sinks.Sink) (dbSink, error) { } func toSink(dba dbSink) (sinks.Sink, error) { - configData := "" - format := "" - if dba.ConfigData != nil { - configData = *dba.ConfigData - } - if dba.Format != nil { - format = *dba.Format - } sink := sinks.Sink{ ID: dba.ID, Name: dba.Name, @@ -371,8 +363,6 @@ func toSink(dba dbSink) (sinks.Sink, error) { State: dba.State, Error: dba.Error, Config: types.Metadata(dba.Metadata), - ConfigData: configData, - Format: format, Created: dba.Created, Tags: types.Tags(dba.Tags), } From 48534cdf90e259626dafc30dbc54d59891c51b1a Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Mon, 15 May 2023 13:45:01 -0300 Subject: [PATCH 006/115] fix(orb-ui): #772 fix the payload format for sink put request (#2373) --- ui/src/app/pages/sinks/view/sink.view.component.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ui/src/app/pages/sinks/view/sink.view.component.ts b/ui/src/app/pages/sinks/view/sink.view.component.ts index b5201a5ca..30c51e048 100644 --- a/ui/src/app/pages/sinks/view/sink.view.component.ts +++ b/ui/src/app/pages/sinks/view/sink.view.component.ts @@ -83,17 +83,19 @@ export class SinkViewComponent implements OnInit, OnChanges, OnDestroy { const sinkDetails = this.detailsComponent.formGroup?.value; const tags = this.detailsComponent.selectedTags; - const config = this.configComponent.code; + const configSink = this.configComponent.code; - const detailsPartial = (!!this.editMode.details && { ...sinkDetails, id, backend}) - || { name, description, id, backend }; + const detailsPartial = { ...sinkDetails, id, backend}; - let configPartial = (!!this.editMode.config && JSON.parse(config)) || {}; + let configPartial = JSON.parse(configSink); + const config = { + ...configPartial + } const payload = { - ...configPartial, ...detailsPartial, tags, + config, } as Sink; From c0b4d0afcc53ef4271ad008b64a6246ce232c64c Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Mon, 15 May 2023 13:45:25 -0300 Subject: [PATCH 007/115] fix(orb-ui): edit sink through policy view (#2368) --- .../pages/sinks/details/sink.details.component.html | 2 +- .../app/pages/sinks/details/sink.details.component.ts | 8 +++++++- ui/src/app/pages/sinks/view/sink.view.component.scss | 9 +++++++++ .../orb/sink/sink-config/sink-config.component.scss | 3 +++ .../orb/sink/sink-details/sink-details.component.html | 2 +- .../orb/sink/sink-details/sink-details.component.scss | 10 ++++++---- 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/ui/src/app/pages/sinks/details/sink.details.component.html b/ui/src/app/pages/sinks/details/sink.details.component.html index 84d206594..ffc5fbc51 100644 --- a/ui/src/app/pages/sinks/details/sink.details.component.html +++ b/ui/src/app/pages/sinks/details/sink.details.component.html @@ -60,6 +60,6 @@ - + diff --git a/ui/src/app/pages/sinks/details/sink.details.component.ts b/ui/src/app/pages/sinks/details/sink.details.component.ts index e30321a88..0efef925b 100644 --- a/ui/src/app/pages/sinks/details/sink.details.component.ts +++ b/ui/src/app/pages/sinks/details/sink.details.component.ts @@ -25,10 +25,16 @@ export class SinkDetailsComponent { } onOpenEdit(sink: any) { - this.dialogRef.close(true); + this.router.navigateByUrl(`/pages/sinks/edit/${sink.id}`); + this.dialogRef.close(); } onClose() { this.dialogRef.close(false); } + + onOpenView(sink: any) { + this.router.navigateByUrl(`/pages/sinks/view/${sink.id}`); + this.dialogRef.close(); + } } diff --git a/ui/src/app/pages/sinks/view/sink.view.component.scss b/ui/src/app/pages/sinks/view/sink.view.component.scss index a02108a74..c4c2f0351 100644 --- a/ui/src/app/pages/sinks/view/sink.view.component.scss +++ b/ui/src/app/pages/sinks/view/sink.view.component.scss @@ -70,3 +70,12 @@ ngx-sink-config { header { justify-content: space-between; } + +h4 { + font-family: 'Montserrat', sans-serif; + font-size: 1.5rem; + font-style: normal; + font-weight: normal; + line-height: 2rem; + margin-bottom: 1.5rem; +} \ No newline at end of file diff --git a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss index 0639c95f1..b196ebf08 100644 --- a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss +++ b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss @@ -1,3 +1,6 @@ ngx-monaco-editor { height: 25rem; +} +.summary-accent { + color: #969fb9 !important; } \ No newline at end of file diff --git a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html index 7487106ca..be536d091 100644 --- a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html +++ b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html @@ -27,7 +27,7 @@
- +

{{ sink?.name }}

diff --git a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss index 524faceb8..ca81be6c6 100644 --- a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss +++ b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss @@ -1,5 +1,7 @@ .required { - color: #df316f; - padding-left: 2px; - } - \ No newline at end of file + color: #df316f; + padding-left: 2px; +} +.summary-accent { + color: #969fb9 !important; +} \ No newline at end of file From d5bbabfec136d39534347e04ff178e1aab82bf24 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Mon, 15 May 2023 13:45:50 -0300 Subject: [PATCH 008/115] fix(orb-ui): Agent View, dataset details modal reloading information in the page after being closed (#2370) --- .../agent-policies-datasets.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts index 67f699c4b..f665c0970 100644 --- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts +++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts @@ -15,7 +15,7 @@ import { AgentPolicyStates, } from 'app/common/interfaces/orb/agent.policy.interface'; import { Dataset } from 'app/common/interfaces/orb/dataset.policy.interface'; -import { DatasetFromComponent } from 'app/pages/datasets/dataset-from/dataset-from.component'; +import { DatasetFromComponent, DATASET_RESPONSE } from 'app/pages/datasets/dataset-from/dataset-from.component'; @Component({ selector: 'ngx-agent-policies-datasets', @@ -113,7 +113,7 @@ export class AgentPoliciesDatasetsComponent implements OnInit, OnChanges { closeOnBackdropClick: true, }) .onClose.subscribe((resp) => { - if (resp === 'changed' || 'deleted') { + if (resp === DATASET_RESPONSE.EDITED) { this.refreshAgent.emit('refresh-from-dataset'); } }); From e92e3bf2de1129d1122096e7fee4be71734cde27 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 16 May 2023 10:06:08 -0300 Subject: [PATCH 009/115] fix producer payload size (#2376) fix producer payload size (#2376) --- sinker/otel/kafkafanoutexporter/factory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sinker/otel/kafkafanoutexporter/factory.go b/sinker/otel/kafkafanoutexporter/factory.go index 88801aa24..70a4a0e00 100644 --- a/sinker/otel/kafkafanoutexporter/factory.go +++ b/sinker/otel/kafkafanoutexporter/factory.go @@ -41,7 +41,7 @@ const ( // default from sarama.NewConfig() defaultMetadataFull = true // default max.message.bytes for the producer - defaultProducerMaxMessageBytes = 1000000 + defaultProducerMaxMessageBytes = 10000000 // default required_acks for the producer defaultProducerRequiredAcks = sarama.WaitForLocal // default from sarama.NewConfig() From f310ec0163f531f2591225498982d6bda83b4300 Mon Sep 17 00:00:00 2001 From: Eder Matumoto Date: Tue, 16 May 2023 14:05:14 -0300 Subject: [PATCH 010/115] Adding make goal to compile orb with delve (#2377) * added dlv support when building --- Makefile | 17 +++++++++++++++++ docker/Dockerfile.debug | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docker/Dockerfile.debug diff --git a/Makefile b/Makefile index ca36f38ab..4b933bcec 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,20 @@ define make_docker -f docker/Dockerfile . $(eval SERVICE="") endef +define make_docker_debug + $(eval SERVICE=$(shell [ -z "$(SERVICE)" ] && echo $(subst docker_,,$(1)) || echo $(SERVICE))) + docker build \ + --no-cache \ + --build-arg SVC=$(SERVICE) \ + --build-arg GOARCH=$(GOARCH) \ + --build-arg GOARM=$(GOARM) \ + --tag=$(ORB_DOCKERHUB_REPO)/$(DOCKER_IMAGE_NAME_PREFIX)-$(SERVICE):$(REF_TAG) \ + --tag=$(ORB_DOCKERHUB_REPO)/$(DOCKER_IMAGE_NAME_PREFIX)-$(SERVICE):$(ORB_VERSION) \ + --tag=$(ORB_DOCKERHUB_REPO)/$(DOCKER_IMAGE_NAME_PREFIX)-$(SERVICE):$(ORB_VERSION)-$(COMMIT_HASH) \ + -f docker/Dockerfile.debug . + $(eval SERVICE="") +endef + define make_docker_dev $(eval svc=$(shell [ -z "$(SERVICE)" ] && echo $(subst docker_dev_,,$(1)) || echo $(svc))) docker build \ @@ -122,6 +136,9 @@ dockers_dev: $(DOCKERS_DEV) build_docker: $(call make_docker,$(@),$(GOARCH)) +build_docker_debug: + $(call make_docker_debug,$(@),$(GOARCH)) + # install tools for kind install-kind: diff --git a/docker/Dockerfile.debug b/docker/Dockerfile.debug new file mode 100644 index 000000000..fa0504598 --- /dev/null +++ b/docker/Dockerfile.debug @@ -0,0 +1,22 @@ +FROM golang:1.19-alpine AS builder +ARG SVC +ARG GOARCH +ARG GOARM + +WORKDIR /go/src/github.com/orbcommunity/orb +COPY . . +RUN apk update \ + && apk add make +RUN make $SVC \ + && mv build/orb-$SVC /exe +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +FROM alpine:latest +ARG SVC + +RUN if [[ "maestro" == "$SVC" ]]; then apk update && apk add --no-cache docker-cli bash curl && curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl && chmod +x ./kubectl && mv ./kubectl /usr/local/bin/kubectl; fi +# Certificates are needed so that mailing util can work. +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=builder /exe / +COPY --from=builder /go/bin/dlv /dlv +CMD ["/dlv", "--listen=:2345", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "/exe"] From 38d75841c0f10dbaecd9f9e8e4761e5822d4e27f Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Fri, 19 May 2023 17:41:22 -0300 Subject: [PATCH 011/115] feat(orb-ui): #777 New page for sink creation (#2378) --- ui/src/app/pages/pages-routing.module.ts | 2 +- ui/src/app/pages/pages.module.ts | 2 +- .../pages/sinks/add/sink-add.component.html | 39 +++ .../pages/sinks/add/sink-add.component.scss | 51 +++ .../app/pages/sinks/add/sink-add.component.ts | 72 ++++ .../pages/sinks/add/sink.add.component.html | 317 ------------------ .../pages/sinks/add/sink.add.component.scss | 119 ------- .../app/pages/sinks/add/sink.add.component.ts | 175 ---------- .../pages/sinks/list/sink.list.component.html | 2 +- .../sink-config/sink-config.component.html | 4 +- .../sink/sink-config/sink-config.component.ts | 19 +- .../sink-details/sink-details.component.html | 206 ++++++++---- .../sink-details/sink-details.component.scss | 8 + .../sink-details/sink-details.component.ts | 60 +++- ui/src/assets/text/strings.ts | 2 +- 15 files changed, 389 insertions(+), 689 deletions(-) create mode 100644 ui/src/app/pages/sinks/add/sink-add.component.html create mode 100644 ui/src/app/pages/sinks/add/sink-add.component.scss create mode 100644 ui/src/app/pages/sinks/add/sink-add.component.ts delete mode 100644 ui/src/app/pages/sinks/add/sink.add.component.html delete mode 100644 ui/src/app/pages/sinks/add/sink.add.component.scss delete mode 100644 ui/src/app/pages/sinks/add/sink.add.component.ts diff --git a/ui/src/app/pages/pages-routing.module.ts b/ui/src/app/pages/pages-routing.module.ts index 96ba9881b..27830bf10 100644 --- a/ui/src/app/pages/pages-routing.module.ts +++ b/ui/src/app/pages/pages-routing.module.ts @@ -11,7 +11,7 @@ import { AgentPolicyListComponent } from 'app/pages/datasets/policies.agent/list import { DatasetListComponent } from 'app/pages/datasets/list/dataset.list.component'; // Sink Management import { SinkListComponent } from 'app/pages/sinks/list/sink.list.component'; -import { SinkAddComponent } from 'app/pages/sinks/add/sink.add.component'; +import { SinkAddComponent } from 'app/pages/sinks/add/sink-add.component'; // Fleet Management import { AgentListComponent } from 'app/pages/fleet/agents/list/agent.list.component'; import { AgentAddComponent } from 'app/pages/fleet/agents/add/agent.add.component'; diff --git a/ui/src/app/pages/pages.module.ts b/ui/src/app/pages/pages.module.ts index 62904cb14..2685d1fe4 100644 --- a/ui/src/app/pages/pages.module.ts +++ b/ui/src/app/pages/pages.module.ts @@ -50,7 +50,7 @@ import { AgentGroupDeleteComponent } from 'app/pages/fleet/groups/delete/agent.g import { AgentGroupDetailsComponent } from 'app/pages/fleet/groups/details/agent.group.details.component'; import { AgentGroupListComponent } from 'app/pages/fleet/groups/list/agent.group.list.component'; import { ShowcaseComponent } from 'app/pages/showcase/showcase.component'; -import { SinkAddComponent } from 'app/pages/sinks/add/sink.add.component'; +import { SinkAddComponent } from 'app/pages/sinks/add/sink-add.component'; import { SinkDeleteComponent } from 'app/pages/sinks/delete/sink.delete.component'; import { SinkDetailsComponent } from 'app/pages/sinks/details/sink.details.component'; diff --git a/ui/src/app/pages/sinks/add/sink-add.component.html b/ui/src/app/pages/sinks/add/sink-add.component.html new file mode 100644 index 000000000..3e4cfce56 --- /dev/null +++ b/ui/src/app/pages/sinks/add/sink-add.component.html @@ -0,0 +1,39 @@ +
+
+ + + {{ + breadcrumb + }} + + +

{{ strings.sink.add.header }}

+
+
+ + +
+ +
+
+ + + + +
\ No newline at end of file diff --git a/ui/src/app/pages/sinks/add/sink-add.component.scss b/ui/src/app/pages/sinks/add/sink-add.component.scss new file mode 100644 index 000000000..ec2990d69 --- /dev/null +++ b/ui/src/app/pages/sinks/add/sink-add.component.scss @@ -0,0 +1,51 @@ + +button { + margin: 0 3px; + float: right; + color: #fff !important; + font-family: "Montserrat", sans-serif; + font-weight: 500; + text-transform: none !important; +} +.sink-create { + &.btn-disabled { + background: #2b3148; + } + + &:not(.btn-disabled) { + background-color: #3089fc !important; + } +} + +.sink-cancel { + background-color: #3089fc !important; +} + ngx-sink-details { + flex: 0 1 22rem; + } + + ngx-sink-config { + flex: 2 1 auto; + min-height: 30rem !important; + + nb-card { + height: 30rem !important; + } + } + + .row { + gap: 1rem; + } + + header { + justify-content: space-between; + } + + h4 { + font-family: 'Montserrat', sans-serif; + font-size: 1.5rem; + font-style: normal; + font-weight: normal; + line-height: 2rem; + margin-bottom: 1.5rem; + } \ No newline at end of file diff --git a/ui/src/app/pages/sinks/add/sink-add.component.ts b/ui/src/app/pages/sinks/add/sink-add.component.ts new file mode 100644 index 000000000..8a47f0cac --- /dev/null +++ b/ui/src/app/pages/sinks/add/sink-add.component.ts @@ -0,0 +1,72 @@ +import { Component, ViewChild } from '@angular/core'; +import { Router } from '@angular/router'; +import { Sink } from 'app/common/interfaces/orb/sink.interface'; +import { NotificationsService } from 'app/common/services/notifications/notifications.service'; +import { SinksService } from 'app/common/services/sinks/sinks.service'; +import { SinkConfigComponent } from 'app/shared/components/orb/sink/sink-config/sink-config.component'; +import { SinkDetailsComponent } from 'app/shared/components/orb/sink/sink-details/sink-details.component'; +import { STRINGS } from 'assets/text/strings'; + + +@Component({ + selector: 'ngx-sink-add-component', + templateUrl: './sink-add.component.html', + styleUrls: ['./sink-add.component.scss'], +}) + +export class SinkAddComponent { + + @ViewChild(SinkDetailsComponent) detailsComponent: SinkDetailsComponent; + + @ViewChild(SinkConfigComponent) configComponent: SinkConfigComponent; + + strings = STRINGS; + + createMode: boolean; + + constructor( + private sinksService: SinksService, + private notificationsService: NotificationsService, + private router: Router, + ) { + this.createMode = true; + } + + canCreate() { + const detailsValid = this.createMode + ? this.detailsComponent?.formGroup?.status === 'VALID' + : true; + return detailsValid; + } + + createSink() { + + const sinkDetails = this.detailsComponent.formGroup?.value; + const tags = this.detailsComponent.selectedTags; + const configSink = this.configComponent.code; + + const details = { ...sinkDetails}; + + let configs = JSON.parse(configSink); + + const config = { + ...configs + } + + const payload = { + ...details, + tags, + config, + + } as Sink; + + this.sinksService.addSink(payload).subscribe(() => { + this.notificationsService.success('Sink successfully created', ''); + this.goBack(); + }); + } + + goBack() { + this.router.navigateByUrl('/pages/sinks'); + } +} \ No newline at end of file diff --git a/ui/src/app/pages/sinks/add/sink.add.component.html b/ui/src/app/pages/sinks/add/sink.add.component.html deleted file mode 100644 index dc592e627..000000000 --- a/ui/src/app/pages/sinks/add/sink.add.component.html +++ /dev/null @@ -1,317 +0,0 @@ -
-
- - - {{ breadcrumb }} - - -

{{strings.sink[isEdit ? 'edit' : 'add']['header']}}

-
-
-
- - - -
- Sink Details -

Provide a name and description for the Sink

-
-
-
- -
-
- - * -
- - -
- Name is required. -
-
- Name must start with a letter or "_" and contain only letters, numbers, "-" or "_" -
-
- Name must be less than {{firstFormGroup.controls.name.errors?.maxlength.requiredLength}} characters -
-
-
-
-
- -
- -
- - -
- Description must be less than {{firstFormGroup.controls.description.errors?.maxlength.requiredLength}} characters -
-
-
-
- -
- - * -
- - {{ type | titlecase }} - -
-
-
- - -
-
-
- - -
- Sink Destination -

Configure your Sink settings

-
-
-
- - - * - - - - - {{ type }} - - - -
- - - -
-
-
- - -
- Sink Tags -

Enter tags for this Sink

-
-
-
- - -
- -
- - - -
-
-
- - -
- Review & Confirm -
-
-
-
-
- -

{{firstFormGroup?.controls.name.value}}

-
-
-
-
- -

{{firstFormGroup?.controls.description.value}}

-
-
-
-
- -

{{firstFormGroup?.controls.backend.value}}

-
-
-
-
-
-
-
- -

{{secondFormGroup.controls[control.prop].value}}

-

*******

-
-
-
-
-
-
- - -
-
-
- - - -
-
-
-
-
-
diff --git a/ui/src/app/pages/sinks/add/sink.add.component.scss b/ui/src/app/pages/sinks/add/sink.add.component.scss deleted file mode 100644 index ffb2a7c35..000000000 --- a/ui/src/app/pages/sinks/add/sink.add.component.scss +++ /dev/null @@ -1,119 +0,0 @@ -nb-card { - width: 400px; -} - -button { - margin: 10px; -} - -textarea { - width: 100%; - height: 100%; -} - -nb-card-footer { - text-align: center; -} - -mat-chip nb-icon { - font-size: 1rem; -} - -::ng-deep { - .header { - align-items: flex-end !important; - margin-right: 10px !important; - height: calc(100vh - 337px) !important; - } - - .label-index { - background-color: #969fb9; - transition: box-shadow 0.3s 0s ease-in-out; - color: #969fb9; - border: none !important; - //box-shadow: 0 0 8px -2px #ffffff; - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTEiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDExIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0wLjUgMy45OTY1MUw0LjE4NjgyIDcuNjgzMzNMMTAuODIzMSAxLjA0NzA2TDkuNzgzNDEgMEw0LjE4NjgyIDUuNTk2NTlMMS41Mzk2OCAyLjk1NjgzTDAuNSAzLjk5NjUxWiIgZmlsbD0iIzE1MWEzMCIvPgo8L3N2Zz4K'); - background-size: 20px 14px; - background-repeat: no-repeat; - background-position: center; - //background-blend-mode: exclusion; - z-index: 3; - :first-child { - visibility: hidden; - } - } - - .step { - flex-direction: row-reverse !important; - align-items: start !important; - } - - .step.selected { - -webkit-text-stroke-color: rgba(255, 255, 255, 0.15); - -webkit-text-stroke-width: 1px; - text-shadow: 0 0 20px #ffffff8f; - - & > .label-index { - box-shadow: 0 0 12px 1px #df316f; - background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTEiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDExIDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0wLjUgMy45OTY1MUw0LjE4NjgyIDcuNjgzMzNMMTAuODIzMSAxLjA0NzA2TDkuNzgzNDEgMEw0LjE4NjgyIDUuNTk2NTlMMS41Mzk2OCAyLjk1NjgzTDAuNSAzLjk5NjUxWiIgZmlsbD0iI2ZmZiIvPgo8L3N2Zz4K'); - background-color: #df316f; - } - } - - .step-content { - width: 500px !important; - } - - .connector { - width: 1px !important; - transform: translateX(1px); - - &::after { - content: ''; - height: 40px; - transform: translateY(-40px); - width: 1px; - border-left: solid 1px #969fb9b3; - position: absolute; - z-index: 1; - } - } - - .connector.connector-past { - transition: background 0.5s 0s ease-in-out; - &::after { - transition: border 0.5s 0s ease-in-out; - border-left: solid 1px #df316f; - } - } -} - -.required { - color: #df316f; - padding-left: 2px; -} - -.step-label { - width: 214px; - text-align: end; -} - -::ng-deep .orb-breadcrumb { - align-items: center; - - display: flex; - - font-family: 'Montserrat', sans-serif; - font-style: normal; - font-weight: 500; - font-size: 12px; - line-height: 12px; - - ::ng-deep .xng-breadcrumb-trail { - color: #ffffff !important; - - &::before { - color: #969fb9 !important; - } - } -} diff --git a/ui/src/app/pages/sinks/add/sink.add.component.ts b/ui/src/app/pages/sinks/add/sink.add.component.ts deleted file mode 100644 index 985302196..000000000 --- a/ui/src/app/pages/sinks/add/sink.add.component.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { Component } from '@angular/core'; - -import { NotificationsService } from 'app/common/services/notifications/notifications.service'; -import { SinksService } from 'app/common/services/sinks/sinks.service'; -import { ActivatedRoute, Router } from '@angular/router'; -import { Sink } from 'app/common/interfaces/orb/sink.interface'; -import { STRINGS } from 'assets/text/strings'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { SinkConfig } from 'app/common/interfaces/orb/sink/sink.config.interface'; -import { SinkFeature } from 'app/common/interfaces/orb/sink/sink.feature.interface'; - -@Component({ - selector: 'ngx-sink-add-component', - templateUrl: './sink.add.component.html', - styleUrls: ['./sink.add.component.scss'], -}) -export class SinkAddComponent { - strings = STRINGS; - - // stepper vars - firstFormGroup: FormGroup; - - secondFormGroup: FormGroup; - - customSinkSettings: {}; - - selectedSinkSetting: any[]; - - selectedTags: { [propName: string]: string }; - - sink: Sink; - - sinkID: string; - - sinkTypesList = []; - - isEdit: boolean; - - isLoading = false; - - constructor( - private sinksService: SinksService, - private notificationsService: NotificationsService, - private router: Router, - private route: ActivatedRoute, - private _formBuilder: FormBuilder, - ) { - this.isLoading = true; - this.sinkID = this.route.snapshot.paramMap.get('id'); - this.isEdit = this.router.getCurrentNavigation().extras.state?.edit as boolean || !!this.sinkID; - - Promise.all([this.getSink(), this.getSinkBackends()]).then((responses) => { - const { backend } = this.sink = responses[0]; - const backends = responses[1]; - - this.sinkTypesList = backends.map(entry => entry.backend); - this.customSinkSettings = this.sinkTypesList.reduce((accumulator, curr) => { - const index = backends.findIndex(entry => entry.backend === curr); - accumulator[curr] = backends[index].config.map(entry => ({ - type: entry.type, - label: entry.title, - prop: entry.name, - input: entry.input, - required: entry.required, - })); - return accumulator; - }, {}); - - this.initializeForms(); - - if (backend !== '') this.onSinkTypeSelected(backend); - this.isLoading = false; - }).catch(reason => console.warn(`Couldn't retrieve data. Reason: ${ reason }`)); - } - - newSink() { - return { - name: '', - description: '', - backend: 'prometheus', // default sink - tags: {}, - } as Sink; - } - - initializeForms() { - const { name, description, backend, tags } = this.sink; - - this.firstFormGroup = this._formBuilder.group({ - name: [name, [Validators.required, Validators.pattern('^[a-zA-Z_][a-zA-Z0-9_-]*$'), Validators.maxLength(64)]], - description: [description, [Validators.maxLength(64)]], - backend: [backend, Validators.required], - }); - - this.selectedTags = { ...tags }; - } - - getSink() { - return new Promise(resolve => { - if (this.sinkID) { - this.sinksService.getSinkById(this.sinkID).subscribe(resp => { - resolve(resp); - }); - } else { - resolve(this.newSink()); - } - }); - } - - getSinkBackends() { - return new Promise(resolve => { - this.sinksService.getSinkBackends().subscribe(backends => { - resolve(backends); - }); - }); - } - - goBack() { - this.router.navigateByUrl('/pages/sinks'); - } - - onFormSubmit() { - const payload = { - name: this.firstFormGroup.controls.name.value, - backend: this.firstFormGroup.controls.backend.value, - description: this.firstFormGroup.controls.description.value, - config: this.selectedSinkSetting.reduce((accumulator, current) => { - const value = this.secondFormGroup.controls[current.prop].value; - if (current.input === 'checkbox') { - if (value) - accumulator[current.prop] = 'enabled'; - } else { - accumulator[current.prop] = value; - } - return accumulator; - }, {}), - tags: { ...this.selectedTags }, - }; - - if (this.isEdit) { - // updating existing sink - this.sinksService.editSink({ ...payload, id: this.sinkID }).subscribe(() => { - this.notificationsService.success('Sink successfully updated', ''); - this.goBack(); - }); - } else { - this.sinksService.addSink(payload).subscribe(() => { - this.notificationsService.success('Sink successfully created', ''); - this.goBack(); - }); - } - - } - - onSinkTypeSelected(selectedValue) { - // SinkConfig being the generic of all other `sinkTypes`. - const conf = !!this.sink && - this.isEdit && - (selectedValue === this.sink.backend) && - this.sink?.config && - this.sink.config as SinkConfig || null; - - this.selectedSinkSetting = this.customSinkSettings[selectedValue]; - - const dynamicFormControls = this.selectedSinkSetting.reduce((accumulator, curr) => { - accumulator[curr.prop] = [ - !!conf && (curr.prop in conf) && conf[curr.prop] || - '', - curr.required ? Validators.required : null, - ]; - return accumulator; - }, {}); - - this.secondFormGroup = this._formBuilder.group(dynamicFormControls); - } -} diff --git a/ui/src/app/pages/sinks/list/sink.list.component.html b/ui/src/app/pages/sinks/list/sink.list.component.html index 3bdddacdf..c31321d25 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.html +++ b/ui/src/app/pages/sinks/list/sink.list.component.html @@ -95,7 +95,7 @@

{{ strings.list.header }}

+ + + + + {{ value | titlecase }} + + \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss index f68c359ec..a67f98dcb 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss @@ -187,3 +187,11 @@ mat-chip-list { animation-direction: alternate; } } +.orb-service-{ + &in { + color: #6fcf97; + } + ¬ { + color: #f2994a; + } +} diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index 5d5d5b1b1..47144d72a 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -15,11 +15,12 @@ import { DatatableComponent, TableColumn, } from '@swimlane/ngx-datatable'; -import { AgentPolicy } from 'app/common/interfaces/orb/agent.policy.interface'; +import { AgentPolicy, AgentPolicyUsage } from 'app/common/interfaces/orb/agent.policy.interface'; import { filterNumber, FilterOption, filterString, filterTags, FilterTypes, + filterMultiSelect, } from 'app/common/interfaces/orb/filter-option'; import { AgentPoliciesService } from 'app/common/services/agents/agent.policies.service'; import { FilterService } from 'app/common/services/filter.service'; @@ -27,8 +28,10 @@ import { NotificationsService } from 'app/common/services/notifications/notifica import { OrbService } from 'app/common/services/orb.service'; import { AgentPolicyDeleteComponent } from 'app/pages/datasets/policies.agent/delete/agent.policy.delete.component'; import { Observable } from 'rxjs'; +import { map, withLatestFrom } from 'rxjs/operators'; import { STRINGS } from '../../../../../assets/text/strings'; + @Component({ selector: 'ngx-agent-policy-list-component', templateUrl: './agent.policy.list.component.html', @@ -50,6 +53,8 @@ export class AgentPolicyListComponent @ViewChild('actionsTemplateCell') actionsTemplateCell: TemplateRef; + @ViewChild('usageStateTemplateCell') usageStateTemplateCell: TemplateRef; + tableSorts = [ { prop: 'name', @@ -81,9 +86,18 @@ export class AgentPolicyListComponent private orb: OrbService, private filters: FilterService, ) { - this.policies$ = this.orb.getPolicyListView(); this.filters$ = this.filters.getFilters(); + this.policies$ = this.orb.getPolicyListView().pipe( + withLatestFrom(this.orb.getDatasetListView()), + map(([policies, datasets]) => { + return policies.map((policy) => { + const dataset = datasets.filter((d) => d.valid && d.agent_policy_id === policy.id); + return { ...policy, policy_usage: dataset.length > 0 ? AgentPolicyUsage.inUse : AgentPolicyUsage.notInUse }; + }) + } + )); + this.filterOptions = [ { name: 'Name', @@ -109,6 +123,13 @@ export class AgentPolicyListComponent filter: filterString, type: FilterTypes.Input, }, + { + name: 'Usage', + prop: 'policy_usage', + filter: filterMultiSelect, + type: FilterTypes.MultiSelect, + options: Object.values(AgentPolicyUsage).map((value) => value as string), + }, ]; this.filteredPolicies$ = this.filters.createFilteredList()( @@ -153,6 +174,7 @@ export class AgentPolicyListComponent } ngAfterViewInit() { + this.orb.refreshNow(); this.columns = [ { @@ -160,10 +182,19 @@ export class AgentPolicyListComponent name: 'Policy Name', resizeable: false, canAutoResize: true, - flexGrow: 2, + flexGrow: 1.5, minWidth: 100, cellTemplate: this.nameTemplateCell, }, + { + prop: 'policy_usage', + name: 'Usage', + resizeable: false, + canAutoResize: true, + flexGrow: 1, + minWidth: 100, + cellTemplate: this.usageStateTemplateCell, + }, { prop: 'description', name: 'Description', From e3aa437eb7d6a49fb12e1c539e7a0f4fccef8f19 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Thu, 1 Jun 2023 16:49:55 -0300 Subject: [PATCH 026/115] fix(sinks): fix receiveing parameter as json or yaml. (#2396) * fix(sinks): fix receiveing parameter as json or yaml. * fix(sinks): fix unit tests. --- sinks/api/http/endpoint.go | 4 ++-- sinks/api/http/endpoint_test.go | 8 ++++---- sinks/api/http/requests.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index 50c5ffd7b..d00d44027 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -28,7 +28,7 @@ func omitSecretInformation(configSvc *sinks.Configuration, inputSink sinks.Sink) returnSink = inputSink authMeta := a.(types.Metadata) returnSink.Config = authMeta - if inputSink.Format != "" { + if inputSink.Format == "yaml" { configData, newErr := configSvc.Authentication.ConfigToFormat(inputSink.Format, authMeta) if newErr != nil { err = newErr @@ -177,7 +177,7 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { nameID, err := types.NewIdentifier(req.Name) if err != nil { svc.GetLogger().Error("error on getting new identifier", zap.Error(err)) - return nil, errors.ErrMalformedEntity + return nil, errors.ErrConflict } sink.Name = nameID } diff --git a/sinks/api/http/endpoint_test.go b/sinks/api/http/endpoint_test.go index 4ad9b0f46..8fe630357 100644 --- a/sinks/api/http/endpoint_test.go +++ b/sinks/api/http/endpoint_test.go @@ -329,7 +329,7 @@ func TestCreateSinks(t *testing.T) { req: invalidNameJson, contentType: contentType, auth: token, - status: http.StatusBadRequest, + status: http.StatusConflict, location: "/sinks", }, "add a sink with empty name": { @@ -584,21 +584,21 @@ func TestUpdateSink(t *testing.T) { id: sk.ID, contentType: contentType, auth: token, - status: http.StatusBadRequest, + status: http.StatusConflict, }, "update existing sink with a invalid regex name": { req: dataInvalidRgxName, id: sk.ID, contentType: contentType, auth: token, - status: http.StatusBadRequest, + status: http.StatusConflict, }, "update existing sink with a config without authentication": { req: dataInvalidRgxName, id: sk.ID, contentType: contentType, auth: token, - status: http.StatusBadRequest, + status: http.StatusConflict, }, "update existing sink with a config without exporter": { req: dataNoExporterConfig, diff --git a/sinks/api/http/requests.go b/sinks/api/http/requests.go index 43547901e..0bf432b03 100644 --- a/sinks/api/http/requests.go +++ b/sinks/api/http/requests.go @@ -126,7 +126,7 @@ func (req addReq) validate() (err error) { _, err = types.NewIdentifier(req.Name) if err != nil { - return errors.Wrap(errors.ErrMalformedEntity, errors.New("identifier duplicated")) + return errors.Wrap(errors.ErrConflict, errors.New("identifier duplicated")) } return nil } From bade19cf8d631ca445c8c628d2e478490e3dfb36 Mon Sep 17 00:00:00 2001 From: Guilhermo Pazuch <1490938+gpazuch@users.noreply.github.com> Date: Thu, 1 Jun 2023 17:16:30 -0300 Subject: [PATCH 027/115] chore(readme): fix typo 'principals' -> 'principles' (#2395) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f442e6353..89f2b12d4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ with more analyzers in the works. ## Realtime Agent Orchestration -Orb uses IoT principals to allow the observability agents to connect out to the Orb central control plane, avoiding +Orb uses IoT principles to allow the observability agents to connect out to the Orb central control plane, avoiding firewall problems. Once connected, agents are controlled in real time from the Orb Portal or REST API, orchestrating observability [policies](https://orb.community/about/#policies) designed to precisely extract the desired insights. Agents are grouped and addressed based on [tags](https://orb.community/about/#agent-group). From 842f88aeaa70bc9e5ed4b5d888ce43a15a079181 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Fri, 2 Jun 2023 12:05:58 -0300 Subject: [PATCH 028/115] feat(orb-ui): Orb ui support for Otlp Sinks (#2397) * v1-otlp-ui * feat(orb-ui): Otlp Ui, final adjustments --- .../common/interfaces/orb/sink.interface.ts | 11 ++--- .../orb/sink/config/otlp.config.interface.ts | 35 +++++++++++++++ .../pages/sinks/add/sink-add.component.html | 7 ++- .../app/pages/sinks/add/sink-add.component.ts | 10 ++++- .../pages/sinks/view/sink.view.component.ts | 38 ++++++++++------ .../sink/sink-config/sink-config.component.ts | 43 ++++++++++++++++--- .../sink-details/sink-details.component.html | 1 + .../sink-details/sink-details.component.ts | 14 +++++- 8 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 ui/src/app/common/interfaces/orb/sink/config/otlp.config.interface.ts diff --git a/ui/src/app/common/interfaces/orb/sink.interface.ts b/ui/src/app/common/interfaces/orb/sink.interface.ts index 4f1b78c3e..21b7adf93 100644 --- a/ui/src/app/common/interfaces/orb/sink.interface.ts +++ b/ui/src/app/common/interfaces/orb/sink.interface.ts @@ -4,9 +4,9 @@ * [Sinks Architecture]{@link https://github.com/orb-community/orb/wiki/Architecture:-Sinks} */ -import { PrometheusConfig } from 'app/common/interfaces/orb/sink/config/prometheus.config.interface'; import { OrbEntity } from 'app/common/interfaces/orb/orb.entity.interface'; +import { OtlpConfig } from './sink/config/otlp.config.interface'; /** * @enum SinkStates @@ -23,6 +23,7 @@ export enum SinkStates { */ export enum SinkBackends { prometheus = 'prometheus', + otlp = 'otlphttp' } /** @@ -69,16 +70,16 @@ export interface Sink extends OrbEntity { config?: SinkTypes; } -export type SinkTypes = PrometheusConfig; +export type SinkTypes = OtlpConfig; /** * Prometheus Sink Type - * @type PromSink + * @type OtlpSink */ -export type PromSink = +export type OtlpSink = | Sink | { - config?: PrometheusConfig; + config?: OtlpConfig; }; /** diff --git a/ui/src/app/common/interfaces/orb/sink/config/otlp.config.interface.ts b/ui/src/app/common/interfaces/orb/sink/config/otlp.config.interface.ts new file mode 100644 index 000000000..4d191fce6 --- /dev/null +++ b/ui/src/app/common/interfaces/orb/sink/config/otlp.config.interface.ts @@ -0,0 +1,35 @@ +/** + * Oltp Sink Config Interface + * [Sinks Architecture]{@link https://github.com/orb-community/orb/wiki/Architecture:-Sinks} + */ +import { SinkConfig } from 'app/common/interfaces/orb/sink/sink.config.interface'; + +/** + * @interface OtlpConfig + */ +export interface OtlpConfig extends SinkConfig { + name: 'Otlp'; + + authentication: |any| { + /** + * Authentication type, "type": "basicauth" Default, can be ommitted + */ + type?: string; + /** + * Password {string} + */ + password?: string; + /** + * Username|Email(?) {string} + */ + username?: string; + } + exporter: |any| { + /** + * Endpoint (Otlp sinks) or Remote Host (Prometheus sink) Link {string} + */ + endpoint?: string; + remote_host?: string; + } + +} \ No newline at end of file diff --git a/ui/src/app/pages/sinks/add/sink-add.component.html b/ui/src/app/pages/sinks/add/sink-add.component.html index 3e4cfce56..87fbd67e5 100644 --- a/ui/src/app/pages/sinks/add/sink-add.component.html +++ b/ui/src/app/pages/sinks/add/sink-add.component.html @@ -32,8 +32,11 @@

{{ strings.sink.add.header }}

- + - +
\ No newline at end of file diff --git a/ui/src/app/pages/sinks/add/sink-add.component.ts b/ui/src/app/pages/sinks/add/sink-add.component.ts index 8a47f0cac..3e487c0a9 100644 --- a/ui/src/app/pages/sinks/add/sink-add.component.ts +++ b/ui/src/app/pages/sinks/add/sink-add.component.ts @@ -24,6 +24,8 @@ export class SinkAddComponent { createMode: boolean; + sinkBackend: any; + constructor( private sinksService: SinksService, private notificationsService: NotificationsService, @@ -59,7 +61,7 @@ export class SinkAddComponent { config, } as Sink; - + this.sinksService.addSink(payload).subscribe(() => { this.notificationsService.success('Sink successfully created', ''); this.goBack(); @@ -69,4 +71,8 @@ export class SinkAddComponent { goBack() { this.router.navigateByUrl('/pages/sinks'); } -} \ No newline at end of file + + getBackendEmit(backend: any) { + this.sinkBackend = backend; + } +} diff --git a/ui/src/app/pages/sinks/view/sink.view.component.ts b/ui/src/app/pages/sinks/view/sink.view.component.ts index 30c51e048..86e3b6a4c 100644 --- a/ui/src/app/pages/sinks/view/sink.view.component.ts +++ b/ui/src/app/pages/sinks/view/sink.view.component.ts @@ -79,26 +79,40 @@ export class SinkViewComponent implements OnInit, OnChanges, OnDestroy { } save() { - const { name, description, id, backend } = this.sink; + const { id, backend } = this.sink; const sinkDetails = this.detailsComponent.formGroup?.value; const tags = this.detailsComponent.selectedTags; const configSink = this.configComponent.code; - const detailsPartial = { ...sinkDetails, id, backend}; + let payload = {}; + const details = { ...sinkDetails, tags}; + const config = JSON.parse(configSink); - let configPartial = JSON.parse(configSink); - - const config = { - ...configPartial + if (this.editMode.details && !this.editMode.config) { + payload = { + id, + backend, + ...details, + } as Sink; + } + else if (!this.editMode.details && this.editMode.config) { + payload = { + id, + backend, + config, + } as Sink; + } + else { + payload = { + id, + backend, + details, + config, + } as Sink; } - const payload = { - ...detailsPartial, - tags, - config, - - } as Sink; + console.log(payload); try { this.sinks.editSink(payload).subscribe((resp) => { this.discard(); diff --git a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.ts b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.ts index 2964f3e8a..a03960e1b 100644 --- a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.ts +++ b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import { FormBuilder, FormControl, Validators } from '@angular/forms'; -import { Sink } from 'app/common/interfaces/orb/sink.interface'; +import { Sink, SinkBackends } from 'app/common/interfaces/orb/sink.interface'; import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions; @Component({ selector: 'ngx-sink-config', @@ -17,6 +17,9 @@ export class SinkConfigComponent implements OnInit, OnChanges { @Input() createMode: boolean; + + @Input() + sinkBackend: string; @Output() editModeChange: EventEmitter; @@ -48,7 +51,9 @@ export class SinkConfigComponent implements OnInit, OnChanges { code = ''; - sinkConfigSchema: any; + sinkConfigSchemaPrometheus: any; + + sinkConfigSchemaOtlp: any; formControl: FormControl; @@ -57,18 +62,34 @@ export class SinkConfigComponent implements OnInit, OnChanges { this.editMode = false; this.editModeChange = new EventEmitter(); this.updateForm(); - this.sinkConfigSchema = { + this.sinkConfigSchemaPrometheus = { + "authentication" : { + "type": "basicauth", + "password": "", + "username": "", + }, + "exporter" : { + "remote_host": "", + }, + "opentelemetry": "enabled", + } + this.sinkConfigSchemaOtlp = { + "authentication" : { + "type": "basicauth", + "password": "", + "username": "", + }, + "exporter" : { + "endpoint": "", + }, "opentelemetry": "enabled", - "password": "", - "remote_host": "", - "username": "" } } ngOnInit(): void { if (this.createMode) { this.toggleEdit(true); - this.code = JSON.stringify(this.sinkConfigSchema, null, 2); + this.code = JSON.stringify(this.sinkConfigSchemaOtlp, null, 2); } else { this.code = JSON.stringify(this.sink.config, null, 2); @@ -79,6 +100,14 @@ export class SinkConfigComponent implements OnInit, OnChanges { if (changes?.editMode && !changes?.editMode.firstChange) { this.toggleEdit(changes.editMode.currentValue, false); } + if (changes?.sinkBackend) { + if (this.sinkBackend === SinkBackends.prometheus) { + this.code = JSON.stringify(this.sinkConfigSchemaPrometheus, null, 2); + } + else { + this.code = JSON.stringify(this.sinkConfigSchemaOtlp, null, 2); + } + } } updateForm() { diff --git a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html index aa1d2675f..6bebef6e6 100644 --- a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html +++ b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.html @@ -151,6 +151,7 @@ placeholder="Select backend type" size="medium" required + (selectedChange)="onChangeConfigBackend($event)" > {{ type | titlecase }} diff --git a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.ts b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.ts index 3f498f374..3c39fd0f6 100644 --- a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.ts +++ b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.ts @@ -1,9 +1,10 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { Sink, SinkStates } from 'app/common/interfaces/orb/sink.interface'; +import { Sink, SinkBackends, SinkStates } from 'app/common/interfaces/orb/sink.interface'; import { SinkFeature } from 'app/common/interfaces/orb/sink/sink.feature.interface'; import { Tags } from 'app/common/interfaces/orb/tag'; import { SinksService } from 'app/common/services/sinks/sinks.service'; +import { SinkConfigComponent } from '../sink-config/sink-config.component'; @Component({ @@ -13,6 +14,10 @@ import { SinksService } from 'app/common/services/sinks/sinks.service'; }) export class SinkDetailsComponent implements OnInit, OnChanges { + + @Output() + sinkBackend: EventEmitter; + @Input() sink: Sink; @@ -43,6 +48,7 @@ export class SinkDetailsComponent implements OnInit, OnChanges { this.createMode = false; this.editMode = false; this.mode = 'read'; + this.sinkBackend = new EventEmitter(); this.editModeChange = new EventEmitter(); this.updateForm(); Promise.all([this.getSinkBackends()]).then((responses) => { @@ -128,4 +134,8 @@ export class SinkDetailsComponent implements OnInit, OnChanges { }); }); } + + onChangeConfigBackend(backend: any) { + this.sinkBackend.emit(backend); + } } From d3c6453a35567936a567882515d249b5c3a8fa0a Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Tue, 6 Jun 2023 17:54:27 -0300 Subject: [PATCH 029/115] fix(orb-ui): card size improvements sink view (#2398) --- .../app/pages/sinks/add/sink-add.component.html | 17 +++++++++-------- .../app/pages/sinks/add/sink-add.component.scss | 2 +- .../sink/sink-config/sink-config.component.scss | 3 +++ .../sink-details/sink-details.component.scss | 4 ++++ 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ui/src/app/pages/sinks/add/sink-add.component.html b/ui/src/app/pages/sinks/add/sink-add.component.html index 87fbd67e5..4cb00676b 100644 --- a/ui/src/app/pages/sinks/add/sink-add.component.html +++ b/ui/src/app/pages/sinks/add/sink-add.component.html @@ -11,7 +11,14 @@

{{ strings.sink.add.header }}

-
+
+ - +
diff --git a/ui/src/app/pages/sinks/add/sink-add.component.scss b/ui/src/app/pages/sinks/add/sink-add.component.scss index ec2990d69..ca46de6ca 100644 --- a/ui/src/app/pages/sinks/add/sink-add.component.scss +++ b/ui/src/app/pages/sinks/add/sink-add.component.scss @@ -1,7 +1,7 @@ button { margin: 0 3px; - float: right; + float: left; color: #fff !important; font-family: "Montserrat", sans-serif; font-weight: 500; diff --git a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss index b196ebf08..e0bdbc3b9 100644 --- a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss +++ b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss @@ -3,4 +3,7 @@ ngx-monaco-editor { } .summary-accent { color: #969fb9 !important; +} +nb-card { + width: 70em; } \ No newline at end of file diff --git a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss index 01c8c4d18..b06c4d3dd 100644 --- a/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss +++ b/ui/src/app/shared/components/orb/sink/sink-details/sink-details.component.scss @@ -29,4 +29,8 @@ input { } .ns1red { color: #df316f; +} + +nb-card { + width: 25em; } \ No newline at end of file From f68d19253a109785a295bcccf206baf566d12954 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Tue, 6 Jun 2023 17:54:50 -0300 Subject: [PATCH 030/115] fix(orb-ui): horizontal scroll bar policy list (#2399) --- .../policies.agent/list/agent.policy.list.component.html | 3 ++- .../policies.agent/list/agent.policy.list.component.scss | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index ed76ee1ca..376ade7b9 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -38,8 +38,9 @@

All Policies

[rowHeight]="50" [rows]="filteredPolicies$ | async" [scrollbarV]="true" + [scrollbarH]="true" [sorts]="tableSorts" - class="orb orb-table" + class="orb orb-table scroll" >
diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss index a67f98dcb..9d5c170da 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss @@ -195,3 +195,6 @@ mat-chip-list { color: #f2994a; } } +.scroll { + width: 1520px; +} \ No newline at end of file From c4efbbabe2ffc61193751a30b8609cd5c1a03c0b Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Tue, 6 Jun 2023 18:13:10 -0300 Subject: [PATCH 031/115] fix(orb-ui): #617 finish change password page implementation (#2400) fix(orb-ui): #617 finish change password page implementation --- .../reset-password.component.html | 189 ++++++++++-------- .../reset-password.component.scss | 124 ++++++++++++ .../reset-password.component.ts | 2 + 3 files changed, 231 insertions(+), 84 deletions(-) diff --git a/ui/src/app/auth/pages/reset-password/reset-password.component.html b/ui/src/app/auth/pages/reset-password/reset-password.component.html index f367045a5..a96e222af 100644 --- a/ui/src/app/auth/pages/reset-password/reset-password.component.html +++ b/ui/src/app/auth/pages/reset-password/reset-password.component.html @@ -1,91 +1,112 @@ -

Change password

-

Please set a new password

+
+ - -

Oh snap!

-
    -
  • {{ error }}
  • -
-
+
+
+
+

Change password

+

Please set a new password

- -

Hooray!

-
    -
  • {{ message }}
  • -
-
+ +

Oh snap!

+
    +
  • {{ error }}
  • +
+
-
+ +

Hooray!

+
    +
  • {{ message }}
  • +
+
-
- - - -

- Password is required! -

-

- Password should contains - from {{getConfigValue('forms.validation.password.minLength')}} - to {{getConfigValue('forms.validation.password.maxLength')}} - characters -

-
-
+ -
- - - -

- Password confirmation is required! -

-

- Password does not match the confirm password. -

-
-
+
+ + + +

+ Password is required! +

+

+ Password should contains + from {{getConfigValue('forms.validation.password.minLength')}} + to {{getConfigValue('forms.validation.password.maxLength')}} + characters +

+
+
- -
+
+ + + +

+ Password confirmation is required! +

+

+ Password does not match the confirm password. +

+
+
- + + + + +
+
+
+ diff --git a/ui/src/app/auth/pages/reset-password/reset-password.component.scss b/ui/src/app/auth/pages/reset-password/reset-password.component.scss index 11a9b4e9f..9e11fbad8 100644 --- a/ui/src/app/auth/pages/reset-password/reset-password.component.scss +++ b/ui/src/app/auth/pages/reset-password/reset-password.component.scss @@ -1,3 +1,4 @@ +@import '../../../@theme/styles/themes'; /** * @license * Copyright Akveo. All Rights Reserved. @@ -8,3 +9,126 @@ margin-bottom: 3rem; } } + +.login-layout { + background: url('../../../../assets/images/login-background.png'); + transform: translateY(-2px); + + .orb-pane { + background-blend-mode: normal; + background-color: transparent; + display: flex; + margin: 0.2vh 350px 0.2vh 144px; + padding: 0; + + div { + max-width: 331px; + + img { + height: 119px; + margin-bottom: 47px; + width: 313px; + } + + p { + color: #969fb9; + font-family: 'Montserrat', serif; + font-size: 24px; + font-style: normal; + font-weight: 200 !important; + letter-spacing: 0; + line-height: 32px; + text-align: left; + } + + strong { + color: #fff; + font-family: 'Montserrat', serif; + font-size: 24px; + font-style: normal; + font-weight: 400 !important; + letter-spacing: 0; + line-height: 32px; + text-align: left; + } + } + } +} + +.form-pane { + height: 100%; + position: absolute; + right: 0; + top: 0; + width: 600px; + + a { + color: #62d9ff; + font-family: 'Montserrat', serif; + } + + .label { + color: #fff; + } + + .big { + font-size: 24px; + line-height: 32px; + } + + .bg { + background: #fff; + background-blend-mode: overlay; + height: 100%; + opacity: 0.2; + position: absolute; + width: 100%; + } + + .pane { + height: 100%; + padding: 0 6rem; + position: relative; + z-index: 3; + + span { + font-family: 'Montserrat', serif; + } + + p { + font-family: 'Montserrat', serif; + text-align: left; + } + + strong { + font-family: 'Montserrat', serif; + text-align: left; + } + + ul { + margin: 0; + padding: 0; + + li { + list-style: none; + margin: 0; + padding: 0; + } + } + + .alert-error { + background: linear-gradient(0deg, rgba(175, 80, 255, 0.25), rgba(175, 80, 255, 0.25)), #313e5d; + border: 1px solid #af50ff; + border-radius: 2px; + box-sizing: border-box; + } + } + + .password-icon { + color: nb-theme(color-basic-600); + float: right; + margin-right: 22px; + margin-top: -40px; + position: relative; + } +} diff --git a/ui/src/app/auth/pages/reset-password/reset-password.component.ts b/ui/src/app/auth/pages/reset-password/reset-password.component.ts index 4986718f0..a863e4f48 100644 --- a/ui/src/app/auth/pages/reset-password/reset-password.component.ts +++ b/ui/src/app/auth/pages/reset-password/reset-password.component.ts @@ -7,6 +7,7 @@ import { NbAuthService, NbResetPasswordComponent, } from '@nebular/auth'; +import { STRINGS } from 'assets/text/strings'; @Component({ selector: 'ngx-reset-password-page', @@ -15,6 +16,7 @@ import { changeDetection: ChangeDetectionStrategy.OnPush, }) export class ResetPasswordComponent extends NbResetPasswordComponent { + strings = STRINGS.login; redirectDelay: number = 0; From dec23722bda5604bcdb0a4cd4f731b2d63701445 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 6 Jun 2023 21:58:15 -0300 Subject: [PATCH 032/115] fix(sinks): bad gateway during partial update (#2401) fix(sinks): bad gateway during partial update (#2401) --- sinks/api/http/endpoint.go | 17 ++++++++++++----- sinks/api/http/endpoint_test.go | 24 +++++++++++------------- sinks/migrate/m1_upgrade_config.go | 10 +--------- sinks/sinks_service.go | 14 ++++++++++++++ sinks/sinks_service_test.go | 17 +++++++++++++---- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index d00d44027..ee8d8f83a 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -10,6 +10,8 @@ package http import ( "context" + "time" + "github.com/go-kit/kit/endpoint" "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" @@ -17,7 +19,6 @@ import ( "github.com/orb-community/orb/sinks/authentication_type" "github.com/orb-community/orb/sinks/backend" "go.uber.org/zap" - "time" ) func omitSecretInformation(configSvc *sinks.Configuration, inputSink sinks.Sink) (returnSink sinks.Sink, err error) { @@ -187,10 +188,16 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { svc.GetLogger().Error("error on updating sink", zap.Error(err)) return nil, err } - omittedSink, err := omitSecretInformation(configSvc, sinkEdited) - if err != nil { - svc.GetLogger().Error("sink was created, but got error in the response build", zap.Error(err)) - return nil, err + // partial update, without config information dont need be ommitted + var omittedSink sinks.Sink + if req.Config != nil || req.ConfigData != "" { + omittedSink, err = omitSecretInformation(configSvc, sinkEdited) + if err != nil { + svc.GetLogger().Error("sink was updated, but got error in the response build", zap.Error(err)) + return nil, err + } + } else { + svc.GetLogger().Info("request sink partial update", zap.String("sinkID", req.id)) } res := sinkRes{ ID: sinkEdited.ID, diff --git a/sinks/api/http/endpoint_test.go b/sinks/api/http/endpoint_test.go index 8fe630357..0eee7bcdf 100644 --- a/sinks/api/http/endpoint_test.go +++ b/sinks/api/http/endpoint_test.go @@ -12,6 +12,13 @@ import ( "context" "encoding/json" "fmt" + "io" + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + "github.com/gofrs/uuid" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" "github.com/opentracing/opentracing-go/mocktracer" @@ -23,12 +30,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "strings" - "testing" ) const ( @@ -1091,6 +1092,9 @@ func TestViewSink(t *testing.T) { TsCreated: sk.Created, }) + if data == "" { + return + } cases := map[string]struct { id string contentType string @@ -1098,13 +1102,7 @@ func TestViewSink(t *testing.T) { status int res string }{ - "view existing sink": { - id: sk.ID, - contentType: contentType, - auth: token, - status: http.StatusOK, - res: data, - }, + "view non-existing sink": { id: "logstash", contentType: contentType, diff --git a/sinks/migrate/m1_upgrade_config.go b/sinks/migrate/m1_upgrade_config.go index 1a40d618d..be7f9bd2f 100644 --- a/sinks/migrate/m1_upgrade_config.go +++ b/sinks/migrate/m1_upgrade_config.go @@ -2,14 +2,12 @@ package migrate import ( "context" - "fmt" + "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks" "github.com/orb-community/orb/sinks/authentication_type" "github.com/orb-community/orb/sinks/authentication_type/basicauth" "go.uber.org/zap" - "net/url" - "strings" ) type Plan1UpdateConfiguration struct { @@ -57,12 +55,6 @@ func (p *Plan1UpdateConfiguration) Up(ctx context.Context) (mainErr error) { } continue } - if _, err := url.Parse(sinkRemoteHost.(string)); err != nil { - s := sinkRemoteHost.(string) - if !strings.HasPrefix("https://", s) && !strings.HasPrefix("http://", s) { - sinkRemoteHost = fmt.Sprintf("https://%s", s) - } - } sinkUsername, ok := sink.Config["username"] if !ok { p.logger.Error("failed to update sink for lack of username", zap.String("sinkID", sink.ID)) diff --git a/sinks/sinks_service.go b/sinks/sinks_service.go index 33b731382..80d08a475 100644 --- a/sinks/sinks_service.go +++ b/sinks/sinks_service.go @@ -10,6 +10,7 @@ package sinks import ( "context" + "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks/authentication_type" @@ -195,6 +196,19 @@ func (svc sinkService) UpdateSinkInternal(ctx context.Context, sink Sink) (Sink, } } else { sink.Backend = currentSink.Backend + // we still need to validate here + be, err := validateBackend(&sink) + if err != nil { + return Sink{}, errors.Wrap(ErrMalformedEntity, err) + } + at, err := validateAuthType(&sink) + if err != nil { + return Sink{}, errors.Wrap(ErrMalformedEntity, err) + } + cfg = Configuration{ + Authentication: at, + Exporter: be, + } //// add default values defaultMetadata := make(types.Metadata, 1) defaultMetadata["opentelemetry"] = "enabled" diff --git a/sinks/sinks_service_test.go b/sinks/sinks_service_test.go index 3db4ec893..9b90ea0db 100644 --- a/sinks/sinks_service_test.go +++ b/sinks/sinks_service_test.go @@ -11,6 +11,8 @@ package sinks_test import ( "context" "fmt" + "testing" + "github.com/gofrs/uuid" mfsdk "github.com/mainflux/mainflux/pkg/sdk/go" thmocks "github.com/mainflux/mainflux/things/mocks" @@ -22,7 +24,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" - "testing" ) const ( @@ -530,10 +531,18 @@ func TestViewSink(t *testing.T) { State: sinks.Unknown, Error: "", Config: types.Metadata{ - "exporter": map[string]interface{}{"remote_host": "https://orb.community/"}, - "authentication": map[string]interface{}{"type": "basicauth", "username": "dbuser", "password": "dbpass"}, + "exporter": map[string]interface{}{ + "remote_host": "https://orb.community/", + }, + "authentication": map[string]interface{}{ + "type": "basicauth", + "username": "dbuser", + "password": "dbpass", + }, + }, + Tags: map[string]string{ + "cloud": "aws", }, - Tags: map[string]string{"cloud": "aws"}, } wrongID, _ := uuid.NewV4() sk, err := service.CreateSink(context.Background(), token, sink) From caa73a481a7e2cb8a93307644ca5136e1cd6a920 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Wed, 7 Jun 2023 11:53:27 -0300 Subject: [PATCH 033/115] fix(sinks): config return on sinks api (#2402) fix(sinks): config return on sinks api (#2402) --- sinks/api/http/endpoint.go | 42 +++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index ee8d8f83a..3fa83b503 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -199,18 +199,36 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { } else { svc.GetLogger().Info("request sink partial update", zap.String("sinkID", req.id)) } - res := sinkRes{ - ID: sinkEdited.ID, - Name: sinkEdited.Name.String(), - Description: *sinkEdited.Description, - Tags: sinkEdited.Tags, - State: sinkEdited.State.String(), - Error: sinkEdited.Error, - Backend: sinkEdited.Backend, - Config: omittedSink.Config, - ConfigData: omittedSink.ConfigData, - Format: sinkEdited.Format, - created: false, + var res sinkRes + if req.Config != nil || req.ConfigData != "" { + res = sinkRes{ + ID: sinkEdited.ID, + Name: sinkEdited.Name.String(), + Description: *sinkEdited.Description, + Tags: sinkEdited.Tags, + State: sinkEdited.State.String(), + Error: sinkEdited.Error, + Backend: sinkEdited.Backend, + Config: omittedSink.Config, + ConfigData: omittedSink.ConfigData, + Format: sinkEdited.Format, + created: false, + } + } else { + res = sinkRes{ + ID: sinkEdited.ID, + Name: sinkEdited.Name.String(), + Description: *sinkEdited.Description, + Tags: sinkEdited.Tags, + State: sinkEdited.State.String(), + Error: sinkEdited.Error, + Backend: sinkEdited.Backend, + Config: sinkEdited.Config, + ConfigData: sinkEdited.ConfigData, + Format: sinkEdited.Format, + created: false, + } + } return res, nil } From a3b9b3cbdcae4a11248231943498d38c7dc31c5b Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Wed, 7 Jun 2023 14:25:08 -0300 Subject: [PATCH 034/115] fix(sinks): partial update (#2403) fix(sinks): partial update (#2403) --- sinks/api/http/endpoint.go | 124 ++++++++++++++------------------ sinks/api/http/endpoint_test.go | 11 +-- 2 files changed, 60 insertions(+), 75 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index 3fa83b503..3d2563a08 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -129,107 +129,89 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { svc.GetLogger().Error("could not find sink with id", zap.String("sinkID", req.id), zap.Error(err)) return nil, err } - if err := req.validate(); err != nil { svc.GetLogger().Error("error validating request", zap.Error(err)) return nil, err } - var config types.Metadata + // Update only the fields in currentSink that are populated in req + if req.Tags != nil { + currentSink.Tags = req.Tags + } + if req.ConfigData != "" { + currentSink.ConfigData = req.ConfigData + } + if req.Format != "" { + currentSink.Format = req.Format + } + if req.Description != nil { + currentSink.Description = req.Description + } + if req.Name != "" { + nameID, err := types.NewIdentifier(req.Name) + if err != nil { + svc.GetLogger().Error("error on getting new identifier", zap.Error(err)) + return nil, errors.ErrConflict + } + currentSink.Name = nameID + } + var configSvc *sinks.Configuration var exporterConfig types.Metadata var authConfig types.Metadata - var configSvc *sinks.Configuration + + // Update the config if either req.Config or req.ConfigData is populated if req.Config != nil || req.ConfigData != "" { - if len(req.Format) > 0 && req.Format == "yaml" { - if len(req.ConfigData) > 0 { - configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromYaml(currentSink.Backend, req.ConfigData) - if err != nil { - svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - } else { + if req.Format == "yaml" { + configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromYaml(currentSink.Backend, req.ConfigData) + if err != nil { svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) - return nil, errors.Wrap(errors.ErrMalformedEntity, errors.New("missing required field when format is sent, config_data must be sent also")) + return nil, errors.Wrap(errors.ErrMalformedEntity, err) } } else if req.Config != nil { - configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromMeta(req.Backend, req.Config) + configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromMeta(currentSink.Backend, req.Config) if err != nil { svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) return nil, errors.Wrap(errors.ErrMalformedEntity, err) } } - config = types.Metadata{ + + currentSink.Config = types.Metadata{ "exporter": exporterConfig, authentication_type.AuthenticationKey: authConfig, } - } else { - config = currentSink.Config - } - - sink := sinks.Sink{ - ID: req.id, - Tags: req.Tags, - Config: config, - ConfigData: req.ConfigData, - Format: req.Format, - Description: req.Description, } - if req.Name != "" { - nameID, err := types.NewIdentifier(req.Name) - if err != nil { - svc.GetLogger().Error("error on getting new identifier", zap.Error(err)) - return nil, errors.ErrConflict - } - sink.Name = nameID + if err := req.validate(); err != nil { + svc.GetLogger().Error("error validating request", zap.Error(err)) + return nil, err } - sinkEdited, err := svc.UpdateSink(ctx, req.token, sink) + sinkEdited, err := svc.UpdateSink(ctx, req.token, currentSink) if err != nil { svc.GetLogger().Error("error on updating sink", zap.Error(err)) return nil, err } - // partial update, without config information dont need be ommitted + var omittedSink sinks.Sink - if req.Config != nil || req.ConfigData != "" { - omittedSink, err = omitSecretInformation(configSvc, sinkEdited) - if err != nil { - svc.GetLogger().Error("sink was updated, but got error in the response build", zap.Error(err)) - return nil, err - } - } else { - svc.GetLogger().Info("request sink partial update", zap.String("sinkID", req.id)) + omittedSink, err = omitSecretInformation(configSvc, sinkEdited) + if err != nil { + svc.GetLogger().Error("sink was updated, but got error in the response build", zap.Error(err)) + return nil, err } - var res sinkRes - if req.Config != nil || req.ConfigData != "" { - res = sinkRes{ - ID: sinkEdited.ID, - Name: sinkEdited.Name.String(), - Description: *sinkEdited.Description, - Tags: sinkEdited.Tags, - State: sinkEdited.State.String(), - Error: sinkEdited.Error, - Backend: sinkEdited.Backend, - Config: omittedSink.Config, - ConfigData: omittedSink.ConfigData, - Format: sinkEdited.Format, - created: false, - } - } else { - res = sinkRes{ - ID: sinkEdited.ID, - Name: sinkEdited.Name.String(), - Description: *sinkEdited.Description, - Tags: sinkEdited.Tags, - State: sinkEdited.State.String(), - Error: sinkEdited.Error, - Backend: sinkEdited.Backend, - Config: sinkEdited.Config, - ConfigData: sinkEdited.ConfigData, - Format: sinkEdited.Format, - created: false, - } + res := sinkRes{ + ID: sinkEdited.ID, + Name: sinkEdited.Name.String(), + Description: *sinkEdited.Description, + Tags: sinkEdited.Tags, + State: sinkEdited.State.String(), + Error: sinkEdited.Error, + Backend: sinkEdited.Backend, + Config: omittedSink.Config, + ConfigData: omittedSink.ConfigData, + Format: sinkEdited.Format, + created: false, } + return res, nil } } diff --git a/sinks/api/http/endpoint_test.go b/sinks/api/http/endpoint_test.go index 0eee7bcdf..68ca20fce 100644 --- a/sinks/api/http/endpoint_test.go +++ b/sinks/api/http/endpoint_test.go @@ -1092,9 +1092,6 @@ func TestViewSink(t *testing.T) { TsCreated: sk.Created, }) - if data == "" { - return - } cases := map[string]struct { id string contentType string @@ -1102,7 +1099,13 @@ func TestViewSink(t *testing.T) { status int res string }{ - + "view existing sink": { + id: sk.ID, + contentType: contentType, + auth: token, + status: http.StatusOK, + res: data, + }, "view non-existing sink": { id: "logstash", contentType: contentType, From 1dd42cc637b977dea2a2478069aa7b04a1516537 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 7 Jun 2023 14:54:17 -0300 Subject: [PATCH 035/115] fix(orb-ui): improve Usage attribute requests (#2404) --- .../list/agent.policy.list.component.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index 47144d72a..65cc264bb 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -27,8 +27,8 @@ import { FilterService } from 'app/common/services/filter.service'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; import { OrbService } from 'app/common/services/orb.service'; import { AgentPolicyDeleteComponent } from 'app/pages/datasets/policies.agent/delete/agent.policy.delete.component'; -import { Observable } from 'rxjs'; -import { map, withLatestFrom } from 'rxjs/operators'; +import { combineLatest, Observable } from 'rxjs'; +import { filter, map } from 'rxjs/operators'; import { STRINGS } from '../../../../../assets/text/strings'; @@ -87,16 +87,19 @@ export class AgentPolicyListComponent private filters: FilterService, ) { this.filters$ = this.filters.getFilters(); - - this.policies$ = this.orb.getPolicyListView().pipe( - withLatestFrom(this.orb.getDatasetListView()), + + this.policies$ = combineLatest([ + this.orb.getPolicyListView(), + this.orb.getDatasetListView() + ]).pipe( + filter(([policies, datasets]) => policies !== undefined && policies !== null && datasets !== undefined && datasets !== null), map(([policies, datasets]) => { return policies.map((policy) => { const dataset = datasets.filter((d) => d.valid && d.agent_policy_id === policy.id); return { ...policy, policy_usage: dataset.length > 0 ? AgentPolicyUsage.inUse : AgentPolicyUsage.notInUse }; - }) - } - )); + }); + }) + ); this.filterOptions = [ { From 24404ceb7b124a7d372923b4f9eaa0bda738eb91 Mon Sep 17 00:00:00 2001 From: manrodrigues Date: Wed, 7 Jun 2023 16:03:29 -0300 Subject: [PATCH 036/115] Test/eng 567 sinks new schema format (#2405) * using new sink schema format in test's sinks --- .../features/steps/control_plane_sink.py | 52 ++++--- .../features/steps/schemas/sink_schema.json | 129 +++++++++++++----- 2 files changed, 127 insertions(+), 54 deletions(-) diff --git a/python-test/features/steps/control_plane_sink.py b/python-test/features/steps/control_plane_sink.py index 7fef5505e..ad27d48b6 100644 --- a/python-test/features/steps/control_plane_sink.py +++ b/python-test/features/steps/control_plane_sink.py @@ -50,7 +50,6 @@ def create_sink(context, **kwargs): configuration_type = kwargs["configuration_type"].lower() else: configuration_type = "" - if include_otel_env_var == "true": context.sink = create_new_sink(token, sink_label_name, endpoint, username, password, include_otel=include_otel_env_var, otel=otel_map[enable_otel], @@ -96,6 +95,7 @@ def create_sink_with_conflict_name(context): def edit_sink_name_with_conflict(context): first_sink = get_sink(context.token, context.existent_sinks_id[0]) context.sink['name'] = first_sink['name'] + context.sink.pop("config") context.error_message = edit_sink(context.token, context.sink['id'], context.sink, expected_status_code=409) @@ -197,7 +197,7 @@ def check_sink_status(context, status, time_to_wait): def edit_sink_field(context, otel): assert_that(otel, any_of("enabled", "disabled")) sink = get_sink(context.token, context.sink['id']) - sink['config']['password'] = configs.get('prometheus_key') + sink['config']['authentication']['password'] = configs.get('prometheus_key') sink['config']["opentelemetry"] = otel context.sink = edit_sink(context.token, context.sink['id'], sink) @@ -224,26 +224,29 @@ def check_all_sinks_status(context): @step("the sink {field_to_edit} is edited and an {type_of_field} one is used") def edit_sink_field(context, field_to_edit, type_of_field): - assert_that(field_to_edit, any_of("remote host", "username", "password", "name", "description", "tags"), + assert_that(field_to_edit, any_of("remote host", "endpoint", "username", "password", "name", "description", "tags"), "Unexpected field to be edited.") assert_that(type_of_field, any_of("valid", "invalid"), "Invalid type of sink field") sink = get_sink(context.token, context.sink['id']) - sink['config']['password'] = configs.get('prometheus_key') - if field_to_edit == "remote host": + sink['config']['authentication']['password'] = configs.get('prometheus_key') + if field_to_edit == "remote host" or field_to_edit == "endpoint": + exporter_key = {"prometheus": "remote_host", "otlphttp": "endpoint"} + sink_backend = context.sink.get("backend") + assert_that(sink_backend, any_of("prometheus", "otlphttp"), f"Invalid sink backend: '{sink_backend}'") if type_of_field == "invalid": - sink['config']['remote_host'] = context.remote_prometheus_endpoint[:-2] + sink['config']['exporter'][exporter_key[sink_backend]] = context.remote_prometheus_endpoint[:-2] else: - sink['config']['remote_host'] = configs.get('remote_prometheus_endpoint') + sink['config']['exporter'][exporter_key[sink_backend]] = configs.get('remote_prometheus_endpoint') if field_to_edit == "password": if type_of_field == "invalid": - sink['config']['password'] = context.prometheus_key[:-2] + sink['config']['authentication']['password'] = context.prometheus_key[:-2] else: - sink['config']['password'] = configs.get('prometheus_key') + sink['config']['authentication']['password'] = configs.get('prometheus_key') if field_to_edit == "username": if type_of_field == "invalid": - sink['config']['username'] = context.prometheus_username[:-2] + sink['config']['authentication']['username'] = context.prometheus_username[:-2] else: - sink['config']['username'] = configs.get('prometheus_username') + sink['config']['authentication']['username'] = configs.get('prometheus_username') context.sink = edit_sink(context.token, context.sink['id'], sink) @@ -270,11 +273,16 @@ def sink_partial_update(context, sink_keys): "partial update") assert_that(include_otel_env_var, any_of("true", "false"), "Unexpected value for 'include_otel_env_var' on " "sinks partial update") + exporter_key = {"prometheus": "remote_host", "otlphttp": "endpoint"} + sink_backend = context.sink.get("backend") + assert_that(sink_backend, any_of("prometheus", "otlphttp"), f"Invalid sink backend: '{sink_backend}'") if include_otel_env_var == "true": - sink_configs = {"remote_host": remote_host, "username": username, "password": password, + sink_configs = {"authentication": {"type": "basicauth", "password": password, "username": username}, + "exporter": {exporter_key[sink_backend]: remote_host}, "opentelemetry": otel_map[enable_otel]} else: - sink_configs = {"remote_host": remote_host, "username": username, "password": password} + sink_configs = {"authentication": {"type": "basicauth", "password": password, "username": username}, + "exporter": {exporter_key[sink_backend]: remote_host}} context.values_to_use_to_update_sink = {"name": f"{context.sink['name']}_updated", "description": "this sink has been updated", "tags": {"sink": "updated", "new": "tag"}, "config": sink_configs} @@ -317,7 +325,7 @@ def clean_sinks(context): delete_sinks(token, sinks_filtered_list) -def create_new_sink(token, name_label, remote_host, username, password, description=None, tag_key='', tag_value=None, +def create_new_sink(token, name_label, remote_host, username, password, description=None, tag_key=None, tag_value=None, backend_type="prometheus", include_otel="false", otel="disabled", configuration_type="", expected_status_code=201): """ @@ -340,22 +348,23 @@ def create_new_sink(token, name_label, remote_host, username, password, descript :return: (dict) a dictionary containing the created sink data """ assert_that(include_otel, any_of("true", "false"), "Unexpected value for 'include_otel' on sinks creation") + exporter_key = {"prometheus": "remote_host", "otlphttp": "endpoint"} if include_otel == "true": - sink_configs = {"remote_host": remote_host, "username": username, "password": password, "opentelemetry": otel} + sink_configs = {"authentication": {"type": "basicauth", "password": password, "username": username}, + "exporter": {exporter_key[backend_type]: remote_host}, "opentelemetry": otel} else: - sink_configs = {"remote_host": remote_host, "username": username, "password": password} + sink_configs = {"authentication": {"type": "basicauth", "password": password, "username": username}, + "exporter": {exporter_key[backend_type]: remote_host}} if configuration_type == "yaml": sink_configs_yaml = yaml.dump(sink_configs) json_request = {"name": name_label, "description": description, "tags": {tag_key: tag_value}, - "backend": backend_type, "validate_only": False, "config_data": sink_configs_yaml, - "format": configuration_type} + "backend": backend_type, "config_data": sink_configs_yaml, "format": configuration_type} elif configuration_type == "json": json_request = {"name": name_label, "description": description, "tags": {tag_key: tag_value}, - "backend": backend_type, "validate_only": False, "config": sink_configs, - "format": configuration_type} + "backend": backend_type, "config": sink_configs, "format": configuration_type} else: json_request = {"name": name_label, "description": description, "tags": {tag_key: tag_value}, - "backend": backend_type, "validate_only": False, "config": sink_configs} + "backend": backend_type, "config": sink_configs} headers_request = {'Content-type': 'application/json', 'Accept': '*/*', 'Authorization': f'Bearer {token}'} json_request = remove_empty_from_json(json_request) response = requests.post(orb_url + '/api/v1/sinks', json=json_request, headers=headers_request, @@ -366,7 +375,6 @@ def create_new_sink(token, name_label, remote_host, username, password, descript response_json = response.text assert_that(response.status_code, equal_to(expected_status_code), 'Request to create sink failed with status=' + str(response.status_code) + ': ' + str(response_json)) - return response_json diff --git a/python-test/features/steps/schemas/sink_schema.json b/python-test/features/steps/schemas/sink_schema.json index 7b1532d86..091f8591d 100644 --- a/python-test/features/steps/schemas/sink_schema.json +++ b/python-test/features/steps/schemas/sink_schema.json @@ -35,9 +35,17 @@ "default": "", "title": "The description Schema", "examples": [ - "" + "This is a sink with prometheus backend" ] }, + "tags": { + "type": "object", + "default": {}, + "title": "The tags Schema", + "required": [], + "properties": {}, + "examples": [{}] + }, "state": { "type": "string", "default": "", @@ -59,40 +67,91 @@ "default": {}, "title": "The config Schema", "required": [ - "password", - "remote_host", - "username" + "authentication", + "exporter" ], "properties": { - "password": { - "type": "string", - "default": "", - "title": "The password Schema", - "examples": [ - "pass" - ] + "authentication": { + "type": "object", + "default": {}, + "title": "The authentication Schema", + "required": [ + "password", + "type", + "username" + ], + "properties": { + "password": { + "type": "string", + "default": "", + "title": "The password Schema", + "examples": [ + "" + ] + }, + "type": { + "type": "string", + "default": "", + "title": "The type Schema", + "examples": [ + "basicauth" + ] + }, + "username": { + "type": "string", + "default": "", + "title": "The username Schema", + "examples": [ + "admin" + ] + } + }, + "examples": [{ + "password": "", + "type": "basicauth", + "username": "admin" + }] }, - "remote_host": { - "type": "string", - "default": "", - "title": "The remote_host Schema", - "examples": [ - "https://prometheus-prod-10-prod-us-central-0.grafana.net/api/prom/push" - ] + "exporter": { + "type": "object", + "default": {}, + "title": "The exporter Schema", + "required": [ + "remote_host" + ], + "properties": { + "remote_host": { + "type": "string", + "default": "", + "title": "The remote_host Schema", + "examples": [ + "https://my.prometheus.endpoint/prom/push" + ] + } + }, + "examples": [{ + "remote_host": "https://my.prometheus.endpoint/prom/push" + }] }, - "username": { + "opentelemetry": { "type": "string", "default": "", - "title": "The username Schema", + "title": "The opentelemetry Schema", "examples": [ - "user" + "enabled" ] } }, "examples": [{ - "password": "pass", - "remote_host": "https://prometheus-prod-10-prod-us-central-0.grafana.net/api/prom/push", - "username": "user" + "authentication": { + "password": "12345678", + "type": "basicauth", + "username": "admin" + }, + "exporter": { + "remote_host": "https://my.prometheus.endpoint/prom/push" + }, + "opentelemetry": "enabled" }] }, "ts_created": { @@ -100,21 +159,27 @@ "default": "", "title": "The ts_created Schema", "examples": [ - "2022-05-27T14:12:09.108703Z" + "2023-06-01T17:37:21.848101999Z" ] } }, "examples": [{ - "id": "ef8b4710-734e-469f-b4ba-724f857499a9", - "name": "sink-schema", + "id": "f000638f-2a8a-4669-b681-b65d5c46d871", + "name": "test_sink_label_name_mEpBRavPHa", "description": "", "state": "unknown", "backend": "prometheus", "config": { - "password": "pass", - "remote_host": "https://prometheus-prod-10-prod-us-central-0.grafana.net/api/prom/push", - "username": "user" + "authentication": { + "password": "", + "type": "basicauth", + "username": "admin" + }, + "exporter": { + "remote_host": "https://prometheus.qa.orb.live/api/v1/write" + }, + "opentelemetry": "enabled" }, - "ts_created": "2022-05-27T14:12:09.108703Z" + "ts_created": "2023-06-01T17:37:21.848101999Z" }] -} +} \ No newline at end of file From cf237858da193e454d6f28f0e651962bc6ac2e2b Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Thu, 8 Jun 2023 16:14:26 -0300 Subject: [PATCH 037/115] feat(ci): Add labels on pull requests (#2406) feat(ci): Add labels on pull requests (#2406) --- .github/labeler.yml | 73 ++++++++++++++++++++++++++++++++++ .github/workflows/labeler.yaml | 12 ++++++ 2 files changed, 85 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/workflows/labeler.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 000000000..7903615fb --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,73 @@ +documentation: + - docs/* + - docs/**/* + - mkdocs.yml + +github-actions: + - .github/workflows/* + - .github/workflows/**/* + - .github/dependabot.yml + - .github/boring-cyborg.yml + - .github/release-drafter.yml + - .github/semantic.yml + - .github/stale.yml + - .github/mergify.yml + - .github/labeler.yml + +github-templates: + - .github/ISSUE_TEMPLATE/* + - .github/PULL_REQUEST_TEMPLATE.md + - .github/.chglog/* + - .github/.chglog/**/* + +internal: + - .flake8 + - .bandit.baseline + - .gitignore + - .pre-commit-config.yaml + - MANIFEST.in + - Makefile + - CONTRIBUTING.md + - MAINTAINERS.md + - CODE_OF_CONDUCT.md + - LICENSE + - THIRD-PARTY-LICENSES + - .dockerignore + - .editorconfig + - setup.cfg + +dependencies: + - pyproject.toml + - poetry.lock + - requirements.txt + +tests: + - automated_tests/* + - automated_tests/**/* + - tests/* + - tests/**/* + +build: + - Dockerfile + +golang: + - "**/*.go" + +javascript: + - "**/*.json" + +json: + - "**/*.json" + +markdown: + - "**/*.md" + +python: + - "**/*.py" + +sql: + - "**/*.py" + +typescript: + - "**/*.ts" + - "**/*.tsx" diff --git a/.github/workflows/labeler.yaml b/.github/workflows/labeler.yaml new file mode 100644 index 000000000..857cfb4a7 --- /dev/null +++ b/.github/workflows/labeler.yaml @@ -0,0 +1,12 @@ +name: "Pull Request Labeler" +on: + - pull_request_target + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 From 99db6011f6b036ee3f4fbd636f78df510841c08b Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:51:01 -0300 Subject: [PATCH 038/115] Fix(sinks): config return empty (#2409) Fix(sinks): config return empty (#2409) --- sinks/api/http/endpoint.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index 3d2563a08..d699931fe 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -133,13 +133,12 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { svc.GetLogger().Error("error validating request", zap.Error(err)) return nil, err } + // Update only the fields in currentSink that are populated in req if req.Tags != nil { currentSink.Tags = req.Tags } - if req.ConfigData != "" { - currentSink.ConfigData = req.ConfigData - } + if req.Format != "" { currentSink.Format = req.Format } @@ -173,16 +172,25 @@ func updateSinkEndpoint(svc sinks.SinkService) endpoint.Endpoint { return nil, errors.Wrap(errors.ErrMalformedEntity, err) } } - - currentSink.Config = types.Metadata{ - "exporter": exporterConfig, - authentication_type.AuthenticationKey: authConfig, + } else { + if currentSink.Format == "yaml" { + configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromYaml(currentSink.Backend, currentSink.ConfigData) + if err != nil { + svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) + return nil, errors.Wrap(errors.ErrMalformedEntity, err) + } + } else { + configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromMeta(currentSink.Backend, currentSink.Config) + if err != nil { + svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) + return nil, errors.Wrap(errors.ErrMalformedEntity, err) + } } } - if err := req.validate(); err != nil { - svc.GetLogger().Error("error validating request", zap.Error(err)) - return nil, err + currentSink.Config = types.Metadata{ + "exporter": exporterConfig, + authentication_type.AuthenticationKey: authConfig, } sinkEdited, err := svc.UpdateSink(ctx, req.token, currentSink) From df57e3106b08330622ab74e65af4619f5593c282 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Tue, 13 Jun 2023 17:55:14 -0300 Subject: [PATCH 039/115] feat(orb-ui): Agent View, checkboxes in the table and multiples reset requests (#2411) --- .../agents/list/agent.list.component.html | 21 ++++- .../agents/list/agent.list.component.scss | 23 +++++ .../fleet/agents/list/agent.list.component.ts | 87 ++++++++++++++++++- .../agents/reset/agent.reset.component.html | 36 ++++++++ .../agents/reset/agent.reset.component.scss | 49 +++++++++++ .../agents/reset/agent.reset.component.ts | 33 +++++++ ui/src/app/pages/pages.module.ts | 2 + 7 files changed, 249 insertions(+), 2 deletions(-) create mode 100644 ui/src/app/pages/fleet/agents/reset/agent.reset.component.html create mode 100644 ui/src/app/pages/fleet/agents/reset/agent.reset.component.scss create mode 100644 ui/src/app/pages/fleet/agents/reset/agent.reset.component.ts diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.html b/ui/src/app/pages/fleet/agents/list/agent.list.component.html index 4d6c5a246..2a99775ca 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.html +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.html @@ -15,7 +15,19 @@

All Agents

- +
+ + +
+
@@ -144,3 +158,8 @@

All Agents

+ + + + \ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.scss b/ui/src/app/pages/fleet/agents/list/agent.list.component.scss index 26b224e2b..35b426b97 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.scss +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.scss @@ -178,3 +178,26 @@ tr div p { color: #969fb9; } } +input[type=checkbox] { + margin-left: 10px; +} +.agent-reset { + color: #fff !important; + font-family: 'Montserrat', sans-serif; + font-weight: 500; + text-transform: none !important; + width: 125px; + + &.btn-disabled { + background: #2b3148; + } + + &:not(.btn-disabled) { + background-color: #3089fc !important; + } +} +.agent-options { + display: flex; + flex-direction: row; + align-items: center; +} \ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 7f21c61a5..db1e15ba0 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -30,6 +30,7 @@ import { AgentDeleteComponent } from 'app/pages/fleet/agents/delete/agent.delete import { AgentDetailsComponent } from 'app/pages/fleet/agents/details/agent.details.component'; import { STRINGS } from 'assets/text/strings'; import { Observable } from 'rxjs'; +import { AgentResetComponent } from '../reset/agent.reset.component'; @Component({ selector: 'ngx-agent-list-component', @@ -45,6 +46,12 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe loading = false; + selected: any[] = []; + + canResetAgents: boolean; + + isResetting: boolean; + // templates @ViewChild('agentNameTemplateCell') agentNameTemplateCell: TemplateRef; @@ -56,6 +63,8 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe @ViewChild('actionsTemplateCell') actionsTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + @ViewChild('agentLastActivityTemplateCell') agentLastActivityTemplateCell: TemplateRef; @@ -84,7 +93,11 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe private router: Router, private orb: OrbService, private filters: FilterService, + protected agentsService: AgentsService, + protected notificationService: NotificationsService, ) { + this.isResetting = false; + this.selected = []; this.agents$ = this.orb.getAgentListView(); this.columns = []; @@ -147,6 +160,15 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe ngAfterViewInit() { this.orb.refreshNow(); this.columns = [ + { + name: '', + prop: 'checkbox', + flexGrow: 1, + minWidth: 62, + canAutoResize: true, + sortable: false, + cellTemplate: this.checkboxTemplateCell, + }, { prop: 'name', flexGrow: 4, @@ -188,7 +210,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe }, { prop: 'ts_last_hb', - flexGrow: 2, + flexGrow: 3, minWidth: 150, canAutoResize: true, name: 'Last Activity', @@ -207,6 +229,53 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe ]; } + + public onCheckboxChange(event: any, row: any): void { + let selectedAgent = { + id: "", + resetable: true, + } + if (this.getChecked(row) === false) { + let resetable = true; + if (row.state === 'new' || row.state === 'offline') { + resetable = false; + } + selectedAgent.id = row.id; + selectedAgent.resetable = resetable; + this.selected.push(selectedAgent); + } else { + for (let i = 0; i < this.selected.length; i++) { + if (this.selected[i].id === row.id) { + this.selected.splice(i, 1); + break; + } + } + } + const reset = this.selected.filter((e) => e.resetable === false); + this.canResetAgents = reset.length > 0 ? true : false; + } + + + + public getChecked(row: any): boolean { + const item = this.selected.filter((e) => e.id === row.id); + return item.length > 0 ? true : false; + } + + resetAgents() { + if (!this.isResetting) { + this.isResetting = true; + this.selected.forEach((agent) => { + this.agentService.resetAgent(agent.id).subscribe(); + }) + this.notifyResetSuccess(); + this.isResetting = false; + } + } + notifyResetSuccess() { + this.notificationService.success('All Agents Resets Requested', ''); + } + onOpenView(agent: any) { this.router.navigate([`view/${agent.id}`], { relativeTo: this.route, @@ -244,6 +313,22 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe }); } + onOpenResetAgents() { + const size = this.selected.length; + this.dialogService + .open(AgentResetComponent, { + context: { size }, + autoFocus: true, + closeOnEsc: true, + }) + .onClose.subscribe((confirm) => { + if (confirm) { + this.resetAgents(); + this.orb.refreshNow(); + } + }) + } + openDetailsModal(row: any) { this.dialogService .open(AgentDetailsComponent, { diff --git a/ui/src/app/pages/fleet/agents/reset/agent.reset.component.html b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.html new file mode 100644 index 000000000..d798fb77d --- /dev/null +++ b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.html @@ -0,0 +1,36 @@ + + + Reset Agents Confirmation + + + +

Are you sure you want to reset a total of {{ size }} Agents? *

+

*To confirm, type the amount of agents to be reset.

+ + + {{size}} + +
+ + + +
\ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/reset/agent.reset.component.scss b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.scss new file mode 100644 index 000000000..48fcf8cf0 --- /dev/null +++ b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.scss @@ -0,0 +1,49 @@ +nb-card { + max-width: 38rem; + + nb-card-header { + background: #232940; + color: #969fb9; + } + + nb-card-body { + margin: 2rem 3rem; + padding: 0; + + p { + color: #969fb9; + } + + .ns1-red { + color: #df316f; + } + } + + nb-card-footer { + text-align: center; + padding: 1.5rem; + } + } + + // ORB + ::ng-deep { + .orb-close-dialog { + background-color: #23294000; + border-radius: 4px; + display: contents; + float: right; + + > span { + float: right; + font-size: 1.5rem; + color: #3089fc; + font-weight: 900; + } + } + + .orb-sink-delete-warning-button:not(.btn-disabled) { + background-color: #3089fc !important; + color: #ffffff !important; + } + } + \ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/reset/agent.reset.component.ts b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.ts new file mode 100644 index 000000000..59ec7a923 --- /dev/null +++ b/ui/src/app/pages/fleet/agents/reset/agent.reset.component.ts @@ -0,0 +1,33 @@ +import { Component, Input } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; +import { STRINGS } from 'assets/text/strings'; + +@Component({ + selector: 'ngx-agent-reset-component', + templateUrl: './agent.reset.component.html', + styleUrls: ['./agent.reset.component.scss'], +}) + +export class AgentResetComponent { + strings = STRINGS.agents; + @Input() size: Number; + + validationInput: Number; + + constructor( + protected dialogRef: NbDialogRef, + ) { + } + + onDelete() { + this.dialogRef.close(true); + } + + onClose() { + this.dialogRef.close(false); + } + + isEnabled(): boolean { + return this.validationInput === this.size; + } +} \ No newline at end of file diff --git a/ui/src/app/pages/pages.module.ts b/ui/src/app/pages/pages.module.ts index 2685d1fe4..3cb52999f 100644 --- a/ui/src/app/pages/pages.module.ts +++ b/ui/src/app/pages/pages.module.ts @@ -49,6 +49,7 @@ import { AgentGroupAddComponent } from 'app/pages/fleet/groups/add/agent.group.a import { AgentGroupDeleteComponent } from 'app/pages/fleet/groups/delete/agent.group.delete.component'; import { AgentGroupDetailsComponent } from 'app/pages/fleet/groups/details/agent.group.details.component'; import { AgentGroupListComponent } from 'app/pages/fleet/groups/list/agent.group.list.component'; +import { AgentResetComponent } from 'app/pages/fleet/agents/reset/agent.reset.component'; import { ShowcaseComponent } from 'app/pages/showcase/showcase.component'; import { SinkAddComponent } from 'app/pages/sinks/add/sink-add.component'; import { SinkDeleteComponent } from 'app/pages/sinks/delete/sink.delete.component'; @@ -124,6 +125,7 @@ import { SinkViewComponent } from './sinks/view/sink.view.component'; AgentListComponent, AgentAddComponent, AgentDeleteComponent, + AgentResetComponent, AgentDetailsComponent, AgentKeyComponent, AgentMatchComponent, From 489e7dca67f31df8a6cc37fc3fdb48eada1941ec Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 14 Jun 2023 12:57:40 -0300 Subject: [PATCH 040/115] fix(orb-ui): few adjustments policy list (#2412) --- .../policies.agent/list/agent.policy.list.component.html | 2 +- .../datasets/policies.agent/list/agent.policy.list.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index 376ade7b9..bb1e01f59 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -40,7 +40,7 @@

All Policies

[scrollbarV]="true" [scrollbarH]="true" [sorts]="tableSorts" - class="orb orb-table scroll" + class="orb orb-table" > diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index 65cc264bb..90cc3983b 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -245,7 +245,7 @@ export class AgentPolicyListComponent { name: '', prop: 'actions', - minWidth: 150, + minWidth: 200, resizeable: false, sortable: false, flexGrow: 1, From b675579507e413a7b85e62f196522954a86326b2 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Wed, 14 Jun 2023 15:17:23 -0300 Subject: [PATCH 041/115] feat(fleet): add agent metadata to get all agents to display version. (#2413) Co-authored-by: Luiz Pegoraro --- fleet/api/http/endpoint.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fleet/api/http/endpoint.go b/fleet/api/http/endpoint.go index d63b8b765..4aa369e44 100644 --- a/fleet/api/http/endpoint.go +++ b/fleet/api/http/endpoint.go @@ -304,15 +304,16 @@ func listAgentsEndpoint(svc fleet.Service) endpoint.Endpoint { policyState, _ := svc.GetPolicyState(ctx, ag) view := agentRes{ - ID: ag.MFThingID, - Name: ag.Name.String(), - ChannelID: ag.MFChannelID, - AgentTags: ag.AgentTags, - OrbTags: *ag.OrbTags, - TsCreated: ag.Created, - State: ag.State.String(), - TsLastHB: ag.LastHB, - PolicyState: policyState, + ID: ag.MFThingID, + Name: ag.Name.String(), + ChannelID: ag.MFChannelID, + AgentTags: ag.AgentTags, + OrbTags: *ag.OrbTags, + TsCreated: ag.Created, + State: ag.State.String(), + TsLastHB: ag.LastHB, + PolicyState: policyState, + AgentMetadata: ag.AgentMetadata, } res.Agents = append(res.Agents, view) } From b0a9848fa76efb3709c9057ff0af0f002db040c8 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Thu, 15 Jun 2023 14:15:00 -0300 Subject: [PATCH 042/115] feat(orb-ui): #33 delete multiple elements (#2414) --- .../list/agent.policy.list.component.html | 18 ++++- .../list/agent.policy.list.component.scss | 17 ++++ .../list/agent.policy.list.component.ts | 72 +++++++++++++++-- .../agents/list/agent.list.component.html | 11 ++- .../agents/list/agent.list.component.scss | 13 ++- .../fleet/agents/list/agent.list.component.ts | 53 ++++++++---- .../agents/reset/agent.reset.component.html | 2 +- .../agents/reset/agent.reset.component.scss | 4 +- .../list/agent.group.list.component.html | 19 ++++- .../list/agent.group.list.component.scss | 17 ++++ .../groups/list/agent.group.list.component.ts | 69 ++++++++++++++-- ui/src/app/pages/pages.module.ts | 3 + .../pages/sinks/list/sink.list.component.html | 19 ++++- .../pages/sinks/list/sink.list.component.scss | 17 ++++ .../pages/sinks/list/sink.list.component.ts | 81 ++++++++++++++++--- .../delete/delete.selected.component.html | 34 ++++++++ .../delete/delete.selected.component.scss | 51 ++++++++++++ .../delete/delete.selected.component.ts | 34 ++++++++ 18 files changed, 485 insertions(+), 49 deletions(-) create mode 100644 ui/src/app/shared/components/delete/delete.selected.component.html create mode 100644 ui/src/app/shared/components/delete/delete.selected.component.scss create mode 100644 ui/src/app/shared/components/delete/delete.selected.component.ts diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index bb1e01f59..cebce7010 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -16,7 +16,16 @@

All Policies

- +
+ + +
@@ -131,4 +142,9 @@

All Policies

{{ value | titlecase }} + + + + \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss index 9d5c170da..383329cf7 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.scss @@ -197,4 +197,21 @@ mat-chip-list { } .scroll { width: 1520px; +} +.options { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; +} +.delete-selected { + color: #ffffff !important; + font-family: 'Montserrat', sans-serif; + font-weight: 600; + text-transform: none !important; + width: 90px; + background-color: #df316f !important; +} +input[type=checkbox] { + margin-left: 10px; } \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index 90cc3983b..f1ffe6959 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -27,6 +27,7 @@ import { FilterService } from 'app/common/services/filter.service'; import { NotificationsService } from 'app/common/services/notifications/notifications.service'; import { OrbService } from 'app/common/services/orb.service'; import { AgentPolicyDeleteComponent } from 'app/pages/datasets/policies.agent/delete/agent.policy.delete.component'; +import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; import { combineLatest, Observable } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { STRINGS } from '../../../../../assets/text/strings'; @@ -47,6 +48,8 @@ export class AgentPolicyListComponent loading = false; + selected: any[] = []; + @ViewChild('nameTemplateCell') nameTemplateCell: TemplateRef; @ViewChild('versionTemplateCell') versionTemplateCell: TemplateRef; @@ -55,6 +58,8 @@ export class AgentPolicyListComponent @ViewChild('usageStateTemplateCell') usageStateTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + tableSorts = [ { prop: 'name', @@ -180,12 +185,21 @@ export class AgentPolicyListComponent this.orb.refreshNow(); this.columns = [ + { + name: '', + prop: 'checkbox', + flexGrow: 0.5, + minWidth: 62, + canAutoResize: true, + sortable: false, + cellTemplate: this.checkboxTemplateCell, + }, { prop: 'name', name: 'Policy Name', resizeable: false, canAutoResize: true, - flexGrow: 1.5, + flexGrow: 4, minWidth: 100, cellTemplate: this.nameTemplateCell, }, @@ -194,7 +208,7 @@ export class AgentPolicyListComponent name: 'Usage', resizeable: false, canAutoResize: true, - flexGrow: 1, + flexGrow: 3, minWidth: 100, cellTemplate: this.usageStateTemplateCell, }, @@ -202,13 +216,13 @@ export class AgentPolicyListComponent prop: 'description', name: 'Description', resizeable: false, - flexGrow: 1, + flexGrow: 4, minWidth: 100, cellTemplate: this.nameTemplateCell, }, { prop: 'tags', - flexGrow: 1, + flexGrow: 3, canAutoResize: true, name: 'Tags', minWidth: 150, @@ -227,7 +241,7 @@ export class AgentPolicyListComponent prop: 'version', name: 'Version', resizeable: false, - flexGrow: 1, + flexGrow: 2, minWidth: 50, cellTemplate: this.versionTemplateCell, }, @@ -239,7 +253,7 @@ export class AgentPolicyListComponent }, name: 'Last Modified', minWidth: 110, - flexGrow: 1, + flexGrow: 3, resizeable: false, }, { @@ -248,7 +262,7 @@ export class AgentPolicyListComponent minWidth: 200, resizeable: false, sortable: false, - flexGrow: 1, + flexGrow: 2, cellTemplate: this.actionsTemplateCell, }, ]; @@ -295,4 +309,48 @@ export class AgentPolicyListComponent } }); } + onOpenDeleteSelected() { + const size = this.selected.length; + const elementName = "Policies" + this.dialogService + .open(DeleteSelectedComponent, { + context: { size, elementName }, + autoFocus: true, + closeOnEsc: true, + }) + .onClose.subscribe((confirm) => { + if (confirm) { + this.deleteSelectedAgentsPolicy(); + this.orb.refreshNow(); + } + }); + } + + deleteSelectedAgentsPolicy() { + this.selected.forEach((policyId) => { + this.agentPoliciesService.deleteAgentPolicy(policyId).subscribe(); + }) + this.notificationsService.success('All selected Policies delete requests succeeded', ''); + } + public onCheckboxChange(event: any, row: any): void { + + if (this.getChecked(row) === false) { + this.selected.push(row.id); + } + else { + for (let i = 0; i < this.selected.length; i++) { + if (this.selected[i] === row.id) { + this.selected.splice(i, 1); + break; + } + } + } + console.log(this.selected); + } + + public getChecked(row: any): boolean { + const item = this.selected.filter((e) => e === row.id); + return item.length > 0 ? true : false; + } } + diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.html b/ui/src/app/pages/fleet/agents/list/agent.list.component.html index 2a99775ca..29dcab57f 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.html +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.html @@ -15,8 +15,15 @@

All Agents

-
+
+ -

Are you sure you want to reset a total of {{ size }} Agents? *

+

Are you sure you want to reset a total of {{ size }} Agents?

*To confirm, type the amount of agents to be reset.

{{ strings.list.header }}
- +
+ + +
@@ -121,3 +133,8 @@

{{ strings.list.header }}

+ + + + \ No newline at end of file diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss index 16ab47381..c65dc661e 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.scss @@ -181,3 +181,20 @@ mat-chip-list { transform: translateX(-70%); } } +.options { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; +} +.delete-selected { + color: #ffffff !important; + font-family: 'Montserrat', sans-serif; + font-weight: 600; + text-transform: none !important; + width: 90px; + background-color: #df316f !important; +} +input[type=checkbox] { + margin-left: 10px; +} \ No newline at end of file diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts index c37b597a9..a55d7b3d5 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts @@ -29,6 +29,7 @@ import { OrbService } from 'app/common/services/orb.service'; import { AgentMatchComponent } from 'app/pages/fleet/agents/match/agent.match.component'; import { AgentGroupDeleteComponent } from 'app/pages/fleet/groups/delete/agent.group.delete.component'; import { AgentGroupDetailsComponent } from 'app/pages/fleet/groups/details/agent.group.details.component'; +import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; import { STRINGS } from 'assets/text/strings'; import { Observable } from 'rxjs'; @@ -49,6 +50,8 @@ export class AgentGroupListComponent searchPlaceholder = 'Search by name'; + selected: any[] = []; + // templates @ViewChild('agentGroupNameTemplateCell') agentGroupNameTemplateCell: TemplateRef; @@ -61,6 +64,8 @@ export class AgentGroupListComponent @ViewChild('actionsTemplateCell') actionsTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + filterValue = null; tableSorts = [ @@ -91,6 +96,8 @@ export class AgentGroupListComponent private orb: OrbService, private filters: FilterService, ) { + this.selected = []; + this.groups$ = this.orb.getGroupListView(); this.filters$ = this.filters.getFilters(); @@ -151,10 +158,19 @@ export class AgentGroupListComponent ngAfterViewInit() { this.orb.refreshNow(); this.columns = [ + { + name: '', + prop: 'checkbox', + flexGrow: 0.5, + minWidth: 62, + canAutoResize: true, + sortable: false, + cellTemplate: this.checkboxTemplateCell, + }, { prop: 'name', name: 'Name', - flexGrow: 1, + flexGrow: 4, canAutoResize: true, resizeable: false, minWidth: 150, @@ -163,7 +179,7 @@ export class AgentGroupListComponent { prop: 'description', name: 'Description', - flexGrow: 2, + flexGrow: 6, canAutoResize: true, resizeable: false, minWidth: 180, @@ -172,7 +188,7 @@ export class AgentGroupListComponent { prop: 'matching_agents', name: 'Agents', - flexGrow: 1, + flexGrow: 3, canAutoResize: true, resizeable: false, minWidth: 80, @@ -182,7 +198,7 @@ export class AgentGroupListComponent { prop: 'tags', name: 'Tags', - flexGrow: 3, + flexGrow: 10, canAutoResize: true, resizeable: false, cellTemplate: this.agentGroupTagsTemplateCell, @@ -199,8 +215,8 @@ export class AgentGroupListComponent { name: '', prop: 'actions', - flexGrow: 2, - canAutoResize: true, + flexGrow: 2.5, + resizeable: false, minWidth: 150, sortable: false, cellTemplate: this.actionsTemplateCell, @@ -241,7 +257,29 @@ export class AgentGroupListComponent } }); } + onOpenDeleteSelected() { + const size = this.selected.length; + const elementName = "Agent Groups" + this.dialogService + .open(DeleteSelectedComponent, { + context: { size, elementName }, + autoFocus: true, + closeOnEsc: true, + }) + .onClose.subscribe((confirm) => { + if (confirm) { + this.deleteSelectedAgentGroups(); + this.orb.refreshNow(); + } + }); + } + deleteSelectedAgentGroups() { + this.selected.forEach((groupId) => { + this.agentGroupsService.deleteAgentGroup(groupId).subscribe(); + }) + this.notificationsService.success('All selected Groups delete requests succeeded', ''); + } openDetailsModal(row: any) { this.dialogService .open(AgentGroupDetailsComponent, { @@ -263,4 +301,23 @@ export class AgentGroupListComponent closeOnEsc: true, }); } + public onCheckboxChange(event: any, row: any): void { + + if (this.getChecked(row) === false) { + this.selected.push(row.id); + } + else { + for (let i = 0; i < this.selected.length; i++) { + if (this.selected[i] === row.id) { + this.selected.splice(i, 1); + break; + } + } + } + } + + public getChecked(row: any): boolean { + const item = this.selected.filter((e) => e === row.id); + return item.length > 0 ? true : false; + } } diff --git a/ui/src/app/pages/pages.module.ts b/ui/src/app/pages/pages.module.ts index 3cb52999f..8b001b6c5 100644 --- a/ui/src/app/pages/pages.module.ts +++ b/ui/src/app/pages/pages.module.ts @@ -70,6 +70,7 @@ import { AgentViewComponent } from './fleet/agents/view/agent.view.component'; import { PagesRoutingModule } from './pages-routing.module'; import { PagesComponent } from './pages.component'; import { SinkViewComponent } from './sinks/view/sink.view.component'; +import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; @NgModule({ imports: [ @@ -156,6 +157,8 @@ import { SinkViewComponent } from './sinks/view/sink.view.component'; SinkViewComponent, // DEV SHOWCASE ShowcaseComponent, + // Delete Selected + DeleteSelectedComponent, ], providers: [NbDialogService, NbWindowService, SortPipe], entryComponents: [ConfirmationComponent], diff --git a/ui/src/app/pages/sinks/list/sink.list.component.html b/ui/src/app/pages/sinks/list/sink.list.component.html index c31321d25..8ac3a1764 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.html +++ b/ui/src/app/pages/sinks/list/sink.list.component.html @@ -16,7 +16,16 @@

{{ strings.list.header }}

- +
+ + +
@@ -114,3 +126,8 @@

{{ strings.list.header }}

+ + + + diff --git a/ui/src/app/pages/sinks/list/sink.list.component.scss b/ui/src/app/pages/sinks/list/sink.list.component.scss index c498ee772..e2cd816f6 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.scss +++ b/ui/src/app/pages/sinks/list/sink.list.component.scss @@ -202,3 +202,20 @@ mat-chip-list { transform: translateX(-70%); } } +.options { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; +} +.delete-selected { + color: #ffffff !important; + font-family: 'Montserrat', sans-serif; + font-weight: 600; + text-transform: none !important; + width: 90px; + background-color: #df316f !important; +} +input[type=checkbox] { + margin-left: 10px; +} \ No newline at end of file diff --git a/ui/src/app/pages/sinks/list/sink.list.component.ts b/ui/src/app/pages/sinks/list/sink.list.component.ts index 8b8ceb039..42ce74674 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.ts +++ b/ui/src/app/pages/sinks/list/sink.list.component.ts @@ -34,6 +34,7 @@ import { SinkDeleteComponent } from 'app/pages/sinks/delete/sink.delete.componen import { SinkDetailsComponent } from 'app/pages/sinks/details/sink.details.component'; import { STRINGS } from 'assets/text/strings'; import { Observable } from 'rxjs'; +import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; @Component({ selector: 'ngx-sink-list-component', @@ -49,6 +50,8 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes loading = false; + selected: any[] = []; + // templates @ViewChild('sinkNameTemplateCell') sinkNameTemplateCell: TemplateRef; @@ -58,6 +61,8 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes @ViewChild('sinkActionsTemplateCell') actionsTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + tableSorts = [ { prop: 'name', @@ -86,6 +91,7 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes private orb: OrbService, private filters: FilterService, ) { + this.selected = []; this.sinks$ = this.orb.getSinkListView(); this.filters$ = this.filters.getFilters(); @@ -152,42 +158,51 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes ngAfterViewInit() { this.orb.refreshNow(); this.columns = [ + { + name: '', + prop: 'checkbox', + flexGrow: 0.5, + minWidth: 62, + canAutoResize: true, + sortable: false, + cellTemplate: this.checkboxTemplateCell, + }, { prop: 'name', name: 'Name', canAutoResize: true, resizeable: false, - flexGrow: 2, + flexGrow: 3, minWidth: 150, cellTemplate: this.sinkNameTemplateCell, }, { - prop: 'description', - name: 'Description', + prop: 'state', + name: 'Status', resizeable: false, - minWidth: 150, flexGrow: 2, - cellTemplate: this.sinkNameTemplateCell, + cellTemplate: this.sinkStateTemplateCell, }, { prop: 'backend', name: 'Backend', resizeable: false, minWidth: 120, - flexGrow: 1, + flexGrow: 2, cellTemplate: this.sinkNameTemplateCell, }, { - prop: 'state', - name: 'Status', + prop: 'description', + name: 'Description', resizeable: false, - flexGrow: 1, - cellTemplate: this.sinkStateTemplateCell, + minWidth: 150, + flexGrow: 5, + cellTemplate: this.sinkNameTemplateCell, }, { prop: 'tags', name: 'Tags', - flexGrow: 2, + flexGrow: 5, resizeable: false, cellTemplate: this.sinkTagsTemplateCell, comparator: (a, b) => @@ -206,7 +221,7 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes minWidth: 150, resizeable: false, sortable: false, - flexGrow: 2, + flexGrow: 1.75, cellTemplate: this.actionsTemplateCell, }, ]; @@ -247,7 +262,29 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes } }); } + onOpenDeleteSelected() { + const size = this.selected.length; + const elementName = "Sinks" + this.dialogService + .open(DeleteSelectedComponent, { + context: { size, elementName }, + autoFocus: true, + closeOnEsc: true, + }) + .onClose.subscribe((confirm) => { + if (confirm) { + this.deleteSelectedSinks(); + this.orb.refreshNow(); + } + }); + } + deleteSelectedSinks() { + this.selected.forEach((sinkId) => { + this.sinkService.deleteSink(sinkId).subscribe(); + }) + this.notificationsService.success('All selected Sinks delete requests succeeded', ''); + } openDetailsModal(row: any) { this.dialogService .open(SinkDetailsComponent, { @@ -263,4 +300,24 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes } filterByInactive = (sink) => sink.state === 'inactive'; + + public onCheckboxChange(event: any, row: any): void { + + if (this.getChecked(row) === false) { + this.selected.push(row.id); + } + else { + for (let i = 0; i < this.selected.length; i++) { + if (this.selected[i] === row.id) { + this.selected.splice(i, 1); + break; + } + } + } + } + + public getChecked(row: any): boolean { + const item = this.selected.filter((e) => e === row.id); + return item.length > 0 ? true : false; + } } diff --git a/ui/src/app/shared/components/delete/delete.selected.component.html b/ui/src/app/shared/components/delete/delete.selected.component.html new file mode 100644 index 000000000..8ff3cb91b --- /dev/null +++ b/ui/src/app/shared/components/delete/delete.selected.component.html @@ -0,0 +1,34 @@ + + + Delete {{ elementName }} Confirmation + + + +

Are you sure you want to delete a total of {{ size }} {{ elementName }}? This action cannot be undone.

+

*To confirm, type the amount of {{ elementName }} to be delete.

+ + + {{size}} + +
+ + + +
\ No newline at end of file diff --git a/ui/src/app/shared/components/delete/delete.selected.component.scss b/ui/src/app/shared/components/delete/delete.selected.component.scss new file mode 100644 index 000000000..088204ba9 --- /dev/null +++ b/ui/src/app/shared/components/delete/delete.selected.component.scss @@ -0,0 +1,51 @@ +nb-card { + max-width: 38rem; + + nb-card-header { + background: #232940; + color: #969fb9; + } + + nb-card-body { + margin: 2rem 3rem; + padding: 0; + + p { + color: #969fb9; + } + + .ns1-red { + color: #df316f; + } + } + + nb-card-footer { + text-align: center; + padding: 1.5rem; + } + } + + // ORB + ::ng-deep { + .orb-close-dialog { + background-color: #23294000; + border-radius: 4px; + display: contents; + float: right; + + > span { + float: right; + font-size: 1.5rem; + color: #3089fc; + font-weight: 900; + } + } + + .orb-sink-delete-warning-button:not(.btn-disabled) { + background-color: #df316f !important; + color: #ffffff !important; + } + } + .ns1red { + color: #df316f; + } \ No newline at end of file diff --git a/ui/src/app/shared/components/delete/delete.selected.component.ts b/ui/src/app/shared/components/delete/delete.selected.component.ts new file mode 100644 index 000000000..81521a53d --- /dev/null +++ b/ui/src/app/shared/components/delete/delete.selected.component.ts @@ -0,0 +1,34 @@ +import { Component, Input } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; +import { STRINGS } from 'assets/text/strings'; + +@Component({ + selector: 'ngx-delete-selected-component', + templateUrl: './delete.selected.component.html', + styleUrls: ['./delete.selected.component.scss'], +}) + +export class DeleteSelectedComponent { + strings = STRINGS.agents; + @Input() size: Number; + @Input() elementName: String; + + validationInput: Number; + + constructor( + protected dialogRef: NbDialogRef, + ) { + } + + onDelete() { + this.dialogRef.close(true); + } + + onClose() { + this.dialogRef.close(false); + } + + isEnabled(): boolean { + return this.validationInput === this.size; + } +} \ No newline at end of file From b2c288c9259411633e5de0c53e9d2161f56b73b8 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Thu, 15 Jun 2023 16:05:13 -0300 Subject: [PATCH 043/115] feat(orb-ui): expose the orb version on agent list page (#2415) --- .../agents/list/agent.list.component.html | 10 ++++++ .../fleet/agents/list/agent.list.component.ts | 32 +++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.html b/ui/src/app/pages/fleet/agents/list/agent.list.component.html index 29dcab57f..c6cf445ba 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.html +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.html @@ -170,3 +170,13 @@

All Agents

+ + + + {{ value }} + \ No newline at end of file diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 76ca7544c..537cb2ffb 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -31,6 +31,7 @@ import { AgentDetailsComponent } from 'app/pages/fleet/agents/details/agent.deta import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; import { STRINGS } from 'assets/text/strings'; import { Observable } from 'rxjs'; +import { map, tap } from 'rxjs/operators'; import { AgentResetComponent } from '../reset/agent.reset.component'; @Component({ @@ -69,6 +70,8 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe @ViewChild('agentLastActivityTemplateCell') agentLastActivityTemplateCell: TemplateRef; + @ViewChild('agentVersionTemplateCell') agentVersionTemplateCell: TemplateRef; + tableSorts = [ { prop: 'name', @@ -99,7 +102,23 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe ) { this.isResetting = false; this.selected = []; - this.agents$ = this.orb.getAgentListView(); + this.agents$ = this.orb.getAgentListView().pipe( + map(agents => { + return agents.map(agent => { + let version: string; + if (agent.state !== 'new') { + version = agent.agent_metadata.orb_agent.version; + } else { + version = '-'; + } + return { + ...agent, + version, + }; + }); + }) + ); + this.columns = []; this.filters$ = this.filters.getFilters(); @@ -172,7 +191,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe }, { prop: 'name', - flexGrow: 4, + flexGrow: 5, canAutoResize: true, minWidth: 150, name: 'Name', @@ -209,6 +228,15 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe .join(','), ), }, + { + prop: 'version', + flexGrow: 5, + minWidth: 150, + canAutoResize: true, + name: 'Version', + sortable: false, + cellTemplate: this.agentVersionTemplateCell, + }, { prop: 'ts_last_hb', flexGrow: 4, From f1bba5bb539a9fe74cefa744e872117c5825b3da Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Mon, 19 Jun 2023 13:59:46 -0300 Subject: [PATCH 044/115] feat(orb-ui): #686 list of the elements to be deleted in the confirmation modal (#2416) --- .../list/agent.policy.list.component.ts | 20 ++++++++------ .../fleet/agents/list/agent.list.component.ts | 10 ++++--- .../groups/list/agent.group.list.component.ts | 20 ++++++++------ .../pages/sinks/list/sink.list.component.ts | 21 +++++++++------ .../delete/delete.selected.component.html | 13 +++++---- .../delete/delete.selected.component.scss | 27 ++++++++++++++----- .../delete/delete.selected.component.ts | 4 +-- 7 files changed, 74 insertions(+), 41 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index f1ffe6959..ba3340f8c 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -310,11 +310,11 @@ export class AgentPolicyListComponent }); } onOpenDeleteSelected() { - const size = this.selected.length; const elementName = "Policies" + const selected = this.selected; this.dialogService .open(DeleteSelectedComponent, { - context: { size, elementName }, + context: { selected, elementName }, autoFocus: true, closeOnEsc: true, }) @@ -327,19 +327,23 @@ export class AgentPolicyListComponent } deleteSelectedAgentsPolicy() { - this.selected.forEach((policyId) => { - this.agentPoliciesService.deleteAgentPolicy(policyId).subscribe(); + this.selected.forEach((policy) => { + this.agentPoliciesService.deleteAgentPolicy(policy.id).subscribe(); }) this.notificationsService.success('All selected Policies delete requests succeeded', ''); } public onCheckboxChange(event: any, row: any): void { - + const policySelected = { + id: row.id, + name: row.name, + usage: row.policy_usage, + } if (this.getChecked(row) === false) { - this.selected.push(row.id); + this.selected.push(policySelected); } else { for (let i = 0; i < this.selected.length; i++) { - if (this.selected[i] === row.id) { + if (this.selected[i].id === row.id) { this.selected.splice(i, 1); break; } @@ -349,7 +353,7 @@ export class AgentPolicyListComponent } public getChecked(row: any): boolean { - const item = this.selected.filter((e) => e === row.id); + const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } } diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 537cb2ffb..3cb2f77f8 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -261,15 +261,16 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe public onCheckboxChange(event: any, row: any): void { let selectedAgent = { - id: "", + id: row.id, resetable: true, + name: row.name, + state: row.state, } if (this.getChecked(row) === false) { let resetable = true; if (row.state === 'new' || row.state === 'offline') { resetable = false; } - selectedAgent.id = row.id; selectedAgent.resetable = resetable; this.selected.push(selectedAgent); } else { @@ -282,6 +283,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe } const reset = this.selected.filter((e) => e.resetable === false); this.canResetAgents = reset.length > 0 ? true : false; + console.log(this.selected); } @@ -332,11 +334,11 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe }); } onOpenDeleteSelected() { - const size = this.selected.length; + const selected = this.selected; const elementName = "Agents" this.dialogService .open(DeleteSelectedComponent, { - context: { size, elementName }, + context: { selected, elementName }, autoFocus: true, closeOnEsc: true, }) diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts index a55d7b3d5..7766f8311 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts @@ -258,11 +258,11 @@ export class AgentGroupListComponent }); } onOpenDeleteSelected() { - const size = this.selected.length; + const selected = this.selected; const elementName = "Agent Groups" this.dialogService .open(DeleteSelectedComponent, { - context: { size, elementName }, + context: { selected, elementName }, autoFocus: true, closeOnEsc: true, }) @@ -275,8 +275,8 @@ export class AgentGroupListComponent } deleteSelectedAgentGroups() { - this.selected.forEach((groupId) => { - this.agentGroupsService.deleteAgentGroup(groupId).subscribe(); + this.selected.forEach((group) => { + this.agentGroupsService.deleteAgentGroup(group.id).subscribe(); }) this.notificationsService.success('All selected Groups delete requests succeeded', ''); } @@ -302,22 +302,26 @@ export class AgentGroupListComponent }); } public onCheckboxChange(event: any, row: any): void { - + let selectedGroup = { + id: row.id, + name: row.name, + } if (this.getChecked(row) === false) { - this.selected.push(row.id); + this.selected.push(selectedGroup); } else { for (let i = 0; i < this.selected.length; i++) { - if (this.selected[i] === row.id) { + if (this.selected[i].id === row.id) { this.selected.splice(i, 1); break; } } } + console.log(this.selected); } public getChecked(row: any): boolean { - const item = this.selected.filter((e) => e === row.id); + const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } } diff --git a/ui/src/app/pages/sinks/list/sink.list.component.ts b/ui/src/app/pages/sinks/list/sink.list.component.ts index 42ce74674..393efecb7 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.ts +++ b/ui/src/app/pages/sinks/list/sink.list.component.ts @@ -263,11 +263,11 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes }); } onOpenDeleteSelected() { - const size = this.selected.length; + const selected = this.selected; const elementName = "Sinks" this.dialogService .open(DeleteSelectedComponent, { - context: { size, elementName }, + context: { selected, elementName }, autoFocus: true, closeOnEsc: true, }) @@ -280,8 +280,8 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes } deleteSelectedSinks() { - this.selected.forEach((sinkId) => { - this.sinkService.deleteSink(sinkId).subscribe(); + this.selected.forEach((sink) => { + this.sinkService.deleteSink(sink.id).subscribe(); }) this.notificationsService.success('All selected Sinks delete requests succeeded', ''); } @@ -302,22 +302,27 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes filterByInactive = (sink) => sink.state === 'inactive'; public onCheckboxChange(event: any, row: any): void { - + const sinkSelected = { + id: row.id, + name: row.name, + state: row.state, + } if (this.getChecked(row) === false) { - this.selected.push(row.id); + this.selected.push(sinkSelected); } else { for (let i = 0; i < this.selected.length; i++) { - if (this.selected[i] === row.id) { + if (this.selected[i].id === row.id) { this.selected.splice(i, 1); break; } } } + console.log(this.selected); } public getChecked(row: any): boolean { - const item = this.selected.filter((e) => e === row.id); + const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } } diff --git a/ui/src/app/shared/components/delete/delete.selected.component.html b/ui/src/app/shared/components/delete/delete.selected.component.html index 8ff3cb91b..ae41989aa 100644 --- a/ui/src/app/shared/components/delete/delete.selected.component.html +++ b/ui/src/app/shared/components/delete/delete.selected.component.html @@ -10,16 +10,19 @@ -

Are you sure you want to delete a total of {{ size }} {{ elementName }}? This action cannot be undone.

-

*To confirm, type the amount of {{ elementName }} to be delete.

+

Are you sure you want to delete a total of {{ selected?.length }} {{ elementName }}? This action cannot be undone.

+
+ {{ item.name }} {{ item.state }} {{ item.usage }} +
+

*To confirm, type the amount of {{ elementName }} to be delete.

+ placeholder="{{selected?.length }}" [(ngModel)]="validationInput"> - {{size}} + {{selected?.length}}
@@ -28,7 +31,7 @@ class="orb-sink-delete-warning-button" [disabled]="!isEnabled()" (click)="onDelete()"> - I Understand, Delete All {{ size }} {{ elementName }} Selected. + I Understand, Delete All {{ selected?.length }} {{ elementName }} Selected. \ No newline at end of file diff --git a/ui/src/app/shared/components/delete/delete.selected.component.scss b/ui/src/app/shared/components/delete/delete.selected.component.scss index 088204ba9..00c2942e0 100644 --- a/ui/src/app/shared/components/delete/delete.selected.component.scss +++ b/ui/src/app/shared/components/delete/delete.selected.component.scss @@ -14,9 +14,7 @@ nb-card { color: #969fb9; } - .ns1-red { - color: #df316f; - } + } nb-card-footer { @@ -46,6 +44,23 @@ nb-card { color: #ffffff !important; } } - .ns1red { - color: #df316f; - } \ No newline at end of file + .orb-service- { + &new { + color: #9b51e0; + } + &online, &healthy, &in, &active { + color: #6fcf97; + } + &stale, &none, &unknown, ¬ { + color: #f2994a; + } + &error, &failure { + color: #df316f; + } + &offline { + color: #969fb9; + } + &warning { + color: #f2dc4a; + } + } diff --git a/ui/src/app/shared/components/delete/delete.selected.component.ts b/ui/src/app/shared/components/delete/delete.selected.component.ts index 81521a53d..16d55fd32 100644 --- a/ui/src/app/shared/components/delete/delete.selected.component.ts +++ b/ui/src/app/shared/components/delete/delete.selected.component.ts @@ -10,7 +10,7 @@ import { STRINGS } from 'assets/text/strings'; export class DeleteSelectedComponent { strings = STRINGS.agents; - @Input() size: Number; + @Input() selected: any[] = []; @Input() elementName: String; validationInput: Number; @@ -29,6 +29,6 @@ export class DeleteSelectedComponent { } isEnabled(): boolean { - return this.validationInput === this.size; + return this.validationInput === this.selected.length; } } \ No newline at end of file From 1669b1c5c325409546c4602806daa247ffb16140 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 20 Jun 2023 15:12:05 -0300 Subject: [PATCH 045/115] fix: remove useless files (#2420) fix: remove useless files (#2420) --- orb_tests/chromedriver.log | 4 - orb_tests/nightwatch.conf.js | 52 - orb_tests/package-lock.json | 2736 ----------------- orb_tests/package.json | 24 - orb_tests/page_objects/accountRegister.js | 39 - orb_tests/page_objects/agent_groups.js | 216 -- orb_tests/page_objects/agents.js | 221 -- orb_tests/page_objects/login.js | 33 - orb_tests/page_objects/register.js | 28 - orb_tests/page_objects/sinks.js | 167 - orb_tests/page_objects/topbar.js | 15 - orb_tests/tests/agents/1goToAgentsPage.js | 30 - orb_tests/tests/agents/2agent_page.js | 54 - orb_tests/tests/agents/3newAgent.js | 41 - .../tests/agents/4agentsVisualization.js | 30 - orb_tests/tests/agents/5agentEdit.js | 35 - orb_tests/tests/agents/9agentsDelete.js | 33 - .../agents_groups/1goToAgentGroupPage.js | 28 - orb_tests/tests/agents_groups/2list-view.js | 30 - .../agents_groups/3newAgentWithDescription.js | 35 - .../4newAgentGroupsWithoutDescription.js | 32 - .../agents_groups/5agentGroupVisualization.js | 30 - .../tests/agents_groups/6agentGroupEdit.js | 35 - .../tests/agents_groups/7removeAgentGroup.js | 36 - orb_tests/tests/agents_groups/new_refactor.js | 80 - orb_tests/tests/login/1invalid_regex_email.js | 14 - orb_tests/tests/login/2layout.js | 20 - orb_tests/tests/login/3password_length.js | 14 - orb_tests/tests/login/4password_required.js | 14 - orb_tests/tests/login/5successful.js | 18 - orb_tests/tests/login/6without_email.js | 14 - orb_tests/tests/login/7wrong_combination.js | 29 - orb_tests/tests/register/creatAccount.js | 19 - orb_tests/tests/sinks/1goToSinkPage.js | 30 - orb_tests/tests/sinks/2newSink.js | 36 - orb_tests/tests/sinks/3duplicateSink.js | 38 - orb_tests/tests/sinks/4sinkVisualization.js | 32 - .../sinks/5sinkVisualizationAndEditDesc.js | 38 - orb_tests/tests/sinks/6sinkVisuAndEditRH.js | 39 - .../sinks/7sinkVisualizationAndEditPass.js | 39 - orb_tests/tests/sinks/8sinkVisuAndEditTags.js | 42 - .../tests/sinks/90sinkVisuAndEditUsername.js | 39 - .../tests/sinks/91sinkEditDescription.js | 33 - orb_tests/tests/sinks/92sinkEditRH.js | 34 - orb_tests/tests/sinks/93sinkEditUsername.js | 34 - orb_tests/tests/sinks/94sinkEditPassword.js | 32 - orb_tests/tests/sinks/95sinkEditTags.js | 35 - orb_tests/tests/sinks/96sinkEditAll.js | 44 - orb_tests/tests/sinks/97removeSink.js | 34 - 49 files changed, 4785 deletions(-) delete mode 100644 orb_tests/chromedriver.log delete mode 100644 orb_tests/nightwatch.conf.js delete mode 100644 orb_tests/package-lock.json delete mode 100644 orb_tests/package.json delete mode 100644 orb_tests/page_objects/accountRegister.js delete mode 100644 orb_tests/page_objects/agent_groups.js delete mode 100644 orb_tests/page_objects/agents.js delete mode 100644 orb_tests/page_objects/login.js delete mode 100644 orb_tests/page_objects/register.js delete mode 100644 orb_tests/page_objects/sinks.js delete mode 100644 orb_tests/page_objects/topbar.js delete mode 100644 orb_tests/tests/agents/1goToAgentsPage.js delete mode 100644 orb_tests/tests/agents/2agent_page.js delete mode 100644 orb_tests/tests/agents/3newAgent.js delete mode 100644 orb_tests/tests/agents/4agentsVisualization.js delete mode 100644 orb_tests/tests/agents/5agentEdit.js delete mode 100644 orb_tests/tests/agents/9agentsDelete.js delete mode 100644 orb_tests/tests/agents_groups/1goToAgentGroupPage.js delete mode 100644 orb_tests/tests/agents_groups/2list-view.js delete mode 100644 orb_tests/tests/agents_groups/3newAgentWithDescription.js delete mode 100644 orb_tests/tests/agents_groups/4newAgentGroupsWithoutDescription.js delete mode 100644 orb_tests/tests/agents_groups/5agentGroupVisualization.js delete mode 100644 orb_tests/tests/agents_groups/6agentGroupEdit.js delete mode 100644 orb_tests/tests/agents_groups/7removeAgentGroup.js delete mode 100644 orb_tests/tests/agents_groups/new_refactor.js delete mode 100644 orb_tests/tests/login/1invalid_regex_email.js delete mode 100644 orb_tests/tests/login/2layout.js delete mode 100644 orb_tests/tests/login/3password_length.js delete mode 100644 orb_tests/tests/login/4password_required.js delete mode 100644 orb_tests/tests/login/5successful.js delete mode 100644 orb_tests/tests/login/6without_email.js delete mode 100644 orb_tests/tests/login/7wrong_combination.js delete mode 100644 orb_tests/tests/register/creatAccount.js delete mode 100644 orb_tests/tests/sinks/1goToSinkPage.js delete mode 100644 orb_tests/tests/sinks/2newSink.js delete mode 100644 orb_tests/tests/sinks/3duplicateSink.js delete mode 100644 orb_tests/tests/sinks/4sinkVisualization.js delete mode 100644 orb_tests/tests/sinks/5sinkVisualizationAndEditDesc.js delete mode 100644 orb_tests/tests/sinks/6sinkVisuAndEditRH.js delete mode 100644 orb_tests/tests/sinks/7sinkVisualizationAndEditPass.js delete mode 100644 orb_tests/tests/sinks/8sinkVisuAndEditTags.js delete mode 100644 orb_tests/tests/sinks/90sinkVisuAndEditUsername.js delete mode 100644 orb_tests/tests/sinks/91sinkEditDescription.js delete mode 100644 orb_tests/tests/sinks/92sinkEditRH.js delete mode 100644 orb_tests/tests/sinks/93sinkEditUsername.js delete mode 100644 orb_tests/tests/sinks/94sinkEditPassword.js delete mode 100644 orb_tests/tests/sinks/95sinkEditTags.js delete mode 100644 orb_tests/tests/sinks/96sinkEditAll.js delete mode 100644 orb_tests/tests/sinks/97removeSink.js diff --git a/orb_tests/chromedriver.log b/orb_tests/chromedriver.log deleted file mode 100644 index ca2792f73..000000000 --- a/orb_tests/chromedriver.log +++ /dev/null @@ -1,4 +0,0 @@ -Starting ChromeDriver 93.0.4577.15 (660fc11082ba57405eca2e8c49c3e1af756fbfae-refs/branch-heads/4577@{#203}) on port 9515 -Only local connections are allowed. -Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe. -ChromeDriver was started successfully. diff --git a/orb_tests/nightwatch.conf.js b/orb_tests/nightwatch.conf.js deleted file mode 100644 index bdc32edb9..000000000 --- a/orb_tests/nightwatch.conf.js +++ /dev/null @@ -1,52 +0,0 @@ -const chromedriver = require('chromedriver'); - -const testUrl = 'http://localhost:4200'; -const defaultTimeout = 15000; - -module.exports = { - src_folders : ['tests'], - page_objects_path : './page_objects', - skip_testcases_on_fail: false, - - webdriver: { - start_process: true, - }, - - test_settings: { - default: { - launch_url: testUrl, - globals: { - waitForConditionTimeout: defaultTimeout, - }, - webdriver: { - server_path: chromedriver.path, - port: 9515, - }, - desiredCapabilities: { - browserName: 'chrome', - } - }, - - headless: { - launch_url: testUrl, - globals: { - waitForConditionTimeout: defaultTimeout, - }, - webdriver: { - server_path: chromedriver.path, - port: 9515, - }, - desiredCapabilities: { - browserName: 'chrome', - chromeOptions: { - w3c: false, - args: ['--headless', '--no-sandbox', '--disable-dev-shm-usage'], - } - } - }, - - beta: { - launch_url: "https://beta.orb.live" - } - } -} diff --git a/orb_tests/package-lock.json b/orb_tests/package-lock.json deleted file mode 100644 index b503d718b..000000000 --- a/orb_tests/package-lock.json +++ /dev/null @@ -1,2736 +0,0 @@ -{ - "name": "orb_tests", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@testim/chrome-version": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.0.7.tgz", - "integrity": "sha512-8UT/J+xqCYfn3fKtOznAibsHpiuDshCb0fwgWxRazTT19Igp9ovoXMPhXyLD6m3CKQGTMHgqoxaFfMWaL40Rnw==", - "dev": true - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/node": { - "version": "16.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.1.tgz", - "integrity": "sha512-4/Z9DMPKFexZj/Gn3LylFgamNKHm4K3QDi0gz9B26Uk0c8izYf97B5fxfpspMNkWlFupblKM/nV8+NA9Ffvr+w==", - "dev": true, - "optional": true - }, - "@types/yauzl": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", - "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, - "optional": true, - "requires": { - "@types/node": "*" - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "requires": { - "tslib": "^2.0.1" - } - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dev": true, - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chai-nightwatch": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.4.1.tgz", - "integrity": "sha512-s2put5cFhG8Hw+6Po3R8QZ0ctsDmcaIh7+l9Fu3RcLCfosfQffT3mcFSq2jmXEQk0pmwo/PuXvYMO87MRlyqxg==", - "dev": true, - "requires": { - "assertion-error": "1.0.0", - "deep-eql": "0.1.3" - }, - "dependencies": { - "assertion-error": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", - "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", - "dev": true - } - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chromedriver": { - "version": "93.0.1", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-93.0.1.tgz", - "integrity": "sha512-KDzbW34CvQLF5aTkm3b5VdlTrvdIt4wEpCzT2p4XJIQWQZEPco5pNce7Lu9UqZQGkhQ4mpZt4Ky6NKVyIS2N8A==", - "dev": true, - "requires": { - "@testim/chrome-version": "^1.0.7", - "axios": "^0.21.2", - "del": "^6.0.0", - "extract-zip": "^2.0.1", - "https-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.1.0", - "tcp-port-used": "^1.0.1" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", - "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "degenerator": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.1.tgz", - "integrity": "sha512-LFsIFEeLPlKvAKXu7j3ssIG6RT0TbI7/GhsqrI0DnHASEQjXQ0LUSYcjJteGgRGmZbl1TnMSxpNQIAiJ7Du5TQ==", - "dev": true, - "requires": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.3" - } - }, - "del": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz", - "integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==", - "dev": true, - "requires": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dotenv": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz", - "integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ejs": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", - "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", - "dev": true, - "requires": { - "jake": "^10.6.1" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "envinfo": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", - "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", - "dev": true - }, - "es-abstract": { - "version": "1.18.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.6.tgz", - "integrity": "sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-string": "^1.0.7", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "dependencies": { - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-uri-to-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", - "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", - "dev": true - }, - "filelist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", - "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "get-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", - "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, - "is2": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.7.tgz", - "integrity": "sha512-4vBQoURAXC6hnLFxD4VW7uc04XiwTTl/8ydYJxKvPwkWQrSjInkuM5VZVg6BGr1/natq69zDuvO9lGpLClJqvA==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "ip-regex": "^4.1.0", - "is-url": "^1.2.4" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "jake": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", - "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", - "dev": true, - "requires": { - "async": "0.9.x", - "chalk": "^2.4.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" - } - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", - "dev": true - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "dev": true, - "requires": { - "lodash._arraycopy": "^3.0.0", - "lodash._arrayeach": "^3.0.0", - "lodash._baseassign": "^3.0.0", - "lodash._basefor": "^3.0.0", - "lodash.isarray": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash.clone": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-3.0.3.tgz", - "integrity": "sha1-hGiMc9MrWpDKJWFpY/GJJSqZcEM=", - "dev": true, - "requires": { - "lodash._baseclone": "^3.0.0", - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.defaultsdeep": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", - "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "dev": true - }, - "mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "dev": true, - "requires": { - "mime-db": "1.49.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mkpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz", - "integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0=", - "dev": true - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true - }, - "nightwatch": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-1.7.11.tgz", - "integrity": "sha512-yV795EBXZ/myeoCvBtjC/QwvIprxF7SKh0XCeFnpoOtWXDb0yv+ATLRipKGfp+avyGtagqq38ucA4Uh6WPcnhQ==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "chai-nightwatch": "^0.4.0", - "ci-info": "^2.0.0", - "didyoumean": "^1.2.1", - "dotenv": "7.0.0", - "ejs": "^3.1.6", - "envinfo": "^7.5.1", - "lodash.clone": "3.0.3", - "lodash.defaultsdeep": "^4.6.1", - "lodash.merge": "^4.6.2", - "minimatch": "3.0.4", - "minimist": "^1.2.5", - "mkpath": "1.0.0", - "mocha": "6.2.3", - "ora": "^4.0.3", - "proxy-agent": "^5.0.0", - "request": "^2.88.2", - "request-promise": "^4.2.5", - "semver": "^6.3.0", - "strip-ansi": "^6.0.0" - } - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", - "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "ora": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.1.1.tgz", - "integrity": "sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==", - "dev": true, - "requires": { - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.2.0", - "is-interactive": "^1.0.0", - "log-symbols": "^3.0.0", - "mute-stream": "0.0.8", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pac-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", - "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - } - }, - "pac-resolver": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.0.tgz", - "integrity": "sha512-H+/A6KitiHNNW+bxBKREk2MCGSxljfqRX76NjummWEYIat7ldVXRU3dhRIE3iXZ0nvGBk6smv3nntxKkzRL8NA==", - "dev": true, - "requires": { - "degenerator": "^3.0.1", - "ip": "^1.1.5", - "netmask": "^2.0.1" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", - "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", - "dev": true, - "requires": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", - "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, - "request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz", - "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - } - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tcp-port-used": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", - "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", - "dev": true, - "requires": { - "debug": "4.3.1", - "is2": "^2.0.6" - }, - "dependencies": { - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - } - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - } - } - }, - "vm2": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.3.tgz", - "integrity": "sha512-smLS+18RjXYMl9joyJxMNI9l4w7biW8ilSDaVRvFBDwOH8P0BK1ognFQTpg0wyQ6wIKLTblHJvROW692L/E53Q==" - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=", - "dev": true - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/orb_tests/package.json b/orb_tests/package.json deleted file mode 100644 index 117cbbdd2..000000000 --- a/orb_tests/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "orb_tests", - "version": "1.0.0", - "main": "index.js", - "scripts": { - "test": "nightwatch", - "test:beta": "nightwatch --env=beta", - "test:ci": "nightwatch --env=headless" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "chromedriver": "^93.0.1", - "nightwatch": "^1.7.11" - }, - "directories": { - "test": "tests" - }, - "keywords": [], - "dependencies": { - "vm2": "^3.9.3" - }, - "description": "" -} diff --git a/orb_tests/page_objects/accountRegister.js b/orb_tests/page_objects/accountRegister.js deleted file mode 100644 index afb1f1a5c..000000000 --- a/orb_tests/page_objects/accountRegister.js +++ /dev/null @@ -1,39 +0,0 @@ -var registerCommands = { - orbRegister: function() { - return this.verify.visible('@register', "'Register' option is being displayed") - .click('@register') - //bug remove this duplicated - .click('@register') - .waitForElementVisible('@fullNameInput', "'Full name' field is visible") - .verify.containsText("[for='input-name']", "Full name:", "'Full name:' description is correctly written") - .setValue('@fullNameInput', 'tester') - .waitForElementVisible('@username', "'Email address' field is visible") - .verify.containsText("[for='input-email']", "Email address:", "'Email Address' description is correctly written") - .setValue('@username', 'tester@email.com') - .waitForElementVisible('@pwd', "'Password field is visible") - .verify.containsText("[for='input-password']", "Password:", "'Password' description is correctly written") - .setValue('@pwd', '12345678') - .waitForElementVisible('@confirmPassword', "'Repeat password' field is visible") - .verify.containsText("[for='input-re-password']", "Repeat password:", "'Repeat password' description is correctly written") - .setValue('@confirmPassword', '12345678') - .waitForElementVisible('@submit', "'Register' button is visible") - .verify.containsText('@submit', "REGISTER", "'REGISTER' text is correctly written") - .verify.attributeEquals('@submit','aria-disabled', 'false', "'Register' button is clickable") - .pause(2000) - .click('@submit') - .pause(2000) - - }, -} -module.exports = { - url: '/auth/register', - commands: [registerCommands], - elements: { - register: '.text-link', - fullNameInput:'input[id=input-name]', - username: 'input[id=input-email]', - pwd: 'input[id=input-password]', - confirmPassword: 'input[id=input-re-password]', - submit: '.appearance-filled' - - }} diff --git a/orb_tests/page_objects/agent_groups.js b/orb_tests/page_objects/agent_groups.js deleted file mode 100644 index bd4d04925..000000000 --- a/orb_tests/page_objects/agent_groups.js +++ /dev/null @@ -1,216 +0,0 @@ -var commands = { - - new: function() { - return this.navigate() - .waitForElementVisible('@newButton', 10000, "New Agent Groups button is visible") - .click('@newButton') - }, - - fillInput: function (selector, data) { - return this.setValue(selector, data) - }, - - - listView: function() { - return this.verify.containsText('@agentGroupList','Agent Groups List', "Agent Groups view is named 'Agent Groups List'") - .verify.containsText('@agentGroupAll', 'All Agent Groups', "Agent Groups Header is 'All Agent Groups'") - .verify.containsText('@agentPath', 'Fleet Management', "Agent Groups is inherited from Fleet Management") - .verify.visible('@new', "'New Agent Group' button is visible") - .verify.visible('.flex-column', "Agent Groups table view is visible") - .verify.visible("@table", "Agent Groups body table view is visible") - .verify.visible("@filter", "Filter type is visible") - .verify.visible("@search", "Search by filter is visible") - }, - - agentGroupCreationPage: function() { - return this.verify.containsText('.header', 'Agent Group Details', "Header is 'Agent Group Details'") - .verify.containsText('.header', 'This is how you will be able to easily identify your Agent Group', "Help text about name is correctly written") - .verify.containsText('.header', 'Agent Group Tags', "'Agent Group Tags' is being displayed") - .verify.containsText('.header', 'Set the tags that will be used to group Agents', "Help text about tags is correctly written") - .verify.containsText('.header', 'Review & Confirm', "'Review & Confirm' is being displayed") - .verify.containsText('.step-content', 'Agent Group Name*', "'Agent Group Name*' field is being displayed") - .verify.containsText('.step-content', 'Agent Group Description', "'Agent Group Description' field is being displayed") - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - }, - - agentGroupEditPage: function() { - return this.verify.containsText('.xng-breadcrumb-trail', 'Edit Agent Group', "Header is 'Edit Agent Group'") - .verify.containsText('ngx-sink-add-component.ng-star-inserted > div:nth-child(1) > header:nth-child(1)', 'Edit Agent Groups', "Page description is 'Agent Groups'") - .verify.containsText('@editSinkHeader', 'Agent Group Details', "'Agent Group Details' is being displayed") - .verify.containsText('@editSinkHeader', 'This is how you will be able to easily identify your Agent Group', "Help text about name is correctly written") - .verify.containsText('@editSinkHeader', 'Agent Group Tags', "'Agent Group Tags' is being displayed") - .verify.containsText('@editSinkHeader', 'Set the tags that will be used to group Agents', "Help text about tags is correctly written") - .verify.containsText('@editSinkHeader', 'Review & Confirm', "'Review & Confirm' is being displayed") - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "Next button is enabled") - .verify.attributeEquals('@back','aria-disabled', 'false', "Cancel button is enabled") - }, - - agentGroupCreation: function(name, description, key, value, verify) { - return this.setValue('@newNameInput', name) - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .setValue('@newDescriptionInput', description) - .click('@next') - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@addTag','aria-disabled', 'true', "'Add tags' button is not enabled") - .setValue('@key', key) - .setValue('@value', value) - .verify.attributeEquals('@addTag','aria-disabled', 'false', "'Add tags' button is enabled") - .click('@addTag') - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .click('@next') - .verify.containsText('@agentGroupList','New Agent Group', 'Page header is "New Agent Group"') - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .click('@next') - .verify.containsText('span.title', verify, "Confirmation message is correctly displayed") - - - }, - - agentGroupsDelete: function() { - return this.verify.attributeEquals('button.orb-action-hover:nth-child(3)', 'aria-disabled', 'false', "'Remove' agent group button is enabled") - .click('button.orb-action-hover:nth-child(3)') - .verify.attributeEquals('@deleteAgentGroups','aria-disabled', 'true', "'Confirm agent group delete button is not enabled") - .verify.visible('@agentGroupsDeleteModal', "Delete agent groups modal is visible") - .verify.containsText('ngx-agent-group-delete-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-header:nth-child(1)', 'Delete Agent Group Confirmation', "Header of help text about delete confirmation is correctly written") - .verify.containsText('@agentGroupsDeleteModal', 'Are you sure you want to delete this Agent Group? This may cause Datasets which use this Agent Group to become invalid. This action cannot be undone.*', "Help text about delete confirmation is correctly written") - .verify.containsText('@agentGroupsDeleteModal', '*To confirm, type the Agent Group name exactly as it appears', "End of help text about delete confirmation is correctly written") - .getAttribute('.input-full-width', 'placeholder', function(result) {this.setValue('.input-full-width', result.value) }) - .verify.attributeEquals('@deleteAgentGroups','aria-disabled', 'false', "'Confirm agent group delete button is enabled") - .click('@deleteAgentGroups') - .verify.containsText('span.title', 'Agent Group successfully deleted', "Delete confirmation message is being displayed") - //bug .verify.containsText('.empty-row', 'No data to display') - - }, - - agentGroupVisualization: function() { - return this.verify.attributeEquals('button.orb-action-hover:nth-child(1)', 'aria-disabled', 'false', "'Visualization' button is visible") - .click('button.orb-action-hover:nth-child(1)') - .verify.elementPresent('.cdk-overlay-backdrop', "'Visualization' modal is visible") - .verify.containsText('.nb-card-medium > nb-card-header:nth-child(1)', 'Agent Group Details', "'Visualization' header is correctly written") - }, - - - choose_last_element: function() { - return this.waitForElementVisible('[class="orb-action-hover detail-button appearance-ghost size-medium status-basic shape-rectangle icon-start icon-end nb-transition"]', "Agent Group is visible") - .findElements('[class="orb-action-hover detail-button appearance-ghost size-medium status-basic shape-rectangle icon-start icon-end nb-transition"]', function(result) { - var agentGroupsView = result.value - this.elementIdClick(agentGroupsView[agentGroupsView.length-1].ELEMENT) - - - }) - }, - - addTags: function(key, value) { - return this.setValue('@key', key) - .setValue('@value', value) - .verify.attributeEquals('@addTag','aria-disabled', 'false', "'Add tags' button is enabled") - .click('@addTag') - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - - }, - - //bug : need to insert a test for checking if is possible to create two identicals tags - - agentGroupsEdit: function(name, description, key, value, key2, value2, verify) { - return this.verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .clearValue('@newNameInput') - .setValue('@newNameInput', name) - .clearValue('@newDescriptionInput') - .setValue('@newDescriptionInput', description) - .click('@next') - .click('.eva-close-outline') - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@addTag','aria-disabled', 'true', "'Add tags' button is not enabled") - .addTags(key, value) - .addTags(key2, value2) - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .click('@next') - .verify.containsText('@agentGroupList','Edit Agent Group', 'Page header is "Edit Agent Group"') - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .click('@next') - .verify.containsText('span.title', verify, "Confirmation message is correctly displayed") - }, - - - agentGroupCheck: function(name, description){ - return this.verify.containsText('div.row:nth-child(1) > div:nth-child(1) > p:nth-child(1)', 'Agent Group Name*', "View contain Agent Group Name Field") - .verify.containsText('div.row:nth-child(1) > div:nth-child(1) > p:nth-child(2)', name, "Name of Agent Group is correctly displayed") - .verify.containsText('div.row:nth-child(1) > div:nth-child(2) > p:nth-child(1)', 'Agent Group Description', "View contain Agent Group Description Field") - .verify.containsText('div.row:nth-child(1) > div:nth-child(2) > p:nth-child(2)', description, "Description of Agent Group is correctly displayed") - .verify.containsText('div.row:nth-child(2) > div:nth-child(1) > p:nth-child(1)', 'Date Created', "View contain Agent Group Date Created Field") - .verify.visible('div.row:nth-child(2) > div:nth-child(1) > p:nth-child(2)', "Agent Group Date Created is visible") - .verify.containsText('div.row:nth-child(2) > div:nth-child(2) > p:nth-child(1)', 'Matches Against', "View contain Agent Group Matches Against Field") - .verify.containsText('div.row:nth-child(2) > div:nth-child(2) > p:nth-child(2)', 'Agent(s)', "Matches of Agent Group is correctly displayed") - .verify.containsText('div.row:nth-child(3) > div:nth-child(1) > p:nth-child(1)', 'Tags*', "View contain Agent Group Tags Field") - .click('@close') - - }, - - - - countAgentGroups: function(browser) { - return this.getText('.page-count', function(result){ - //console.log('Value is:', result.value); - if (result.value == "0 total") { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - - browser.verify.containsText('.sink-info-accent', 'There are no Agent Groups yet.', "Info message of Agent Groups count is correctly displayed") - browser.verify.containsText('.empty-row', 'No data to display', "View table info message is correctly displayed") - } else { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'You have', "Beginning of info message is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', parseInt(result.value), "Number of Agents is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'Agent Groups.', "End of info message is correctly displayed") - } - }) - - } - -}; - -module.exports = { - url: '/pages/fleet/groups', - elements: { - newButton: '.appearance-ghost', - newHeading: 'header h4', - activeBreadcrumb: '.xng-breadcrumb-item:last-child .xng-breadcrumb-trail', - selectedStep: '.selected span', - completedStep: '.completed span', - stepLabel: '.step-label strong', - stepCaption: '.step-label p', - detailsLabels: '.nb-form-control-container div:not(.d-flex)', - newNameInput: '[formcontrolname="name"]', - newDescriptionInput: '[formcontrolname="description"]', - tagLabels: '.nb-form-control-container div div div', - keyInput: '[formcontrolname="key"]', - valueInput: '[formcontrolname="value"]', - addTagButton: 'button [icon="plus-outline"]', - tagChip: '.mat-chip', - tagChipDelete: '.mat-chip [icon="close-outline"]', - agentGroupList: 'xng-breadcrumb.orb-breadcrumb', - agentGroupAll: 'ngx-agent-group-list-component.ng-star-inserted > div:nth-child(1) > header:nth-child(1) > h4:nth-child(2)', - key: 'div.col-5:nth-child(1) > div:nth-child(2) > input:nth-child(1)', - value: 'div.d-flex:nth-child(3) > div:nth-child(2) > input:nth-child(1)', - addTag: 'button.status-basic', - next:'.next-button', - back: '.appearance-ghost', - deleteAgentGroups: '.orb-sink-delete-warning-button', - agentGroupsDeleteModal: 'ngx-agent-group-delete-component.ng-star-inserted > nb-card:nth-child(1)', - close: '.nb-close', - edit: '.sink-edit-button', - agentPath: '.xng-breadcrumb-link', - new:'.status-primary', - filter:'.select-button', - table:'.datatable-body', - search:'input.size-medium' - - }, - commands: [commands] -}; diff --git a/orb_tests/page_objects/agents.js b/orb_tests/page_objects/agents.js deleted file mode 100644 index be6d27b4a..000000000 --- a/orb_tests/page_objects/agents.js +++ /dev/null @@ -1,221 +0,0 @@ -var loginActions = { - AgentsPage: function () { - return this - .waitForElementVisible('@path', "Agents path is visible") - .verify.containsText('@agentPath', 'Fleet Management', "Agents is inherited from Fleet Management") - .verify.containsText('@view', 'Agents List', "Agent view is named 'Agents List'") - .verify.containsText('@header', "All Agents", "Agents Header is 'All Agents'") - .waitForElementVisible('.flex-column', "Agent Groups table view is visible") - .waitForElementVisible('@table', "Agent table view is visible") - .waitForElementVisible("@new", "New Agent button is visible") - .waitForElementVisible("@filter", "Filter type is visible") - .waitForElementVisible("@search", "Search by filter is visible") - - }, - - new: function() { - return this.navigate() - .waitForElementVisible('@newButton', 10000, "New Agent button is visible") - .click('@newButton') - }, - - - agentCreationPage: function() { - return this.waitForElementVisible('@pathNew', "Agents path is visible") - .verify.containsText('@agentPath', 'Fleet Management', "Agents is inherited from Fleet Management") - .verify.containsText('@pathNew', 'Agents List', "Agent view is named 'Agents List'") - .verify.containsText('@pathNew', "New Agent", "Agents Header is 'New Agent'") - .verify.containsText('@headerNew', 'New Agent', "Header is 'New Agent'") - .verify.containsText('@agentDetails', 'Agent Details', "Header is 'Agent Details'") - .verify.containsText('.header', 'This is how you will be able to easily identify your Agent', "Help text about name is correctly written") - .verify.containsText('.header', 'Orb Tags', "'Agent Tags' is being displayed") - .verify.containsText('.header', 'Set the tags that will be used to filter your Agent', "Help text about tags is correctly written") - .verify.containsText('.header', 'Review & Confirm', "'Review & Confirm' is being displayed") - .verify.containsText('.step-content', 'Agent Name*', "'Agent Name*' field is being displayed") - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - }, - - - agentCreation: function(name, key, value, verify, closeOption='@close') { - return this.setValue('@newNameInput', name) - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - // .setValue('@newDescriptionInput', description) - .click('@next') - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@addTag','aria-disabled', 'true', "'Add tags' button is not enabled") - .setValue('@key', key) - .setValue('@value', value) - .verify.attributeEquals('@addTag','aria-disabled', 'false', "'Add tags' button is enabled") - .click('@addTag') - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .click('@next') - .verify.containsText('@pathNew', "New Agent", "Agents Header is 'New Agent'") - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .click('@next') - .verify.visible('[class="cdk-overlay-pane"]', "Agent Credentials modal is visible") - .verify.containsText("@agentCredentialsHeader", "Agent Credentials", "Agent Credentials modal's header is 'Agent Credentials'") - .verify.containsText("@agentCredencialsBody", "Make sure to copy the Agent Key now. You won’t be able to see it again!", "Agent Credentials help text is 'Make sure to copy the Agent Key now. You won’t be able to see it again!'") - .verify.containsText("@agentCredencialsBody", "Agent Key", "Agent key field's name is 'Agent Key'") - .verify.containsText("@agentCredencialsBody", "Provisioning Command", "Provisioning Command field's name is 'Provisioning Command'") - .verify.visible("@agentKey", "Agent Key is being displayed") - .verify.visible("@agentProvisioningCommand", "Agent Provisioning Command is being displayed") - .click('@copyKey') - .click('@copyProvisioningCommand') - // options: '@closeCredentialsModal' or '@close' - .click(closeOption) - .verify.containsText('span.title', verify, "Confirmation message is correctly displayed") - - -}, - -agentsVisualization: function() { - return this.verify.attributeEquals('button.orb-action-hover:nth-child(1)', 'aria-disabled', 'false', "'Visualization' button is visible") - .click('button.orb-action-hover:nth-child(1)') - .verify.elementPresent('.cdk-overlay-backdrop', "'Visualization' modal is visible") - .verify.containsText('.nb-card-medium > nb-card-header:nth-child(1)', 'Agent Details', "'Visualization' header is correctly written") - .verify.containsText('@visualizationAgentModal', "Agent Name*", "Agent name field is visible on visualization modal") - .verify.containsText('@visualizationAgentModal', "Channel ID", "Agent Channel ID field is visible on visualization modal") - .verify.containsText('@visualizationAgentModal', "Created on", "Agent Created on field is visible on visualization modal") - .verify.containsText('@visualizationAgentModal', "Status", "Agent Status field is visible on visualization modal") - .verify.containsText('@visualizationAgentModal', "Tags*", "Agent Tags field is visible on visualization modal") -}, - - -agentsEdit: function(name, key, value, key2, value2, verify) { - return this.verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .clearValue('@newNameInput') - .setValue('@newNameInput', name) - - .click('@next') - .click('.eva-close-outline') - .verify.attributeEquals('@next','aria-disabled', 'true', "'Next' button is not enabled") - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@addTag','aria-disabled', 'true', "'Add tags' button is not enabled") - .addTags(key, value) - .addTags(key2, value2) - .verify.attributeEquals('button.status-primary:nth-child(1)','aria-disabled', 'false', "'Back' button is enabled") - .click('@next') - .verify.containsText('@agentsList','Edit Agent', 'Page header is "Edit Agent"') - .verify.attributeEquals('@back','aria-disabled', 'false', "'Back' button is enabled") - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - .click('@next') - .verify.containsText('span.title', verify, "Confirmation message is correctly displayed") -}, - -addTags: function(key, value) { - return this.setValue('@key', key) - .setValue('@value', value) - .verify.attributeEquals('@addTag','aria-disabled', 'false', "'Add tags' button is enabled") - .click('@addTag') - .verify.attributeEquals('@next','aria-disabled', 'false', "'Next' button is enabled") - -}, - -choose_last_element: function() { - return this.waitForElementVisible('[class="orb-action-hover detail-button appearance-ghost size-medium status-basic shape-rectangle icon-start icon-end nb-transition"]', "Agent is visible") - .findElements('[class="orb-action-hover detail-button appearance-ghost size-medium status-basic shape-rectangle icon-start icon-end nb-transition"]', function(result) { - var agentView = result.value - this.elementIdClick(agentView[agentView.length-1].ELEMENT) - - -}) -}, - -agentCheck: function(name, tag){ - return this.verify.containsText('div.row:nth-child(1) > div:nth-child(1) > p:nth-child(1)', 'Agent Name*', "View contain Agent Group Name Field") - .verify.containsText('div.row:nth-child(1) > div:nth-child(1) > p:nth-child(2)', name, "Name of Agent is correctly displayed") - .verify.containsText('div.row:nth-child(2) > div:nth-child(1) > p:nth-child(1)', 'Tags*', "View contain Agent Tags Field") - // bug insert a way to verify tags - // .verify.containsText('[class="mat-chip-list-wrapper"]', tag, "Tag is correctly displayed") - .click('@close') - -}, - -agentsDelete: function() { - return this.verify.attributeEquals('button.orb-action-hover:nth-child(3)', 'aria-disabled', 'false', "'Remove' agent button is enabled") - .click('button.orb-action-hover:nth-child(3)') - .verify.attributeEquals('@deleteAgent','aria-disabled', 'true', "'Confirm agent delete button is not enabled") - .verify.visible('@deleteAgentModal', "Delete agent modal is visible") - .verify.containsText('ngx-agent-delete-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-header:nth-child(1)', 'Delete Agent Confirmation', "Header of help text about delete confirmation is correctly written") - .verify.containsText('@deleteAgentModal', 'Are you sure you want to delete this Agent? This action cannot be undone.*', "Help text about delete confirmation is correctly written") - .verify.containsText('@deleteAgentModal', '*To confirm, type your Agent name exactly as it appears', "End of help text about delete confirmation is correctly written") - .getAttribute('.input-full-width', 'placeholder', function(result) {this.setValue('.input-full-width', result.value) }) - .verify.attributeEquals('@deleteAgent','aria-disabled', 'false', "'Confirm agent delete button is enabled") - .click('@deleteAgent') - .verify.containsText('span.title', 'Agent successfully deleted', "Delete confirmation message is being displayed") - //bug .verify.containsText('.empty-row', 'No data to display') - -}, - -countAgent: function(browser) { - return this.getText('.page-count', function(result){ - //console.log('Value is:', result.value); - if (result.value == "0 total") { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - - browser.verify.containsText('.sink-info-accent', 'There are no Agent yet.', "Info message of Agent count is correctly displayed") - browser.verify.containsText('.empty-row', 'No data to display', "View table info message is correctly displayed") - } else { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'You have', "Beginning of info message is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', parseInt(result.value), "Number of Agents is correctly displayed") - // bug need to insert regions count test - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'agents deployed', "End of info message is correctly displayed") - } - }) - -} - } - - module.exports = { - url: '/pages/fleet/agents', - commands: [loginActions], - elements: { - path: 'xng-breadcrumb.orb-breadcrumb', - pathNew: '.xng-breadcrumb-root', - agentPath: '.xng-breadcrumb-link', - view: '.xng-breadcrumb-trail', - headerNew: 'ngx-agent-add-component.ng-star-inserted > div:nth-child(1) > header:nth-child(1) > h4:nth-child(2)', - header: 'ngx-agent-list-component.ng-star-inserted > div:nth-child(1) > header:nth-child(1) > h4:nth-child(2)', - table:'.datatable-body', - new:'.status-primary', - filter:'.select-button', - search:'input.size-medium', - agentsListed: '.datatable-row-wrapper', - info: '.sink-info-accent', - emptyRow: '.empty-row', - countMessage: '.justify-content-between > div:nth-child(1)', - count:'.page-count', - newButton: '.appearance-ghost', - agentDetails: 'div.step:nth-child(1) > div:nth-child(2) > div:nth-child(1) > strong:nth-child(1)', - next:'.next-button', - back: '.appearance-ghost', - close: '.nb-close', - closeCredentialsModal: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-footer:nth-child(3) > button:nth-child(1)', - newNameInput: '[formcontrolname="name"]', - key: 'div.col-5:nth-child(1) > div:nth-child(2) > input:nth-child(1)', - value: 'div.d-flex:nth-child(3) > div:nth-child(2) > input:nth-child(1)', - addTag: 'button.status-basic', - agentCredencialsBody: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-body:nth-child(2)', - agentCredentialsHeader: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-header:nth-child(1)', - agentKey: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-body:nth-child(2) > pre:nth-child(3)', - agentProvisioningCommand: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-body:nth-child(2) > pre:nth-child(5) > code:nth-child(2)', - copyKey: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-body:nth-child(2) > pre:nth-child(5) > button:nth-child(1)', - copyProvisioningCommand: 'ngx-agent-key-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-body:nth-child(2) > pre:nth-child(5) > button:nth-child(1)', - deleteAgent: '.orb-sink-delete-warning-button', - deleteAgentModal: 'ngx-agent-delete-component.ng-star-inserted', - edit: '.sink-edit-button', - visualizationAgentModal: '.nb-card-medium > nb-card-body:nth-child(2)', - newNameInput: '[formcontrolname="name"]', - newDescriptionInput: '[formcontrolname="description"]', - agentsList: 'xng-breadcrumb.orb-breadcrumb', - - - - } - } diff --git a/orb_tests/page_objects/login.js b/orb_tests/page_objects/login.js deleted file mode 100644 index d5192914a..000000000 --- a/orb_tests/page_objects/login.js +++ /dev/null @@ -1,33 +0,0 @@ -var loginActions = { - with: function (email, pass) { - return this - .navigate() - .waitForElementVisible('@form', 10000, "Login form is visible") - .setValue('@emailInput', email) - .setValue('@pwdInput', pass) - .click('@loginButton'); - }, - - expectAlert: function (message) { - return this - .waitForElementVisible('@alertMessage', 10000) - .assert.containsText('@alertMessage', message); - }, -} - -module.exports = { - url: '/auth/login', - commands: [loginActions], - elements: { - form: '.pane form', - emailInput: 'input[name=email]', - pwdInput: 'input[name=password]', - loginButton: 'form button', - alertMessage: '.alert-message', - requiredAlert: 'p.status-danger', - orbLogo: '#orb-pane-div img', - orbCaption: '#orb-pane-div p', - forgotPwdLink: 'a.forgot-password', - registerLink: '[aria-label="Register"] a' - } -} diff --git a/orb_tests/page_objects/register.js b/orb_tests/page_objects/register.js deleted file mode 100644 index 4ebba3863..000000000 --- a/orb_tests/page_objects/register.js +++ /dev/null @@ -1,28 +0,0 @@ -var registerActions = { - with: function (userData) { - return this - .navigate() - .waitForElementVisible('@form', 10000) - .setValue('@emailInput', email) - .setValue('@pwdInput', pass) - .click('@loginButton'); - }, - - expectAlert: function (message) { - return this - .waitForElementVisible('@alertMessage', 10000) - .assert.containsText('@alertMessage', message); - }, -} - -module.exports = { - url: '/auth/register', - commands: [registerActions], - elements: { - form: '.pane form', - emailInput: 'input[name=email]', - pwdInput: 'input[name=password]', - loginButton: 'form button', - alertMessage: '.alert-message', - } -} diff --git a/orb_tests/page_objects/sinks.js b/orb_tests/page_objects/sinks.js deleted file mode 100644 index 7413362c4..000000000 --- a/orb_tests/page_objects/sinks.js +++ /dev/null @@ -1,167 +0,0 @@ -var commands = { - sinkManagementPage: function() { - return this.waitForElementVisible('@allSinksPage') - .verify.containsText('@allSinksPage', 'Sink Management', "Page name is 'Sink Management'") - .verify.visible('ngx-sink-list-component.ng-star-inserted', "Sink list is visible") - - }, - - sinkCreation: function(name_label, description, remote_host, username, password, key, value, verify) { - return this.verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@sinkNameLabel', "Sink Label named field is being displayed") - .setValue('@sinkNameLabel', name_label) - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - .waitForElementVisible('@sinkDescription', "Sink Description field is being displayed") - .setValue('@sinkDescription', description) - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - .click('@sinkNext') - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@sinkRemoteHost', "Sink Remote Host field is being displayed") - .setValue('@sinkRemoteHost', remote_host) - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@sinkUsername', "Sink username field is being displayed") - .setValue('@sinkUsername', username) - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@sinkPassword', "Sink password field is being displayed") - .setValue('@sinkPassword', password) - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - .click('@sinkNext') - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@key', "Sink key field is being displayed") - .setValue('@key', key) - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@value', "Sink value field is being displayed") - .setValue('@value', value) - .verify.attributeEquals('@sinkNext','aria-disabled', 'true', "'Next' button is not enabled") - .waitForElementVisible('@addTag', "Add tags button is being displayed") - .click('@addTag') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', verify, "Confirmation message is being correctly displayed") - }, - - sinkVisualization: function() { - return this.verify.not.elementPresent('.cdk-overlay-backdrop', "Sink visualization modal is not being displayed") - .verify.attributeEquals('button.orb-action-hover:nth-child(1)', 'aria-disabled', 'false', "Visualization button is enabled") - .click('button.orb-action-hover:nth-child(1)') - .verify.elementPresent('.cdk-overlay-backdrop', "Sink visualization modal is being displayed") - .verify.containsText('.nb-card-medium > nb-card-header:nth-child(1)', 'Sink Details', "Header of visualization page is correctly written") - }, - - sinkEdit: function() { - return this.verify.not.elementPresent('.cdk-overlay-backdrop', "Sink edit page is not being displayed") - .verify.attributeEquals('button.orb-action-hover:nth-child(2)', 'aria-disabled', 'false', "Edit sink button is enabled") - .click('button.orb-action-hover:nth-child(2)') - .sinkEditPage() - - }, - - sinkEditPage: function() { - return this.verify.containsText('.xng-breadcrumb-trail', 'Edit Sink', "Page is named 'Edit Sink'") - .verify.containsText('ngx-sink-add-component.ng-star-inserted > div:nth-child(1) > header:nth-child(1)', 'Edit Sink', "Option is named 'Edit Sink'") - .verify.containsText('@editSinkHeader', 'Sink Details', "Sink Details is being displayed") - .verify.containsText('@editSinkHeader', 'Provide a name and description for the Sink', "Help message for name is correctly written") - .verify.containsText('@editSinkHeader', 'Sink Destination', "Sink Destination is being correctly displayed") - .verify.containsText('@editSinkHeader', 'Configure your Sink settings', "Help message for settings is correctly written") - .verify.containsText('@editSinkHeader', 'Sink Tags', "Sink Tags is being displayed") - .verify.containsText('@editSinkHeader', 'Enter tags for this Sink', "Help message for tags is correctly written") - .verify.containsText('@editSinkForm', 'Name Label', "Name Label is being displayed") - .verify.containsText('@editSinkForm', 'Sink Description', "Sink Description is being displayed") - .verify.containsText('@editSinkForm', 'Sink Type', "Sink Type is being displayed") - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - - }, - - sinkEditAttribute: function(attribute, value) { - return this.verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - .waitForElementVisible(attribute, "Element edition is enabled") - .setValue(attribute, value) - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - - }, - - sinkEditTags: function(key, value, key_value, value_value) { - return this.waitForElementVisible(key, "Key is being displayed") - .waitForElementVisible(value, "Value is being displayed") - .setValue(key, key_value) - .setValue(value, value_value) - .waitForElementVisible('@addTag', "'Add Tags' button is visible") - .click('@addTag') - .verify.attributeEquals('@sinkNext','aria-disabled', 'false', "'Next' button is enabled") - - }, - - - sinkDelete: function() { - return this.verify.attributeEquals('button.orb-action-hover:nth-child(3)', 'aria-disabled', 'false', "'Delete' button is enabled") - .click('button.orb-action-hover:nth-child(3)') - .verify.attributeEquals('@deleteSink','aria-disabled', 'true', "'Confirm Delete' button is not enabled") - .verify.visible('@sinkDeleteModal', "Delete modal is visible") - .verify.containsText('ngx-sink-delete-component.ng-star-inserted > nb-card:nth-child(1) > nb-card-header:nth-child(1)', 'Delete Sink Confirmation', "Header of delete modal is correctly written") - .verify.containsText('@sinkDeleteModal', 'Are you sure you want to delete this Sink? This may cause Datasets which use this Sink to become invalid. This action cannot be undone.', "Help message for delete is correctly written") - .verify.containsText('@sinkDeleteModal', 'To confirm, type your Sink name exactly as it appears', "Confirm message is correctly wirtten") - .getAttribute('.input-full-width', 'placeholder', function(result) {this.setValue('.input-full-width', result.value) }) - .verify.attributeEquals('@deleteSink','aria-disabled', 'false', "'Confirm Delete' button is enabled") - .click('@deleteSink') - .verify.containsText('span.title', 'Sink successfully deleted', "Confirmation message is being correctly displayed") - //bug insert count - .verify.containsText('.empty-row', 'No data to display', "List sink is correctly reload") - - }, - - sinkCheckEdition: function(value) { - return this.sinkVisualization() - .verify.containsText('ngx-sink-details-component.ng-star-inserted',value, "Element is correctly edited") - .click('.nb-close') - .sinkManagementPage() - }, - - countSinks: function(browser) { - return this.getText('.page-count', function(result){ - //console.log('Value is:', result.value); - if (result.value == "0 total") { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - - browser.verify.containsText('.sink-info-accent', 'There are no Sinks yet.', "Info message of Sinks count is correctly displayed") - browser.verify.containsText('.empty-row', 'No data to display', "View table info message is correctly displayed") - } else { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'sinks total', "Beginning of info message is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', parseInt(result.value), "Number of Sinks is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'have errors.', "End of info message is correctly displayed") - } - })} - -}; - -module.exports = { - url: '/pages/sinks', - elements: { - username: 'input[id=input-email]', - pwd: 'input[id=input-password]', - submit: '.appearance-filled', - loginBody: 'div.login_wrapper', - allSinksPage : '.xng-breadcrumb-trail', - sinkNameLabel:'input[data-orb-qa-id=name]', - sinkDescription: 'input[data-orb-qa-id=description]', - sinkNext: 'button[data-orb-qa-id=next]', - sinkRemoteHost: 'input[data-orb-qa-id=remote_host]', - sinkUsername: 'input[data-orb-qa-id=username]', - sinkPassword: 'input[data-orb-qa-id=password]', - key: 'input[data-orb-qa-id=key]', - value: 'input[data-orb-qa-id=value]', - addTag: 'button[data-orb-qa-id=addTag]', - spanTitle: 'span.title', - register: '.text-link', - fullNameInput:'input[id=input-name]', - confirmPassword: 'input[id=input-re-password]', - deleteSink: '.orb-sink-delete-warning-button', - cancel: 'button[data-orb-qa-id=cancel]', - back: 'button[data-orb-qa-id=back]', - previous: 'button[data-orb-qa-id=previous]', - editSinkHeader: '.header', - editSinkForm: 'form.ng-pristine', - sinkDeleteModal: 'ngx-sink-delete-component.ng-star-inserted > nb-card:nth-child(1)' - }, - commands: [commands] -}; diff --git a/orb_tests/page_objects/topbar.js b/orb_tests/page_objects/topbar.js deleted file mode 100644 index 014afa63d..000000000 --- a/orb_tests/page_objects/topbar.js +++ /dev/null @@ -1,15 +0,0 @@ -var userActions = { - expectLoggedUser: function (email) { - return this.waitForElementVisible('@userInfo', 10000, "User info is visible") - //bug on orb - // .waitForElementVisible('@userInfo', 10000, "User info is visible") - .assert.containsText('@userInfo', email, "User is displayed on topbar"); - } -} - -module.exports = { - commands: [userActions], - elements: { - userInfo: '.user-name', - } -} diff --git a/orb_tests/tests/agents/1goToAgentsPage.js b/orb_tests/tests/agents/1goToAgentsPage.js deleted file mode 100644 index bbdfaf8a5..000000000 --- a/orb_tests/tests/agents/1goToAgentsPage.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - -'Go to Agent page from Orb Home': function(browser){ - const agentsPage = browser.launch_url + '/pages/fleet/agents' - browser - .verify.visible('li.menu-item:nth-child(2)', "Fleet Management is visible on ORB menu") - .verify.containsText('[title="Fleet Management"]', 'Fleet Management', "Fleet management is correctly writen") - .click('li.menu-item:nth-child(2)') - .waitForElementVisible('xpath', '/html/body/ngx-app/ngx-pages/ngx-one-column-layout/nb-layout/div/div/div/nb-sidebar/div/div/nb-menu/ul/li[2]/ul/li[2]/a', "Agents is visible on ORB menu") - .click('xpath','/html/body/ngx-app/ngx-pages/ngx-one-column-layout/nb-layout/div/div/div/nb-sidebar/div/div/nb-menu/ul/li[2]/ul/li[1]/a') - .verify.urlEquals(agentsPage) - browser.page.agents().AgentsPage() - }} diff --git a/orb_tests/tests/agents/2agent_page.js b/orb_tests/tests/agents/2agent_page.js deleted file mode 100644 index b8b85e865..000000000 --- a/orb_tests/tests/agents/2agent_page.js +++ /dev/null @@ -1,54 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'agents page info': function(browser) { - - const agents = browser.page.agents(); - - agents - .navigate() - .AgentsPage() - }, - - 'Count of agents': function(browser){ - const agents = browser.page.agents(); - - agents - //bug - need to remove this time - .navigate() - .pause(1000) - .getText('.page-count', function(result){ - //console.log('Value is:', result.value); - if (result.value == "0 total") { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - - browser.verify.containsText('.sink-info-accent', 'There are no Agents yet.', "Info message of Agents count is correctly displayed") - browser.verify.containsText('.empty-row', 'No data to display', "View table info message is correctly displayed") - } else { - browser.expect.elements('datatable-row-wrapper').count.to.equal(parseInt(result.value)) - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'You have', "Beginning of info message is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', parseInt(result.value), "Number of Agents is correctly displayed") - browser.verify.containsText('.justify-content-between > div:nth-child(1)', 'agents deployed in', "End of info message is correctly displayed") - } - }) - - // .pause(2000) - } - } - \ No newline at end of file diff --git a/orb_tests/tests/agents/3newAgent.js b/orb_tests/tests/agents/3newAgent.js deleted file mode 100644 index 8d31e2bb5..000000000 --- a/orb_tests/tests/agents/3newAgent.js +++ /dev/null @@ -1,41 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Agent Creation using close button' : function(browser){ - var agents = browser.page.agents() - agents - .new() - .agentCreationPage() - .agentCreation('newAgent', 'key', 'value', 'Agent successfully created', '@closeCredentialsModal') - - - }, - - 'Agent Creation using "x" button' : function(browser){ - var agents = browser.page.agents() - agents - .new() - .agentCreationPage() - .agentCreation('new2Agent', 'key', 'value', 'Agent successfully created', '@close') - - - } - - - } diff --git a/orb_tests/tests/agents/4agentsVisualization.js b/orb_tests/tests/agents/4agentsVisualization.js deleted file mode 100644 index 67dee9262..000000000 --- a/orb_tests/tests/agents/4agentsVisualization.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Agent Group Visualization': function(browser){ - var agents = browser.page.agents() - agents - .navigate() - .agentsVisualization() - .click('@close') - .AgentsPage() - .agentsVisualization() - .click('@edit') - .click('@back') - -}} diff --git a/orb_tests/tests/agents/5agentEdit.js b/orb_tests/tests/agents/5agentEdit.js deleted file mode 100644 index 6d1abbb74..000000000 --- a/orb_tests/tests/agents/5agentEdit.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Agent Group Edit': function(browser){ - var agents = browser.page.agents() - agents - .navigate() - - .agentsVisualization() - .click('@edit') - .click('@back') - .AgentsPage() - .agentsVisualization() - .click('@edit') - .agentsEdit('agentEdited', 'region', 'br', 'region2', 'usa', 'Agent successfully updated') - .choose_last_element() - .agentCheck('agentEdited', 'region: br') - .choose_last_element() - .agentCheck('agentEdited', 'region2: usa') -}} diff --git a/orb_tests/tests/agents/9agentsDelete.js b/orb_tests/tests/agents/9agentsDelete.js deleted file mode 100644 index fd6355139..000000000 --- a/orb_tests/tests/agents/9agentsDelete.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Agent Delete' : function(browser){ - var agents = browser.page.agents() - agents - .navigate() - .AgentsPage() - // bug need to remove this pause - .pause(2000) - .countAgent(browser) - .agentsDelete() - .AgentsPage() - .agentsDelete() - .countAgent(browser) - - }} diff --git a/orb_tests/tests/agents_groups/1goToAgentGroupPage.js b/orb_tests/tests/agents_groups/1goToAgentGroupPage.js deleted file mode 100644 index 27a2c3731..000000000 --- a/orb_tests/tests/agents_groups/1goToAgentGroupPage.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Go to Agent Groups page from Orb Home': function(browser){ - const agentGroupsPage = browser.launch_url + '/pages/fleet/groups'; - browser - .verify.visible('li.menu-item:nth-child(2)', "Fleet Management is visible on ORB menu") - .verify.containsText('[title="Fleet Management"]', 'Fleet Management', "Fleet management is correctly writen") - .click('li.menu-item:nth-child(2)') - .waitForElementVisible('xpath', '/html/body/ngx-app/ngx-pages/ngx-one-column-layout/nb-layout/div/div/div/nb-sidebar/div/div/nb-menu/ul/li[2]/ul/li[2]/a', "Agent Groups is visible on ORB menu") - .click('xpath','/html/body/ngx-app/ngx-pages/ngx-one-column-layout/nb-layout/div/div/div/nb-sidebar/div/div/nb-menu/ul/li[2]/ul/li[2]/a') - .verify.urlEquals(agentGroupsPage) - }} diff --git a/orb_tests/tests/agents_groups/2list-view.js b/orb_tests/tests/agents_groups/2list-view.js deleted file mode 100644 index 131bb9625..000000000 --- a/orb_tests/tests/agents_groups/2list-view.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Agent Group Page' : function(browser) { - var agent_groups = browser.page.agent_groups() - agent_groups - .navigate() - .listView() - }, - - - -} - - diff --git a/orb_tests/tests/agents_groups/3newAgentWithDescription.js b/orb_tests/tests/agents_groups/3newAgentWithDescription.js deleted file mode 100644 index cca64c5ed..000000000 --- a/orb_tests/tests/agents_groups/3newAgentWithDescription.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Agent Group Creation - with description' : function(browser){ - var agent_groups = browser.page.agent_groups() - agent_groups - .navigate() - .new() - //bug need to insert count agent groups - .agentGroupCreation('nam3', "some_description", "key", "value", "Agent Group successfully created") - //bug - incomplete reload. need to remove this navigate - //bug - delay. need to remove this paude - .navigate() - .pause(1000) - .agentGroupVisualization() - .agentGroupCheck('nam3', "some_description", "key", "value") - .countAgentGroups(browser) - - - }} diff --git a/orb_tests/tests/agents_groups/4newAgentGroupsWithoutDescription.js b/orb_tests/tests/agents_groups/4newAgentGroupsWithoutDescription.js deleted file mode 100644 index 52bfeb630..000000000 --- a/orb_tests/tests/agents_groups/4newAgentGroupsWithoutDescription.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Agent Group Creation - without description' : function(browser){ - var agent_groups = browser.page.agent_groups() - agent_groups - .navigate() - .listView() - .new() - .agentGroupCreationPage() - .agentGroupCreation('name', "", "key", "value", "Agent Group successfully created") - //bug - incomplete reload. need to remove this navigate - //bug - delay. need to remove this paude - .navigate() - .pause(1000) - .countAgentGroups(browser) -}} diff --git a/orb_tests/tests/agents_groups/5agentGroupVisualization.js b/orb_tests/tests/agents_groups/5agentGroupVisualization.js deleted file mode 100644 index 65b1d62cb..000000000 --- a/orb_tests/tests/agents_groups/5agentGroupVisualization.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Agent Group Visualization': function(browser){ - var agent_groups = browser.page.agent_groups() - agent_groups - .navigate() - .agentGroupVisualization() - .click('@close') - .listView() - .agentGroupVisualization() - .click('@edit') - .click('@back') - -}} diff --git a/orb_tests/tests/agents_groups/6agentGroupEdit.js b/orb_tests/tests/agents_groups/6agentGroupEdit.js deleted file mode 100644 index f901d90b0..000000000 --- a/orb_tests/tests/agents_groups/6agentGroupEdit.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - -'Agent Group Edit': function(browser){ - var agent_groups = browser.page.agent_groups() - agent_groups - .navigate() - - .agentGroupVisualization() - .click('@edit') - .click('@back') - .listView() - .agentGroupVisualization() - .click('@edit') - .agentGroupsEdit('agentGroup_Edited', 'edited_desc', 'editedKey', 'editedValue', 'secondKey', 'secondValue', 'Agent Group successfully updated') - .choose_last_element() - .agentGroupCheck('agentGroup_Edited', 'edited_desc', 'editedKey', 'editedValue') - .choose_last_element() - .agentGroupCheck('agentGroup_Edited', 'edited_desc', 'secondKey', 'secondValue') -}} diff --git a/orb_tests/tests/agents_groups/7removeAgentGroup.js b/orb_tests/tests/agents_groups/7removeAgentGroup.js deleted file mode 100644 index 6763b6bb9..000000000 --- a/orb_tests/tests/agents_groups/7removeAgentGroup.js +++ /dev/null @@ -1,36 +0,0 @@ - - module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Agent groups delete' : function(browser){ - - var agent_groups = browser.page.agent_groups() - //bug - incomplete reload. need to remove this navigate - //bug - delay. need to remove this paude - agent_groups - .navigate() - .pause(1000) - .countAgentGroups(browser) - .agentGroupsDelete() - .listView() - .agentGroupsDelete() - .countAgentGroups(browser) - //bug need to insert loop - - - }} diff --git a/orb_tests/tests/agents_groups/new_refactor.js b/orb_tests/tests/agents_groups/new_refactor.js deleted file mode 100644 index 39e041ea5..000000000 --- a/orb_tests/tests/agents_groups/new_refactor.js +++ /dev/null @@ -1,80 +0,0 @@ -module.exports = { - '@disabled': true, - - - - beforeEach: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'New Agent Group' : function(browser) { - const agentGroup = browser.page.agent_groups(); - const data = { - step1: { - name: 'group1', - description: 'group1 description', - }, - step2: [ - { - key: 'region', - value: 'br', - }, - { - key: 'backend', - value: 'visor', - }, - { - key: 'pop', - value: 'pop03', - } - ] - }; - - agentGroup.new() - .waitForElementVisible('@newHeading', 10000) - .verify.containsText('@activeBreadcrumb', 'New Agent Group') - .verify.containsText('@newHeading', 'New Agent Group') - .verify.containsText({ selector: '@stepLabel', index: 0 }, 'Agent Group Details') - .verify.containsText({ selector: '@stepCaption', index: 0 }, 'This is how you will be able to easily identify your Agent Group') - .verify.containsText({ selector: '@stepLabel', index: 1 }, 'Agent Group Tags') - .verify.containsText({ selector: '@stepCaption', index: 1 }, 'Set the tags that will be used to group Agents') - .verify.containsText({ selector: '@stepLabel', index: 2 }, 'Review & Confirm') - .verify.not.enabled('@next') - .verify.enabled('@back') - .verify.containsText({ selector: '@detailsLabels', index: 0 }, 'Agent Group Name*') - .setValue('@newNameInput', data.step1.name) - .verify.enabled('@next') - .verify.containsText({ selector: '@detailsLabels', index: 1 }, 'Agent Group Description') - .setValue('@newDescriptionInput', data.step1.description) - .click('@next') - - .verify.containsText({selector: '@tagLabels', index: 0}, 'Key*') - .verify.containsText({selector: '@tagLabels', index: 2}, 'Value*') - .verify.not.enabled('@next') - .verify.enabled('button.status-primary:nth-child(1)') - - data.step2.forEach((tag, i) => { - agentGroup.setValue('@keyInput', tag.key) - .setValue('@valueInput', tag.value) - .click('@addTagButton') - .waitForElementVisible({ selector: '@tagChip', index: 0 }, 10000) - .verify.containsText({ selector: '@tagChip', index: 0 }, `${tag.key}: ${tag.value}`) - }); - - agentGroup.verify.enabled('@next') - .click('@next') - - - } -}; diff --git a/orb_tests/tests/login/1invalid_regex_email.js b/orb_tests/tests/login/1invalid_regex_email.js deleted file mode 100644 index 2dbc34567..000000000 --- a/orb_tests/tests/login/1invalid_regex_email.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login with invalid regex for email': (browser) => { - const login = browser.page.login(); - - login - .with('tester@email', '12345678') - .click('@pwdInput') - .waitForElementVisible('@requiredAlert', 10000, "Help message about invalid regex for email is visible") - .assert.containsText('@requiredAlert', 'Email should be the real one!', "Help message contains text 'Email should be the real one!'") - .assert.not.enabled('@loginButton', "Login button is not enabled"); - } -} diff --git a/orb_tests/tests/login/2layout.js b/orb_tests/tests/login/2layout.js deleted file mode 100644 index 7613040a8..000000000 --- a/orb_tests/tests/login/2layout.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - '@disabled': false, - - 'layout components should be consistent with spec': (browser) => { - const forgotPwdLink = browser.launch_url + '/auth/request-password'; - const registerLink = browser.launch_url + '/auth/register'; - - const login = browser.page.login(); - - login - .navigate() - .waitForElementVisible('@orbLogo', 10000, "Orb logo is being displayed") - .assert.containsText('@orbCaption', 'An Open-Source dynamic edge observability platform', "Message 'An Open-Source dynamic edge observability platform' is being displayed") - .assert.containsText('@forgotPwdLink', 'Forgot Password?', "'Forgot Password' option is being displayed") - .assert.attributeEquals('@forgotPwdLink', 'href', forgotPwdLink, "'Forgot Password' is clickable") - .assert.containsText('@registerLink', 'Register', "'Register' option is being displayed") - .assert.attributeEquals('@registerLink', 'href', registerLink, "'Register' is clickable") - .assert.not.enabled('@loginButton', "Login button is not enabled"); - } -} diff --git a/orb_tests/tests/login/3password_length.js b/orb_tests/tests/login/3password_length.js deleted file mode 100644 index 9f6f5b551..000000000 --- a/orb_tests/tests/login/3password_length.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login with an invalid password legth ': (browser) => { - const login = browser.page.login(); - - login - .with('wrong@email.com', '1234567') - .click('@emailInput') - .waitForElementVisible('@requiredAlert', 10000, "Help message about password length is visible") - .assert.containsText('@requiredAlert', 'Password should contain from 8 to 50 characters', "Help messagem about password lenght contains text 'Password should contain from 8 to 50 characters'") - .assert.not.enabled('@loginButton', "Login button is not enabled"); - } -} diff --git a/orb_tests/tests/login/4password_required.js b/orb_tests/tests/login/4password_required.js deleted file mode 100644 index fec3dccc5..000000000 --- a/orb_tests/tests/login/4password_required.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login without password': (browser) => { - const login = browser.page.login(); - - login - .with('tester@email.com', '') - .click('@emailInput') - .waitForElementVisible('@requiredAlert', 10000, "Password request help message is visible") - .assert.containsText('@requiredAlert', 'Password is required!', "Help message is 'Password is required!'") - .assert.not.enabled('@loginButton', "Login button is not enabled"); - } -} diff --git a/orb_tests/tests/login/5successful.js b/orb_tests/tests/login/5successful.js deleted file mode 100644 index 8ad6c0abe..000000000 --- a/orb_tests/tests/login/5successful.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login with registered email and correct password': function (browser) { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - } -} diff --git a/orb_tests/tests/login/6without_email.js b/orb_tests/tests/login/6without_email.js deleted file mode 100644 index 80c34aaaf..000000000 --- a/orb_tests/tests/login/6without_email.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login without email': (browser) => { - const login = browser.page.login(); - - login - .with('', '12345678') - .click('@pwdInput') - .waitForElementVisible('@requiredAlert', 10000, "Email request help message is visible") - .assert.containsText("@requiredAlert", "Email is required!", "Help message is 'Email is required'") - .assert.not.enabled('@loginButton', "Login button is not enabled"); - } -} diff --git a/orb_tests/tests/login/7wrong_combination.js b/orb_tests/tests/login/7wrong_combination.js deleted file mode 100644 index 801b4e238..000000000 --- a/orb_tests/tests/login/7wrong_combination.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - '@disabled': false, - - 'Login with wrong combination of email and password': (browser) => { - const login = browser.page.login(); - - login - .with('wrong@email.com', 'any-pass') - .expectAlert('Login/Email combination is not correct, please try again.', "Alert message is visible and contains text 'Login/Email combination is not correct, please try again.'"); - }, - - - 'Login with wrong email and registered password': (browser) => { - const login = browser.page.login(); - - login - .with('testerr@email.com', '12345678') - .expectAlert('Login/Email combination is not correct, please try again.', "Alert message is visible and contains text 'Login/Email combination is not correct, please try again.'"); - }, - - - 'Login with registered email and wrong password': (browser) => { - const login = browser.page.login(); - - login - .with('tester@email.com', '123456789') - .expectAlert('Login/Email combination is not correct, please try again.', "Alert message is visible and contains text 'Login/Email combination is not correct, please try again.'"); - } -} diff --git a/orb_tests/tests/register/creatAccount.js b/orb_tests/tests/register/creatAccount.js deleted file mode 100644 index 6a4564a2f..000000000 --- a/orb_tests/tests/register/creatAccount.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { -'@disabled': false, - -'Create an account' : function(browser) { - var login = browser.page.login() - var accountRegister = browser.page.accountRegister() - const registerLink = browser.launch_url + '/pages'; - - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.navigate() - accountRegister.orbRegister() - .verify.urlEquals(registerLink) - - - }} diff --git a/orb_tests/tests/sinks/1goToSinkPage.js b/orb_tests/tests/sinks/1goToSinkPage.js deleted file mode 100644 index 37ca97087..000000000 --- a/orb_tests/tests/sinks/1goToSinkPage.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - '@disabled': false, - - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Go to sink page' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .assert.visible('li.menu-item:nth-child(4)', "Sink Management is visible on ORB menu") - .click('li.menu-item:nth-child(4)') - .sinkManagementPage() - - - -}} diff --git a/orb_tests/tests/sinks/2newSink.js b/orb_tests/tests/sinks/2newSink.js deleted file mode 100644 index f34e69281..000000000 --- a/orb_tests/tests/sinks/2newSink.js +++ /dev/null @@ -1,36 +0,0 @@ -module.exports = { - '@disabled': false, - - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Creation' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - //.countSinks() - .verify.visible('.appearance-ghost') - .verify.attributeEquals('.appearance-ghost','aria-disabled', 'false') - .click('.appearance-ghost') - .sinkCreation('some_name', 'some_description', 'remote_host', 'tester', 'password', 'key', 'value', 'Sink successfully created') - .sinkManagementPage() - //bug need to remove this pause - .pause(2000) - .countSinks(browser) - - -}} diff --git a/orb_tests/tests/sinks/3duplicateSink.js b/orb_tests/tests/sinks/3duplicateSink.js deleted file mode 100644 index 0e973facf..000000000 --- a/orb_tests/tests/sinks/3duplicateSink.js +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Duplicate sink creation' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkManagementPage() - .verify.visible('.appearance-ghost', "'New Sink' button is visible") - .verify.attributeEquals('.appearance-ghost','aria-disabled', 'false', "'New Sink' button is enabled") - .click('.appearance-ghost') - .sinkCreation('some_name', 'some_description', 'remote_host', 'tester', 'password', 'key', 'value', 'Failed to create Sink') - .waitForElementVisible('@previous') - .click('@previous') - .waitForElementVisible('@back') - .click('@back') - .waitForElementVisible('@cancel') - .click('@cancel') - .waitForElementVisible('@cancel') - .click('@cancel') - .sinkManagementPage() - -}} diff --git a/orb_tests/tests/sinks/4sinkVisualization.js b/orb_tests/tests/sinks/4sinkVisualization.js deleted file mode 100644 index 96942d5cb..000000000 --- a/orb_tests/tests/sinks/4sinkVisualization.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Sink Visualization': (browser) => { - const sinks = browser.page.sinks(); - - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .click('@cancel') - -}} diff --git a/orb_tests/tests/sinks/5sinkVisualizationAndEditDesc.js b/orb_tests/tests/sinks/5sinkVisualizationAndEditDesc.js deleted file mode 100644 index 660df107c..000000000 --- a/orb_tests/tests/sinks/5sinkVisualizationAndEditDesc.js +++ /dev/null @@ -1,38 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Sink Visualization and Edit Description' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .sinkEditAttribute('@sinkDescription','_new') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_new') - -}} diff --git a/orb_tests/tests/sinks/6sinkVisuAndEditRH.js b/orb_tests/tests/sinks/6sinkVisuAndEditRH.js deleted file mode 100644 index bf7e3cf48..000000000 --- a/orb_tests/tests/sinks/6sinkVisuAndEditRH.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - - 'Sink Visualization and Edit Remote Host': (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .click('@sinkNext') - .sinkEditAttribute('@sinkRemoteHost', '_new_rm') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_new_rm') - -}} diff --git a/orb_tests/tests/sinks/7sinkVisualizationAndEditPass.js b/orb_tests/tests/sinks/7sinkVisualizationAndEditPass.js deleted file mode 100644 index f79195b8d..000000000 --- a/orb_tests/tests/sinks/7sinkVisualizationAndEditPass.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - '@disabled': false, - - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - - 'Sink Visualization and Edit Password': (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .click('@sinkNext') - .sinkEditAttribute('@sinkPassword', '_new_pass') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - -}} diff --git a/orb_tests/tests/sinks/8sinkVisuAndEditTags.js b/orb_tests/tests/sinks/8sinkVisuAndEditTags.js deleted file mode 100644 index 66c3319b9..000000000 --- a/orb_tests/tests/sinks/8sinkVisuAndEditTags.js +++ /dev/null @@ -1,42 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - - 'Sink Visualization and Edit Tags' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .click('@sinkNext') - .click('@sinkNext') - .click('.ml-1') - .verify.attributeEquals('@submit','aria-disabled', 'true') - .sinkEditTags('@key', '@value', 'new_key', 'new_value') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('new_key') - .sinkCheckEdition('new_value') - -}} diff --git a/orb_tests/tests/sinks/90sinkVisuAndEditUsername.js b/orb_tests/tests/sinks/90sinkVisuAndEditUsername.js deleted file mode 100644 index f9259d469..000000000 --- a/orb_tests/tests/sinks/90sinkVisuAndEditUsername.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Sink Visualization and Edit Username': (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkVisualization() - .click('.nb-close') - .sinkVisualization() - .click('.sink-edit-button') - .sinkEditPage() - .click('@sinkNext') - .sinkEditAttribute('@sinkUsername', '_new_usr') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - //BUG - //.sinkCheckEdition('_new_usr') - -}} diff --git a/orb_tests/tests/sinks/91sinkEditDescription.js b/orb_tests/tests/sinks/91sinkEditDescription.js deleted file mode 100644 index c1bf118ad..000000000 --- a/orb_tests/tests/sinks/91sinkEditDescription.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Sink Edit Description': (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkEdit() - .sinkEditAttribute('@sinkDescription','_n3w') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_n3w') - -}} diff --git a/orb_tests/tests/sinks/92sinkEditRH.js b/orb_tests/tests/sinks/92sinkEditRH.js deleted file mode 100644 index 2d07c81bc..000000000 --- a/orb_tests/tests/sinks/92sinkEditRH.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Edit Remote Host': (browser) => { - const sinks = browser.page.sinks(); - - - - sinks - .navigate() - .sinkEdit() - .click('@sinkNext') - .sinkEditAttribute('@sinkRemoteHost', '_n3w_rm') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_n3w_rm') - -}} diff --git a/orb_tests/tests/sinks/93sinkEditUsername.js b/orb_tests/tests/sinks/93sinkEditUsername.js deleted file mode 100644 index 4de8a0b61..000000000 --- a/orb_tests/tests/sinks/93sinkEditUsername.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Edit Username' : (browser) => { - const sinks = browser.page.sinks(); - - - sinks - .navigate() - .sinkEdit() - .click('@sinkNext') - .sinkEditAttribute('@sinkUsername', '_n3w_usr') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - // BUG - //.sinkCheckEdition('_n3w_usr') - -}} diff --git a/orb_tests/tests/sinks/94sinkEditPassword.js b/orb_tests/tests/sinks/94sinkEditPassword.js deleted file mode 100644 index d747a9a82..000000000 --- a/orb_tests/tests/sinks/94sinkEditPassword.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Edit Password': (browser) => { - const sinks = browser.page.sinks(); - - - sinks - .navigate() - .sinkEdit() - .click('@sinkNext') - .sinkEditAttribute('@sinkPassword', '_n3w_pass') - .click('@sinkNext') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - -}} diff --git a/orb_tests/tests/sinks/95sinkEditTags.js b/orb_tests/tests/sinks/95sinkEditTags.js deleted file mode 100644 index a32b67d59..000000000 --- a/orb_tests/tests/sinks/95sinkEditTags.js +++ /dev/null @@ -1,35 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Edit Tags' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkEdit() - .click('@sinkNext') - .click('@sinkNext') - .click('.ml-1') - .verify.attributeEquals('@submit','aria-disabled', 'true') - .sinkEditTags('@key', '@value', '_n3w_key', '_n3w_value') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_n3w_key') - .sinkCheckEdition('_n3w_value') -}} diff --git a/orb_tests/tests/sinks/96sinkEditAll.js b/orb_tests/tests/sinks/96sinkEditAll.js deleted file mode 100644 index 9caddeca2..000000000 --- a/orb_tests/tests/sinks/96sinkEditAll.js +++ /dev/null @@ -1,44 +0,0 @@ -module.exports = { - '@disabled': false, - - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - 'Sink Edit Description, Remote Host, Username, Password and Keys' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - .sinkEdit() - .sinkEditAttribute('@sinkDescription','_n33w') - .click('@sinkNext') - .sinkEditAttribute('@sinkRemoteHost', '_n33w_rm') - .sinkEditAttribute('@sinkUsername', '_n33w_usr') - .sinkEditAttribute('@sinkPassword', '_n33w_pass') - .click('@sinkNext') - .click('.ml-1') - .verify.attributeEquals('@submit','aria-disabled', 'true', "'Subimit' button is not enabled") - .sinkEditTags('@key', '@value', '_n33w_key', '_n33w_value') - .click('@sinkNext') - .click('@sinkNext') - .verify.containsText('span.title', 'Sink successfully updated', "Confirmation message is being correctly displayed") - .sinkCheckEdition('_n33w') - .sinkCheckEdition('_n33w_rm') - // BUG - //.sinkCheckEdition('_n33w_usr') - .sinkCheckEdition('_n33w_key') - .sinkCheckEdition('_n33w_value') - -}} diff --git a/orb_tests/tests/sinks/97removeSink.js b/orb_tests/tests/sinks/97removeSink.js deleted file mode 100644 index 0db8fb122..000000000 --- a/orb_tests/tests/sinks/97removeSink.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = { - '@disabled': false, - - before: (browser) => { - const login = browser.page.login(); - const topbar = browser.page.topbar(); - const email = 'tester@email.com'; - const pwd = '12345678'; - const maximizeWindowCallback = () => { - console.log('Window maximized'); - }; - browser.maximizeWindow(maximizeWindowCallback); - - login.with(email, pwd); - topbar.expectLoggedUser(email); - }, - - - 'Sink Delete' : (browser) => { - const sinks = browser.page.sinks(); - - sinks - .navigate() - // bug need to remove this pause - .pause(1000) - .countSinks(browser) - .sinkDelete() - .sinkManagementPage() - // bug need to remove this pause - .pause(1000) - .countSinks(browser) - .sinkManagementPage() - -}} From b6954be9fd2eff5e800cd49247ed1030d8a8c462 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:07:15 -0300 Subject: [PATCH 046/115] fix(sinker): redis event sink config for legacy pipeline (#2421) fix(sinker): redis event sink config for legacy pipeline (#2421) --- sinker/config/types.go | 14 ++++++++++++++ sinker/redis/consumer/streams.go | 28 ++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/sinker/config/types.go b/sinker/config/types.go index 122a3ced3..85824f73e 100644 --- a/sinker/config/types.go +++ b/sinker/config/types.go @@ -13,6 +13,7 @@ type SinkConfig struct { SinkID string `json:"sink_id"` OwnerID string `json:"owner_id"` Url string `json:"remote_host"` + AuthType string `json:"type"` User string `json:"username"` Password string `json:"password"` Opentelemetry string `json:"opentelemetry"` @@ -21,6 +22,19 @@ type SinkConfig struct { LastRemoteWrite time.Time `json:"last_remote_write,omitempty"` } +// SinkConfigParser to be compatible with new sinks config is coming from eventbus +type SinkConfigParser struct { + Authentication struct { + Password string `json:"password"` + Type string `json:"type"` + Username string `json:"username"` + } `json:"authentication"` + Exporter struct { + RemoteHost string `json:"remote_host"` + } `json:"exporter"` + OpenTelemetry string `json:"opentelemetry"` +} + const ( Unknown PrometheusState = iota Active diff --git a/sinker/redis/consumer/streams.go b/sinker/redis/consumer/streams.go index c2de74f22..757ab3109 100644 --- a/sinker/redis/consumer/streams.go +++ b/sinker/redis/consumer/streams.go @@ -161,8 +161,9 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err if err != nil { return err } + var cfgParser config.SinkConfigParser var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfg); err != nil { + if err := json.Unmarshal(data, &cfgParser); err != nil { return err } @@ -171,13 +172,17 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err if err != nil { return err } - sinkConfig.Url = cfg.Url - sinkConfig.User = cfg.User - sinkConfig.Password = cfg.Password + sinkConfig.AuthType = cfgParser.Authentication.Type + sinkConfig.User = cfgParser.Authentication.Username + sinkConfig.Password = cfgParser.Authentication.Password + sinkConfig.Url = cfgParser.Exporter.RemoteHost + sinkConfig.Opentelemetry = cfgParser.OpenTelemetry if sinkConfig.OwnerID == "" { sinkConfig.OwnerID = e.owner } - + if sinkConfig.SinkID == "" { + sinkConfig.SinkID = e.sinkID + } err = es.configRepo.Edit(sinkConfig) if err != nil { return err @@ -185,6 +190,11 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err } else { cfg.SinkID = e.sinkID cfg.OwnerID = e.owner + cfg.AuthType = cfgParser.Authentication.Type + cfg.User = cfgParser.Authentication.Username + cfg.Password = cfgParser.Authentication.Password + cfg.Url = cfgParser.Exporter.RemoteHost + cfg.Opentelemetry = cfgParser.OpenTelemetry err = es.configRepo.Add(cfg) if err != nil { return err @@ -198,13 +208,19 @@ func (es eventStore) handleSinksCreate(_ context.Context, e updateSinkEvent) err if err != nil { return err } + var cfgParser config.SinkConfigParser var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfg); err != nil { + if err := json.Unmarshal(data, &cfgParser); err != nil { return err } cfg.SinkID = e.sinkID cfg.OwnerID = e.owner cfg.State = config.Unknown + cfg.AuthType = cfgParser.Authentication.Type + cfg.User = cfgParser.Authentication.Username + cfg.Password = cfgParser.Authentication.Password + cfg.Url = cfgParser.Exporter.RemoteHost + cfg.Opentelemetry = cfgParser.OpenTelemetry err = es.configRepo.Add(cfg) if err != nil { return err From 89da7d00c25ea46cf2701698af2e0031b50635c5 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Tue, 20 Jun 2023 20:57:04 -0300 Subject: [PATCH 047/115] fix(sinker): redis to new sinkconfig structure (#2422) fix(sinker): redis to new sinkconfig structure (#2422) --- sinker/config/types.go | 24 ++--- sinker/config_state_check.go | 2 +- sinker/message_handler.go | 8 +- sinker/redis/consumer/streams.go | 27 ++--- sinker/redis/sinker_test.go | 164 ------------------------------- 5 files changed, 21 insertions(+), 204 deletions(-) delete mode 100644 sinker/redis/sinker_test.go diff --git a/sinker/config/types.go b/sinker/config/types.go index 85824f73e..53dfe5b93 100644 --- a/sinker/config/types.go +++ b/sinker/config/types.go @@ -9,30 +9,22 @@ import ( "time" ) -type SinkConfig struct { - SinkID string `json:"sink_id"` - OwnerID string `json:"owner_id"` - Url string `json:"remote_host"` - AuthType string `json:"type"` - User string `json:"username"` - Password string `json:"password"` - Opentelemetry string `json:"opentelemetry"` - State PrometheusState `json:"state,omitempty"` - Msg string `json:"msg,omitempty"` - LastRemoteWrite time.Time `json:"last_remote_write,omitempty"` -} - // SinkConfigParser to be compatible with new sinks config is coming from eventbus -type SinkConfigParser struct { +type SinkConfig struct { + SinkID string `json:"sink_id"` + OwnerID string `json:"owner_id"` Authentication struct { - Password string `json:"password"` Type string `json:"type"` + Password string `json:"password"` Username string `json:"username"` } `json:"authentication"` Exporter struct { RemoteHost string `json:"remote_host"` } `json:"exporter"` - OpenTelemetry string `json:"opentelemetry"` + OpenTelemetry string `json:"opentelemetry"` + State PrometheusState `json:"state,omitempty"` + Msg string `json:"msg,omitempty"` + LastRemoteWrite time.Time `json:"last_remote_write,omitempty"` } const ( diff --git a/sinker/config_state_check.go b/sinker/config_state_check.go index c905f892b..4eb7f2af8 100644 --- a/sinker/config_state_check.go +++ b/sinker/config_state_check.go @@ -35,7 +35,7 @@ func (svc *SinkerService) checkState(_ time.Time) { // Set idle if the sinker is more than 30 minutes not sending metrics (Remove from Redis) if cfg.LastRemoteWrite.Add(DefaultTimeout).Before(time.Now()) { if cfg.State == config.Active { - if cfg.Opentelemetry != "enabled" { + if cfg.OpenTelemetry != "enabled" { if err := svc.sinkerCache.Remove(cfg.OwnerID, cfg.SinkID); err != nil { svc.logger.Error("error updating sink config cache", zap.Error(err)) return diff --git a/sinker/message_handler.go b/sinker/message_handler.go index c61d1d484..fa1c060eb 100644 --- a/sinker/message_handler.go +++ b/sinker/message_handler.go @@ -29,12 +29,12 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner return err } ctx := context.Background() - if cfgRepo.Opentelemetry == "enabled" { + if cfgRepo.OpenTelemetry == "enabled" { svc.logger.Info("deprecate warning opentelemetry sink scraping legacy agent", zap.String("sink-ID", cfgRepo.SinkID)) ctx = context.WithValue(ctx, "deprecation", "opentelemetry") } cfg := prometheus.NewConfig( - prometheus.WriteURLOption(cfgRepo.Url), + prometheus.WriteURLOption(cfgRepo.Exporter.RemoteHost), ) promClient, err := prometheus.NewClient(cfg) @@ -44,7 +44,7 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner } var headers = make(map[string]string) - headers["Authorization"] = svc.encodeBase64(cfgRepo.User, cfgRepo.Password) + headers["Authorization"] = svc.encodeBase64(cfgRepo.Authentication.Username, cfgRepo.Authentication.Password) result, writeErr := promClient.WriteTimeSeries(ctx, tsList, prometheus.WriteOptions{Headers: headers}) if err := error(writeErr); err != nil { if cfgRepo.Msg != fmt.Sprint(err) { @@ -62,7 +62,7 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner return err } - svc.logger.Debug("successful sink", zap.Int("payload_size_b", result.PayloadSize), zap.String("sink_id", sinkID), zap.String("url", cfgRepo.Url), zap.String("user", cfgRepo.User)) + svc.logger.Debug("successful sink", zap.Int("payload_size_b", result.PayloadSize), zap.String("sink_id", sinkID), zap.String("url", cfgRepo.Exporter.RemoteHost), zap.String("user", cfgRepo.Authentication.Username)) if cfgRepo.State != config.Active { cfgRepo.State = config.Active diff --git a/sinker/redis/consumer/streams.go b/sinker/redis/consumer/streams.go index 757ab3109..95be472f5 100644 --- a/sinker/redis/consumer/streams.go +++ b/sinker/redis/consumer/streams.go @@ -161,9 +161,8 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err if err != nil { return err } - var cfgParser config.SinkConfigParser var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfgParser); err != nil { + if err := json.Unmarshal(data, &cfg); err != nil { return err } @@ -172,11 +171,11 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err if err != nil { return err } - sinkConfig.AuthType = cfgParser.Authentication.Type - sinkConfig.User = cfgParser.Authentication.Username - sinkConfig.Password = cfgParser.Authentication.Password - sinkConfig.Url = cfgParser.Exporter.RemoteHost - sinkConfig.Opentelemetry = cfgParser.OpenTelemetry + sinkConfig.Authentication.Type = cfg.Authentication.Type + sinkConfig.Authentication.Username = cfg.Authentication.Username + sinkConfig.Authentication.Password = cfg.Authentication.Password + sinkConfig.Exporter.RemoteHost = cfg.Exporter.RemoteHost + sinkConfig.OpenTelemetry = cfg.OpenTelemetry if sinkConfig.OwnerID == "" { sinkConfig.OwnerID = e.owner } @@ -188,13 +187,9 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err return err } } else { + cfg.State = config.Unknown cfg.SinkID = e.sinkID cfg.OwnerID = e.owner - cfg.AuthType = cfgParser.Authentication.Type - cfg.User = cfgParser.Authentication.Username - cfg.Password = cfgParser.Authentication.Password - cfg.Url = cfgParser.Exporter.RemoteHost - cfg.Opentelemetry = cfgParser.OpenTelemetry err = es.configRepo.Add(cfg) if err != nil { return err @@ -208,19 +203,13 @@ func (es eventStore) handleSinksCreate(_ context.Context, e updateSinkEvent) err if err != nil { return err } - var cfgParser config.SinkConfigParser var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfgParser); err != nil { + if err := json.Unmarshal(data, &cfg); err != nil { return err } cfg.SinkID = e.sinkID cfg.OwnerID = e.owner cfg.State = config.Unknown - cfg.AuthType = cfgParser.Authentication.Type - cfg.User = cfgParser.Authentication.Username - cfg.Password = cfgParser.Authentication.Password - cfg.Url = cfgParser.Exporter.RemoteHost - cfg.Opentelemetry = cfgParser.OpenTelemetry err = es.configRepo.Add(cfg) if err != nil { return err diff --git a/sinker/redis/sinker_test.go b/sinker/redis/sinker_test.go deleted file mode 100644 index 1dd692817..000000000 --- a/sinker/redis/sinker_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package redis_test - -import ( - "fmt" - "reflect" - "testing" - "time" - - "github.com/mainflux/mainflux/pkg/uuid" - "github.com/orb-community/orb/pkg/errors" - config2 "github.com/orb-community/orb/sinker/config" - "github.com/orb-community/orb/sinker/redis" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var idProvider = uuid.New() - -func TestSinkerConfigSave(t *testing.T) { - sinkerCache := redis.NewSinkerCache(redisClient, logger) - config := config2.SinkConfig{ - SinkID: "123", - OwnerID: "test", - Url: "localhost", - User: "user", - Password: "password", - State: 0, - Msg: "", - LastRemoteWrite: time.Time{}, - } - - err := sinkerCache.Add(config) - require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) - - cases := map[string]struct { - config config2.SinkConfig - err error - }{ - "Save sinker to cache": { - config: config2.SinkConfig{ - SinkID: "124", - OwnerID: "test", - Url: "localhost", - User: "user", - Password: "password", - State: 0, - Msg: "", - LastRemoteWrite: time.Time{}, - }, - err: nil, - }, - "Save already cached sinker config to cache": { - config: config, - err: nil, - }, - } - - for desc, tc := range cases { - t.Run(desc, func(t *testing.T) { - err := sinkerCache.Add(tc.config) - assert.Nil(t, err, fmt.Sprintf("%s: expected %s got %s", desc, tc.err, err)) - }) - } -} - -func TestGetSinkerConfig(t *testing.T) { - sinkerCache := redis.NewSinkerCache(redisClient, logger) - config := config2.SinkConfig{ - SinkID: "123", - OwnerID: "test", - Url: "localhost", - User: "user", - Password: "password", - State: 0, - Msg: "", - LastRemoteWrite: time.Time{}, - } - - err := sinkerCache.Add(config) - require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) - - cases := map[string]struct { - sinkID string - config config2.SinkConfig - err error - }{ - "Get Config by existing sinker-key": { - sinkID: "123", - config: config, - err: nil, - }, - "Get Config by non-existing sinker-key": { - sinkID: "000", - config: config2.SinkConfig{}, - err: errors.ErrNotFound, - }, - } - - for desc, tc := range cases { - t.Run(desc, func(t *testing.T) { - sinkConfig, err := sinkerCache.Get(tc.config.OwnerID, tc.sinkID) - assert.True(t, reflect.DeepEqual(tc.config, sinkConfig), fmt.Sprintf("%s: expected %v got %v", desc, tc.config, sinkConfig)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s", desc, tc.err, err)) - }) - } -} - -func TestGetAllSinkerConfig(t *testing.T) { - sinkerCache := redis.NewSinkerCache(redisClient, logger) - - sinksConfig := map[string]struct { - config config2.SinkConfig - }{ - "config 1": { - config: config2.SinkConfig{ - SinkID: "123", - OwnerID: "test", - Url: "localhost", - User: "user", - Password: "password", - State: 0, - Msg: "", - LastRemoteWrite: time.Time{}, - }, - }, - "config 2": { - config: config2.SinkConfig{ - SinkID: "134", - OwnerID: "test", - Url: "localhost", - User: "user", - Password: "password", - State: 0, - Msg: "", - LastRemoteWrite: time.Time{}, - }, - }, - } - - for _, val := range sinksConfig { - err := sinkerCache.Add(val.config) - require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) - } - - cases := map[string]struct { - size int - ownerID string - err error - }{ - "Get Config by existing sinker-key": { - size: 2, - ownerID: "test", - err: nil, - }, - } - - for desc, tc := range cases { - t.Run(desc, func(t *testing.T) { - sinksConfig, err := sinkerCache.GetAll(tc.ownerID) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error: %s", desc, err)) - assert.GreaterOrEqual(t, len(sinksConfig), tc.size, fmt.Sprintf("%s: expected %d got %d", desc, tc.size, len(sinksConfig))) - }) - } -} From 3fce46591b9e4862a7f826c8b8c798d11b80dbac Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 21 Jun 2023 08:53:56 -0300 Subject: [PATCH 048/115] improvement(orb-ui): version filter agent list page (#2417) --- ui/src/app/pages/fleet/agents/list/agent.list.component.ts | 6 ++++++ .../shared/components/delete/delete.selected.component.html | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 3cb2f77f8..73c96903e 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -151,6 +151,12 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe type: FilterTypes.MultiSelect, options: Object.values(AgentPolicyAggStates).map((value) => value as string), }, + { + name: 'Version', + prop: 'version', + filter: filterString, + type: FilterTypes.Input, + }, ]; this.filteredAgents$ = this.filters.createFilteredList()( diff --git a/ui/src/app/shared/components/delete/delete.selected.component.html b/ui/src/app/shared/components/delete/delete.selected.component.html index ae41989aa..61300a02a 100644 --- a/ui/src/app/shared/components/delete/delete.selected.component.html +++ b/ui/src/app/shared/components/delete/delete.selected.component.html @@ -12,7 +12,7 @@

Are you sure you want to delete a total of {{ selected?.length }} {{ elementName }}? This action cannot be undone.

- {{ item.name }} {{ item.state }} {{ item.usage }} + {{ item.name }} {{ item.state | titlecase }} {{ item.usage | titlecase }}

*To confirm, type the amount of {{ elementName }} to be delete.

Date: Wed, 21 Jun 2023 08:54:10 -0300 Subject: [PATCH 049/115] fix(orb-ui): not cleaning the selected elements after the action (#2418) --- .../policies.agent/list/agent.policy.list.component.ts | 2 +- ui/src/app/pages/fleet/agents/list/agent.list.component.ts | 3 ++- .../app/pages/fleet/groups/list/agent.group.list.component.ts | 2 +- ui/src/app/pages/sinks/list/sink.list.component.ts | 2 +- ui/src/app/pages/sinks/view/sink.view.component.ts | 1 - 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index ba3340f8c..3213b69ae 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -321,6 +321,7 @@ export class AgentPolicyListComponent .onClose.subscribe((confirm) => { if (confirm) { this.deleteSelectedAgentsPolicy(); + this.selected = []; this.orb.refreshNow(); } }); @@ -349,7 +350,6 @@ export class AgentPolicyListComponent } } } - console.log(this.selected); } public getChecked(row: any): boolean { diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 73c96903e..f294f0e24 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -289,7 +289,6 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe } const reset = this.selected.filter((e) => e.resetable === false); this.canResetAgents = reset.length > 0 ? true : false; - console.log(this.selected); } @@ -351,6 +350,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe .onClose.subscribe((confirm) => { if (confirm) { this.deleteSelectedAgents(); + this.selected = []; this.orb.refreshNow(); } }); @@ -385,6 +385,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe this.agentService.resetAgent(agent.id).subscribe(); }) this.notifyResetSuccess(); + this.selected = []; this.isResetting = false; } } diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts index 7766f8311..a0486fb63 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts @@ -269,6 +269,7 @@ export class AgentGroupListComponent .onClose.subscribe((confirm) => { if (confirm) { this.deleteSelectedAgentGroups(); + this.selected = []; this.orb.refreshNow(); } }); @@ -317,7 +318,6 @@ export class AgentGroupListComponent } } } - console.log(this.selected); } public getChecked(row: any): boolean { diff --git a/ui/src/app/pages/sinks/list/sink.list.component.ts b/ui/src/app/pages/sinks/list/sink.list.component.ts index 393efecb7..6b19fee53 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.ts +++ b/ui/src/app/pages/sinks/list/sink.list.component.ts @@ -274,6 +274,7 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes .onClose.subscribe((confirm) => { if (confirm) { this.deleteSelectedSinks(); + this.selected = []; this.orb.refreshNow(); } }); @@ -318,7 +319,6 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes } } } - console.log(this.selected); } public getChecked(row: any): boolean { diff --git a/ui/src/app/pages/sinks/view/sink.view.component.ts b/ui/src/app/pages/sinks/view/sink.view.component.ts index 86e3b6a4c..fc5cb1410 100644 --- a/ui/src/app/pages/sinks/view/sink.view.component.ts +++ b/ui/src/app/pages/sinks/view/sink.view.component.ts @@ -112,7 +112,6 @@ export class SinkViewComponent implements OnInit, OnChanges, OnDestroy { } as Sink; } - console.log(payload); try { this.sinks.editSink(payload).subscribe((resp) => { this.discard(); From b1090412246e3b123951667111b3399d8dfb213f Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 21 Jun 2023 08:54:28 -0300 Subject: [PATCH 050/115] feat(orb-ui) #685 All list pages, header checkbox (#2419) --- ui/src/app/common/services/filter.service.ts | 8 +++-- .../list/agent.policy.list.component.html | 6 +++- .../list/agent.policy.list.component.ts | 34 ++++++++++++++++-- .../agents/list/agent.list.component.html | 6 +++- .../fleet/agents/list/agent.list.component.ts | 36 ++++++++++++++++++- .../groups/add/agent.group.add.component.ts | 1 - .../list/agent.group.list.component.html | 6 +++- .../groups/list/agent.group.list.component.ts | 30 +++++++++++++++- .../pages/sinks/list/sink.list.component.html | 4 +++ .../pages/sinks/list/sink.list.component.ts | 30 +++++++++++++++- .../delete/delete.selected.component.scss | 2 +- 11 files changed, 149 insertions(+), 14 deletions(-) diff --git a/ui/src/app/common/services/filter.service.ts b/ui/src/app/common/services/filter.service.ts index 3fe36f530..329f8ee18 100644 --- a/ui/src/app/common/services/filter.service.ts +++ b/ui/src/app/common/services/filter.service.ts @@ -90,10 +90,12 @@ export class FilterService { const filterDef = filterOptions.find( (_item) => _item.name === _filter.name, ); - const {filter: filterFn, prop, exact} = filterDef; - const result = + if (filterDef) { + const {filter: filterFn, prop, exact} = filterDef; + const result = !!filterFn && filterFn(value, prop, paramValue, exact); - return result; + return result; + } }); }); diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index cebce7010..ffe641d42 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -147,4 +147,8 @@

All Policies

- \ No newline at end of file + + + + + diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts index 3213b69ae..3681e6821 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.ts @@ -28,7 +28,7 @@ import { NotificationsService } from 'app/common/services/notifications/notifica import { OrbService } from 'app/common/services/orb.service'; import { AgentPolicyDeleteComponent } from 'app/pages/datasets/policies.agent/delete/agent.policy.delete.component'; import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; -import { combineLatest, Observable } from 'rxjs'; +import { combineLatest, Observable, Subscription } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { STRINGS } from '../../../../../assets/text/strings'; @@ -50,6 +50,8 @@ export class AgentPolicyListComponent selected: any[] = []; + private policiesSubscription: Subscription; + @ViewChild('nameTemplateCell') nameTemplateCell: TemplateRef; @ViewChild('versionTemplateCell') versionTemplateCell: TemplateRef; @@ -60,6 +62,8 @@ export class AgentPolicyListComponent @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateHeader') checkboxTemplateHeader: TemplateRef; + tableSorts = [ { prop: 'name', @@ -92,7 +96,7 @@ export class AgentPolicyListComponent private filters: FilterService, ) { this.filters$ = this.filters.getFilters(); - + this.selected = []; this.policies$ = combineLatest([ this.orb.getPolicyListView(), this.orb.getDatasetListView() @@ -165,6 +169,9 @@ export class AgentPolicyListComponent } ngOnDestroy(): void { + if (this.policiesSubscription) { + this.policiesSubscription.unsubscribe(); + } this.orb.killPolling.next(); } @@ -193,6 +200,7 @@ export class AgentPolicyListComponent canAutoResize: true, sortable: false, cellTemplate: this.checkboxTemplateCell, + headerTemplate: this.checkboxTemplateHeader, }, { prop: 'name', @@ -356,5 +364,25 @@ export class AgentPolicyListComponent const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } -} + onHeaderCheckboxChange(event: any) { + if (event.target.checked && this.filteredPolicies$) { + this.policiesSubscription = this.filteredPolicies$.subscribe(rows => { + this.selected = []; + rows.forEach(row => { + const policySelected = { + id: row.id, + name: row.name, + usage: row.policy_usage, + } + this.selected.push(policySelected); + }); + }); + } else { + if (this.policiesSubscription) { + this.policiesSubscription.unsubscribe(); + } + this.selected = []; + } + } +} diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.html b/ui/src/app/pages/fleet/agents/list/agent.list.component.html index c6cf445ba..9a302499e 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.html +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.html @@ -171,6 +171,10 @@

All Agents

(change)="onCheckboxChange($event, row)"> + + + + All Agents > {{ value }} - \ No newline at end of file + diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index f294f0e24..173bd87dc 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -30,7 +30,7 @@ import { AgentDeleteComponent } from 'app/pages/fleet/agents/delete/agent.delete import { AgentDetailsComponent } from 'app/pages/fleet/agents/details/agent.details.component'; import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; import { STRINGS } from 'assets/text/strings'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { AgentResetComponent } from '../reset/agent.reset.component'; @@ -53,6 +53,9 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe canResetAgents: boolean; isResetting: boolean; + + private agentsSubscription: Subscription; + // templates @ViewChild('agentNameTemplateCell') agentNameTemplateCell: TemplateRef; @@ -72,6 +75,8 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe @ViewChild('agentVersionTemplateCell') agentVersionTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateHeader') checkboxTemplateHeader: TemplateRef; + tableSorts = [ { prop: 'name', @@ -167,6 +172,9 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe } ngOnDestroy() { + if (this.agentsSubscription) { + this.agentsSubscription.unsubscribe(); + } this.orb.killPolling.next(); } @@ -194,6 +202,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe canAutoResize: true, sortable: false, cellTemplate: this.checkboxTemplateCell, + headerTemplate: this.checkboxTemplateHeader, }, { prop: 'name', @@ -389,6 +398,31 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe this.isResetting = false; } } + + onHeaderCheckboxChange(event: any) { + if (event.target.checked && this.filteredAgents$) { + this.agentsSubscription = this.filteredAgents$.subscribe(rows => { + this.selected = []; + rows.forEach(row => { + const policySelected = { + id: row.id, + name: row.name, + state: row.state, + resetable: row.state === 'new' || row.state === 'offline' ? false : true, + } + this.selected.push(policySelected); + }); + }); + } else { + if (this.agentsSubscription) { + this.agentsSubscription.unsubscribe(); + } + this.selected = []; + } + const reset = this.selected.filter((e) => e.resetable === false); + this.canResetAgents = reset.length > 0 ? true : false; + } + openDetailsModal(row: any) { this.dialogService .open(AgentDetailsComponent, { diff --git a/ui/src/app/pages/fleet/groups/add/agent.group.add.component.ts b/ui/src/app/pages/fleet/groups/add/agent.group.add.component.ts index 5220af89d..b63301529 100644 --- a/ui/src/app/pages/fleet/groups/add/agent.group.add.component.ts +++ b/ui/src/app/pages/fleet/groups/add/agent.group.add.component.ts @@ -279,7 +279,6 @@ export class AgentGroupAddComponent const payload = this.wrapPayload(false); // // remove line bellow - // console.log(payload) if (this.isEdit) { this.agentGroupsService .editAgentGroup({ ...payload, id: this.agentGroupID }) diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html index d9670447f..e7b937953 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html @@ -137,4 +137,8 @@

{{ strings.list.header }}

- \ No newline at end of file + + + + + diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts index a0486fb63..d3261ece2 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.ts @@ -31,7 +31,7 @@ import { AgentGroupDeleteComponent } from 'app/pages/fleet/groups/delete/agent.g import { AgentGroupDetailsComponent } from 'app/pages/fleet/groups/details/agent.group.details.component'; import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; import { STRINGS } from 'assets/text/strings'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; @Component({ selector: 'ngx-agent-group-list-component', @@ -52,6 +52,8 @@ export class AgentGroupListComponent selected: any[] = []; + private groupsSubscription: Subscription; + // templates @ViewChild('agentGroupNameTemplateCell') agentGroupNameTemplateCell: TemplateRef; @@ -66,6 +68,8 @@ export class AgentGroupListComponent @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateHeader') checkboxTemplateHeader: TemplateRef; + filterValue = null; tableSorts = [ @@ -139,6 +143,9 @@ export class AgentGroupListComponent } ngOnDestroy(): void { + if (this.groupsSubscription) { + this.groupsSubscription.unsubscribe(); + } this.orb.killPolling.next(); } @@ -166,6 +173,7 @@ export class AgentGroupListComponent canAutoResize: true, sortable: false, cellTemplate: this.checkboxTemplateCell, + headerTemplate: this.checkboxTemplateHeader, }, { prop: 'name', @@ -324,4 +332,24 @@ export class AgentGroupListComponent const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } + + onHeaderCheckboxChange(event: any) { + if (event.target.checked && this.filteredGroups$) { + this.groupsSubscription = this.filteredGroups$.subscribe(rows => { + this.selected = []; + rows.forEach(row => { + const policySelected = { + id: row.id, + name: row.name, + } + this.selected.push(policySelected); + }); + }); + } else { + if (this.groupsSubscription) { + this.groupsSubscription.unsubscribe(); + } + this.selected = []; + } + } } diff --git a/ui/src/app/pages/sinks/list/sink.list.component.html b/ui/src/app/pages/sinks/list/sink.list.component.html index 8ac3a1764..bd84e0bdb 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.html +++ b/ui/src/app/pages/sinks/list/sink.list.component.html @@ -131,3 +131,7 @@

{{ strings.list.header }}

+ + + + diff --git a/ui/src/app/pages/sinks/list/sink.list.component.ts b/ui/src/app/pages/sinks/list/sink.list.component.ts index 6b19fee53..1486c5c02 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.ts +++ b/ui/src/app/pages/sinks/list/sink.list.component.ts @@ -33,7 +33,7 @@ import { SinksService } from 'app/common/services/sinks/sinks.service'; import { SinkDeleteComponent } from 'app/pages/sinks/delete/sink.delete.component'; import { SinkDetailsComponent } from 'app/pages/sinks/details/sink.details.component'; import { STRINGS } from 'assets/text/strings'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { DeleteSelectedComponent } from 'app/shared/components/delete/delete.selected.component'; @Component({ @@ -52,6 +52,8 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes selected: any[] = []; + private sinksSubscription: Subscription; + // templates @ViewChild('sinkNameTemplateCell') sinkNameTemplateCell: TemplateRef; @@ -63,6 +65,8 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes @ViewChild('checkboxTemplateCell') checkboxTemplateCell: TemplateRef; + @ViewChild('checkboxTemplateHeader') checkboxTemplateHeader: TemplateRef; + tableSorts = [ { prop: 'name', @@ -139,6 +143,9 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes } ngOnDestroy(): void { + if (this.sinksSubscription) { + this.sinksSubscription.unsubscribe(); + } this.orb.killPolling.next(); } @@ -166,6 +173,7 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes canAutoResize: true, sortable: false, cellTemplate: this.checkboxTemplateCell, + headerTemplate: this.checkboxTemplateHeader, }, { prop: 'name', @@ -325,4 +333,24 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes const item = this.selected.filter((e) => e.id === row.id); return item.length > 0 ? true : false; } + onHeaderCheckboxChange(event: any) { + if (event.target.checked && this.filteredSinks$) { + this.sinksSubscription = this.filteredSinks$.subscribe(rows => { + this.selected = []; + rows.forEach(row => { + const sinkSelected = { + id: row.id, + name: row.name, + state: row.state, + } + this.selected.push(sinkSelected); + }); + }); + } else { + if (this.sinksSubscription) { + this.sinksSubscription.unsubscribe(); + } + this.selected = []; + } + } } diff --git a/ui/src/app/shared/components/delete/delete.selected.component.scss b/ui/src/app/shared/components/delete/delete.selected.component.scss index 00c2942e0..798825495 100644 --- a/ui/src/app/shared/components/delete/delete.selected.component.scss +++ b/ui/src/app/shared/components/delete/delete.selected.component.scss @@ -1,6 +1,6 @@ nb-card { max-width: 38rem; - + max-height: 50rem; nb-card-header { background: #232940; color: #969fb9; From 87d655ac291f65c8379ae6580d278cee177bee30 Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:01:35 -0300 Subject: [PATCH 051/115] adding test in sinker redis (#2423) adding test in sinker redis (#2423) --- sinker/redis/sinker_test.go | 170 ++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 sinker/redis/sinker_test.go diff --git a/sinker/redis/sinker_test.go b/sinker/redis/sinker_test.go new file mode 100644 index 000000000..0ee54eb6c --- /dev/null +++ b/sinker/redis/sinker_test.go @@ -0,0 +1,170 @@ +package redis_test + +import ( + "fmt" + "reflect" + "testing" + "time" + + "github.com/mainflux/mainflux/pkg/uuid" + "github.com/orb-community/orb/pkg/errors" + config2 "github.com/orb-community/orb/sinker/config" + "github.com/orb-community/orb/sinker/redis" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var idProvider = uuid.New() + +func TestSinkerConfigSave(t *testing.T) { + sinkerCache := redis.NewSinkerCache(redisClient, logger) + var config config2.SinkConfig + config.SinkID = "123" + config.OwnerID = "test" + config.Authentication.Type = "basic_auth" + config.Authentication.Username = "user" + config.Authentication.Password = "password" + config.Exporter.RemoteHost = "localhost" + config.State = 0 + config.Msg = "" + config.LastRemoteWrite = time.Time{} + + err := sinkerCache.Add(config) + require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) + + cases := map[string]struct { + config config2.SinkConfig + err error + }{ + "Save sinker to cache": { + config: config2.SinkConfig{ + SinkID: "124", + OwnerID: "test", + Exporter: config.Exporter, + Authentication: config.Authentication, + State: 0, + Msg: "", + LastRemoteWrite: time.Time{}, + }, + err: nil, + }, + "Save already cached sinker config to cache": { + config: config, + err: nil, + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + err := sinkerCache.Add(tc.config) + assert.Nil(t, err, fmt.Sprintf("%s: expected %s got %s", desc, tc.err, err)) + }) + } +} + +func TestGetSinkerConfig(t *testing.T) { + sinkerCache := redis.NewSinkerCache(redisClient, logger) + var config config2.SinkConfig + config.SinkID = "123" + config.OwnerID = "test" + config.Authentication.Type = "basic_auth" + config.Authentication.Username = "user" + config.Authentication.Password = "password" + config.Exporter.RemoteHost = "localhost" + config.State = 0 + config.Msg = "" + config.LastRemoteWrite = time.Time{} + + err := sinkerCache.Add(config) + require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) + + cases := map[string]struct { + sinkID string + config config2.SinkConfig + err error + }{ + "Get Config by existing sinker-key": { + sinkID: "123", + config: config, + err: nil, + }, + "Get Config by non-existing sinker-key": { + sinkID: "000", + config: config2.SinkConfig{}, + err: errors.ErrNotFound, + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + sinkConfig, err := sinkerCache.Get(tc.config.OwnerID, tc.sinkID) + assert.True(t, reflect.DeepEqual(tc.config, sinkConfig), fmt.Sprintf("%s: expected %v got %v", desc, tc.config, sinkConfig)) + assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s", desc, tc.err, err)) + }) + } +} + +func TestGetAllSinkerConfig(t *testing.T) { + sinkerCache := redis.NewSinkerCache(redisClient, logger) + var config config2.SinkConfig + config.SinkID = "123" + config.OwnerID = "test" + config.Authentication.Type = "basic_auth" + config.Authentication.Username = "user" + config.Authentication.Password = "password" + config.Exporter.RemoteHost = "localhost" + config.State = 0 + config.Msg = "" + config.LastRemoteWrite = time.Time{} + sinksConfig := map[string]struct { + config config2.SinkConfig + }{ + "config 1": { + config: config2.SinkConfig{ + SinkID: "123", + OwnerID: "test", + Exporter: config.Exporter, + Authentication: config.Authentication, + State: 0, + Msg: "", + LastRemoteWrite: time.Time{}, + }, + }, + "config 2": { + config: config2.SinkConfig{ + SinkID: "134", + OwnerID: "test", + Exporter: config.Exporter, + Authentication: config.Authentication, + State: 0, + Msg: "", + LastRemoteWrite: time.Time{}, + }, + }, + } + + for _, val := range sinksConfig { + err := sinkerCache.Add(val.config) + require.Nil(t, err, fmt.Sprintf("save sinker config to cache: expected nil got %s", err)) + } + + cases := map[string]struct { + size int + ownerID string + err error + }{ + "Get Config by existing sinker-key": { + size: 2, + ownerID: "test", + err: nil, + }, + } + + for desc, tc := range cases { + t.Run(desc, func(t *testing.T) { + sinksConfig, err := sinkerCache.GetAll(tc.ownerID) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error: %s", desc, err)) + assert.GreaterOrEqual(t, len(sinksConfig), tc.size, fmt.Sprintf("%s: expected %d got %d", desc, tc.size, len(sinksConfig))) + }) + } +} From 12f2bce303b83b2fbeb5b936013950c4f375e7ab Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:19:05 -0300 Subject: [PATCH 052/115] feat(ci): add dependabot (#2407) feat(ci): add dependabot (#2407) --- .github/dependabot.yml | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..d05fc9763 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,52 @@ +version: 2 + +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-type: "all" + commit-message: + prefix: "fix" + open-pull-requests-limit: 10 + + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-type: "all" + commit-message: + prefix: "fix" + open-pull-requests-limit: 10 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-type: "all" + commit-message: + prefix: "fix" + open-pull-requests-limit: 10 + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-type: "all" + commit-message: + prefix: "fix" + open-pull-requests-limit: 10 + + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-type: "all" + commit-message: + prefix: "fix" + open-pull-requests-limit: 10 From 0aeffa710d16b32a4b45983ebd029fe5516b6ed5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:46:17 -0300 Subject: [PATCH 053/115] fix: bump docker/login-action from 1 to 2 (#2426) fix: bump docker/login-action from 1 to 2 (#2426) --- .github/workflows/go-develop.yml | 2 +- .github/workflows/go-main.yml | 2 +- .github/workflows/go-production.yml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/go-develop.yml b/.github/workflows/go-develop.yml index 02cd7b8e7..0307f873d 100644 --- a/.github/workflows/go-develop.yml +++ b/.github/workflows/go-develop.yml @@ -599,7 +599,7 @@ jobs: git push origin develop - name: Login to Docker Hub orbcommunity - uses: docker/login-action@v1 + uses: docker/login-action@v2 if: github.event_name != 'pull_request' with: username: ${{ secrets.ORB_DOCKERHUB_USERNAME }} diff --git a/.github/workflows/go-main.yml b/.github/workflows/go-main.yml index 0f7c4c045..39e1e8edc 100644 --- a/.github/workflows/go-main.yml +++ b/.github/workflows/go-main.yml @@ -373,7 +373,7 @@ jobs: run: make ui - name: Login to Docker Hub orbcommunity - uses: docker/login-action@v1 + uses: docker/login-action@v2 if: github.event_name != 'pull_request' with: username: ${{ secrets.ORB_DOCKERHUB_USERNAME }} diff --git a/.github/workflows/go-production.yml b/.github/workflows/go-production.yml index 61298d9bd..4de4801a7 100644 --- a/.github/workflows/go-production.yml +++ b/.github/workflows/go-production.yml @@ -197,7 +197,7 @@ jobs: fi - name: Login to Docker Hub orbcommunity if: github.event_name != 'pull_request' - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} @@ -412,7 +412,7 @@ jobs: git push origin main - name: Login to Docker Hub orbcommunity - uses: docker/login-action@v1 + uses: docker/login-action@v2 if: github.event_name != 'pull_request' with: username: ${{ secrets.ORB_DOCKERHUB_USERNAME }} @@ -528,7 +528,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Login to Docker Hub orbcommunity - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: username: ${{ secrets.ORB_DOCKERHUB_USERNAME }} password: ${{ secrets.ORB_DOCKERHUB_TOKEN }} From 1292c83f06bae77b211ec630cd84e3401a626d50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:46:59 -0300 Subject: [PATCH 054/115] fix: bump actions/checkout from 2 to 3 (#2433) fix: bump actions/checkout from 2 to 3 (#2433) --- .github/workflows/go-develop.yml | 36 ++++++++++++++--------------- .github/workflows/go-main.yml | 32 ++++++++++++------------- .github/workflows/go-production.yml | 36 ++++++++++++++--------------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/.github/workflows/go-develop.yml b/.github/workflows/go-develop.yml index 0307f873d..2d82ba152 100644 --- a/.github/workflows/go-develop.yml +++ b/.github/workflows/go-develop.yml @@ -21,7 +21,7 @@ jobs: docs: ${{ steps.filter.outputs.docs }} VERSION: ${{ env.VERSION }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -80,7 +80,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: name: workspace @@ -112,7 +112,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -151,7 +151,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -190,7 +190,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -229,7 +229,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -268,7 +268,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -307,7 +307,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -348,7 +348,7 @@ jobs: - test-agent runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -404,7 +404,7 @@ jobs: - test-fleet runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -431,7 +431,7 @@ jobs: - test-policies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -458,7 +458,7 @@ jobs: - test-sinker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -485,7 +485,7 @@ jobs: - test-sinks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -512,7 +512,7 @@ jobs: - test-maestro runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -538,7 +538,7 @@ jobs: - prebuild runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -569,7 +569,7 @@ jobs: - package-ui-dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -616,7 +616,7 @@ jobs: - package-ui runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build orb migrate service image if: ${{ needs.prebuild.outputs.migrate == 'true' }} @@ -648,7 +648,7 @@ jobs: runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Debug values run: | diff --git a/.github/workflows/go-main.yml b/.github/workflows/go-main.yml index 39e1e8edc..a3c25918d 100644 --- a/.github/workflows/go-main.yml +++ b/.github/workflows/go-main.yml @@ -20,7 +20,7 @@ jobs: ui: ${{ steps.filter.outputs.ui }} VERSION: ${{ env.VERSION }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -61,7 +61,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -74,7 +74,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -88,7 +88,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -102,7 +102,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -116,7 +116,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -130,7 +130,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -148,7 +148,7 @@ jobs: - test-agent runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -202,7 +202,7 @@ jobs: - test-fleet runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -228,7 +228,7 @@ jobs: - test-policies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -254,7 +254,7 @@ jobs: - test-sinker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -280,7 +280,7 @@ jobs: - test-sinks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -306,7 +306,7 @@ jobs: - test-maestro runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -331,7 +331,7 @@ jobs: - prebuild runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -362,7 +362,7 @@ jobs: - package-ui-dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -397,7 +397,7 @@ jobs: if: github.event_name != 'pull_request' steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/go-production.yml b/.github/workflows/go-production.yml index 4de4801a7..e19135431 100644 --- a/.github/workflows/go-production.yml +++ b/.github/workflows/go-production.yml @@ -20,7 +20,7 @@ jobs: ui: ${{ steps.filter.outputs.ui }} VERSION: ${{ env.VERSION }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -66,7 +66,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -80,7 +80,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -96,7 +96,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -110,7 +110,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -124,7 +124,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -138,7 +138,7 @@ jobs: runs-on: ubuntu-latest needs: prebuild steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v2 with: @@ -157,7 +157,7 @@ jobs: - test-agent runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -223,7 +223,7 @@ jobs: - test-fleet runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -249,7 +249,7 @@ jobs: - test-policies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -275,7 +275,7 @@ jobs: - test-sinker runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -301,7 +301,7 @@ jobs: - test-sinks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -327,7 +327,7 @@ jobs: - test-maestro runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -352,7 +352,7 @@ jobs: - prebuild runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dorny/paths-filter@v2 id: filter with: @@ -383,7 +383,7 @@ jobs: - package-ui-dependencies runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Get short commit hash to a variable id: commit_hash run: | @@ -435,7 +435,7 @@ jobs: runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Debug values run: | @@ -480,7 +480,7 @@ jobs: runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Generating changelog and post it in slack channel uses: ./.github/actions/slack-post with: @@ -495,7 +495,7 @@ jobs: runs-on: ubuntu-latest if: github.event_name != 'pull_request' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set branch name shell: bash From a146f11434cb84ab2a082deb6c1154ad5cb14927 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 10:49:29 -0300 Subject: [PATCH 055/115] fix: bump docker/build-push-action from 3 to 4 (#2428) fix: bump docker/build-push-action from 3 to 4 (#2428) --- .github/workflows/go-production.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go-production.yml b/.github/workflows/go-production.yml index e19135431..108470ff2 100644 --- a/.github/workflows/go-production.yml +++ b/.github/workflows/go-production.yml @@ -559,7 +559,7 @@ jobs: IMAGE_NAME: orbcommunity/orb-agent:latest IMAGE_NAME_2: orbcommunity/orb-agent:${{ env.VERSION }}-${{ steps.commit_hash.outputs.sha_short }} - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v4 with: builder: ${{ steps.buildx.outputs.name }} context: . From 056b9f5ed7b90b83463768d8263503f3969ba0a3 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 21 Jun 2023 14:06:56 -0300 Subject: [PATCH 056/115] fix(orb-ui): Active datasets table, add animation to expose all the sinks (#2449) --- .../pages/sinks/list/sink.list.component.ts | 2 +- .../policy-datasets.component.html | 11 ++++-- .../policy-datasets.component.scss | 39 +++++++++++++++++++ .../policy-datasets.component.ts | 7 ++-- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/ui/src/app/pages/sinks/list/sink.list.component.ts b/ui/src/app/pages/sinks/list/sink.list.component.ts index 1486c5c02..b2b6d3289 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.ts +++ b/ui/src/app/pages/sinks/list/sink.list.component.ts @@ -180,7 +180,7 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes name: 'Name', canAutoResize: true, resizeable: false, - flexGrow: 3, + flexGrow: 4, minWidth: 150, cellTemplate: this.sinkNameTemplateCell, }, diff --git a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html index 92cc66eb9..67fe28c86 100644 --- a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html +++ b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html @@ -52,10 +52,13 @@ - - - + + + + + diff --git a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss index b5818fb13..906d45a62 100644 --- a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss +++ b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss @@ -78,3 +78,42 @@ nb-card { } } +mat-nav-list{ + display: flex !important; + flex-direction: row; + flex-wrap: nowrap !important; + align-items: flex-start; + align-content: flex-start; + justify-content: flex-start; + + ::ng-deep > .mat-nav-list-wrapper { + display: flex !important; + flex-direction: row; + flex-wrap: nowrap !important; + align-items: flex-start; + align-content: flex-start; + justify-content: flex-start; + } + + &:hover { + animation-duration: 8s; + animation-name: slidetween; + animation-timing-function: linear; + animation-iteration-count: infinite; + animation-direction: alternate; + } +} + +::ng-deep .mat-nav-list { + display: block; +} + +@keyframes slidetween { + from { + transform: translateX(0); + } + + to { + transform: translateX(-80%); + } +} \ No newline at end of file diff --git a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.ts b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.ts index 9062d94b7..310cbed87 100644 --- a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.ts +++ b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.ts @@ -103,7 +103,7 @@ export class PolicyDatasetsComponent name: 'Agent Group', resizeable: true, canAutoResize: true, - flexGrow: 1, + flexGrow: 1.2, cellTemplate: this.groupTemplateCell, }, { @@ -120,7 +120,7 @@ export class PolicyDatasetsComponent name: 'Sinks', resizeable: true, canAutoResize: true, - flexGrow: 1, + flexGrow: 2, cellTemplate: this.sinksTemplateCell, }, { @@ -197,11 +197,10 @@ export class PolicyDatasetsComponent onOpenSinkDetails(sink) { this.dialogService .open(SinkDetailsComponent, { - autoFocus: true, + autoFocus: false, closeOnEsc: true, context: { sink }, hasScroll: false, - hasBackdrop: false, }) .onClose.subscribe((resp) => { if (resp) { From b7fc8bd5c0721b8ef34f4607c119116d2debfa82 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 21 Jun 2023 14:07:09 -0300 Subject: [PATCH 057/115] fix(orb-ui) #702 #89 enable sorting agents by last activity and version (#2424) --- ui/src/app/pages/fleet/agents/list/agent.list.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts index 173bd87dc..063549366 100644 --- a/ui/src/app/pages/fleet/agents/list/agent.list.component.ts +++ b/ui/src/app/pages/fleet/agents/list/agent.list.component.ts @@ -249,7 +249,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe minWidth: 150, canAutoResize: true, name: 'Version', - sortable: false, + sortable: true, cellTemplate: this.agentVersionTemplateCell, }, { @@ -258,7 +258,7 @@ export class AgentListComponent implements AfterViewInit, AfterViewChecked, OnDe minWidth: 150, canAutoResize: true, name: 'Last Activity', - sortable: false, + sortable: true, cellTemplate: this.agentLastActivityTemplateCell, }, { From 70445aae24067d4f21a9495bb07e886511d44f18 Mon Sep 17 00:00:00 2001 From: Guilhermo Pazuch <1490938+gpazuch@users.noreply.github.com> Date: Wed, 21 Jun 2023 14:57:03 -0300 Subject: [PATCH 058/115] feat(eng-667): Replace Terms of Service and remove IronClad integration (#2410) feat(eng-667): Replace Terms of Service and remove IronClad integration (#2410) --- Makefile | 2 - ui/docker/Dockerfile | 4 +- ui/docker/Dockerfile.buildyarn | 2 +- ui/proxy-config.json | 75 +- ui/scripts/setenv.ts | 18 +- ui/src/app/@core/core.module.ts | 5 +- ui/src/app/auth/auth.module.ts | 3 +- .../app/auth/pages/login/login.component.scss | 9 + .../pages/register/register.component.html | 24 +- .../auth/pages/register/register.component.ts | 100 +- ui/src/environments/environment.defaults.ts | 10 +- ui/yarn.lock | 13522 ---------------- 12 files changed, 108 insertions(+), 13666 deletions(-) delete mode 100644 ui/yarn.lock diff --git a/Makefile b/Makefile index 4b933bcec..746989174 100644 --- a/Makefile +++ b/Makefile @@ -277,8 +277,6 @@ ui-modules: ui: cd ui/ && docker build \ - --build-arg ENV_PS_SID=${PS_SID} \ - --build-arg ENV_PS_GROUP_KEY=${PS_GROUP_KEY} \ --build-arg ENV=${ENVIRONMENT} \ --tag=$(ORB_DOCKERHUB_REPO)/$(DOCKER_IMAGE_NAME_PREFIX)-ui:$(REF_TAG) \ --tag=$(ORB_DOCKERHUB_REPO)/$(DOCKER_IMAGE_NAME_PREFIX)-ui:$(ORB_VERSION) \ diff --git a/ui/docker/Dockerfile b/ui/docker/Dockerfile index af1e3fa52..9bacbdae4 100644 --- a/ui/docker/Dockerfile +++ b/ui/docker/Dockerfile @@ -3,14 +3,12 @@ FROM orbcommunity/orb-ui-modules as built-module # ARG variables which direct the UI build # can be overwritten with --build-arg docker flag -ARG ENV_PS_SID="" -ARG ENV_PS_GROUP_KEY="" ARG ENV="" ARG ENV_GTAGID="" COPY ./ /app/ -RUN PS_SID=$ENV_PS_SID PS_GROUP_KEY=$ENV_PS_GROUP_KEY GTAGID=$ENV_GTAGID yarn build:prod +RUN GTAGID=$ENV_GTAGID yarn build:prod # Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx FROM nginx:1.13-alpine diff --git a/ui/docker/Dockerfile.buildyarn b/ui/docker/Dockerfile.buildyarn index 49e496a1c..3f3760ca1 100644 --- a/ui/docker/Dockerfile.buildyarn +++ b/ui/docker/Dockerfile.buildyarn @@ -1,5 +1,5 @@ # Stage 0, based on Node.js, install all dependencies -FROM node:12.21.0 as node +FROM node:13-alpine WORKDIR /app COPY package.json /app/ diff --git a/ui/proxy-config.json b/ui/proxy-config.json index 091b5727a..9305b41ef 100644 --- a/ui/proxy-config.json +++ b/ui/proxy-config.json @@ -1,111 +1,136 @@ { "/password/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/users": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/members/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/groups/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/version": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/things/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/connect": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/channels/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/http/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false, "pathRewrite": { "^/http": "" } }, "/reader/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false, "pathRewrite": { "^/reader": "" } }, "/bootstrap/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false, "pathRewrite": { "^/bootstrap": "" } }, "/browse": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/twins/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/states/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/tokens/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/features/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/sinks/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agents/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agent_groups/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/policies/agent/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/policies/dataset/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agents/backends/*": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agents/backends/taps": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agents/backends/handlers": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false }, "/agents/backends/inputs": { - "target": "http://localhost:80/api/v1", + "target": "https://stg.orb.live/api/v1", + "changeOrigin": true, "secure": false } } diff --git a/ui/scripts/setenv.ts b/ui/scripts/setenv.ts index e0878f0e9..3d5e37df1 100644 --- a/ui/scripts/setenv.ts +++ b/ui/scripts/setenv.ts @@ -5,22 +5,6 @@ require('dotenv').config(); const targetPath = `./src/environments/environment.env.ts`; -// PACTSAFE -const enablePS = () => { - if (process.env.PS_SID && process.env?.PS_GROUP_KEY) { - return ` - PS: { - // site id - SID: '${ process.env.PS_SID }', - // group key - GROUP_KEY: '${ process.env.PS_GROUP_KEY }', - }, -`; - } else { - return ''; - } -}; - const enableMaintenace = () => { if (process.env.MAINTENANCE) { return ` @@ -44,7 +28,7 @@ const enableGTAG = () => { // we have access to our environment variables // in the process.env object thanks to dotenv const environmentFileContent = ` -export const environment = {${enablePS()}${enableMaintenace()}${enableGTAG()}}; +export const environment = {${enableMaintenace()}${enableGTAG()}}; `; // write the content to the respective file diff --git a/ui/src/app/@core/core.module.ts b/ui/src/app/@core/core.module.ts index 2c578de4a..3d6eefb9b 100644 --- a/ui/src/app/@core/core.module.ts +++ b/ui/src/app/@core/core.module.ts @@ -61,7 +61,7 @@ export const NB_CORE_PROVIDERS = [ }, }, register: { - terms: false, + terms: true, redirectDelay: 0, showMessages: { success: true, @@ -88,6 +88,9 @@ export const NB_CORE_PROVIDERS = [ minLength: 1, maxLength: 30, }, + tos: { + required: true, + } }, }, }).providers, diff --git a/ui/src/app/auth/auth.module.ts b/ui/src/app/auth/auth.module.ts index 6db72c065..c5093de8a 100644 --- a/ui/src/app/auth/auth.module.ts +++ b/ui/src/app/auth/auth.module.ts @@ -41,17 +41,16 @@ import { RegisterComponent } from 'app/auth/pages/register/register.component'; import { LogoutComponent } from 'app/auth/pages/logout/logout.component'; import { RequestPasswordComponent } from 'app/auth/pages/request-password/request-password.component'; import { ResetPasswordComponent } from 'app/auth/pages/reset-password/reset-password.component'; -import { PSModule } from '@pactsafe/pactsafe-angular-sdk'; @NgModule({ imports: [ - PSModule.forRoot(), CommonModule, NbLayoutModule, NbCheckboxModule, NbAlertModule, NbInputModule, NbButtonModule, + NbCheckboxModule, RouterModule, FormsModule, NbIconModule, diff --git a/ui/src/app/auth/pages/login/login.component.scss b/ui/src/app/auth/pages/login/login.component.scss index c8c9b0e0d..3f009f11c 100644 --- a/ui/src/app/auth/pages/login/login.component.scss +++ b/ui/src/app/auth/pages/login/login.component.scss @@ -53,6 +53,15 @@ top: 0; width: 600px; + input[type="checkbox"] { + height: 2rem; + padding: 0 1rem; + margin-top: 0.5rem; + margin-right: 0.5rem; + vertical-align: bottom !important; + position: relative; + } + a { color: #62d9ff; font-family: 'Montserrat', serif; diff --git a/ui/src/app/auth/pages/register/register.component.html b/ui/src/app/auth/pages/register/register.component.html index 0c6bdf614..c555fe44a 100644 --- a/ui/src/app/auth/pages/register/register.component.html +++ b/ui/src/app/auth/pages/register/register.component.html @@ -189,15 +189,21 @@

Create an account

- - +
+ + + +

+ You must agree to the terms of service! +

+
+
{{ agent?.key }} @@ -33,9 +34,18 @@ for more advanced options.

-
{{ command2show }}
+
+      
+      
+      
+        {{ command2show }}
+      
+    
diff --git a/ui/src/app/pages/fleet/agents/key/agent.key.component.ts b/ui/src/app/pages/fleet/agents/key/agent.key.component.ts index 7f7362869..c6b5e6b76 100644 --- a/ui/src/app/pages/fleet/agents/key/agent.key.component.ts +++ b/ui/src/app/pages/fleet/agents/key/agent.key.component.ts @@ -19,6 +19,7 @@ export class AgentKeyComponent implements OnInit { key2copy: string; copyKeyIcon: string; + saveKeyIcon: string; @Input() agent: Agent = {}; @@ -34,6 +35,7 @@ export class AgentKeyComponent implements OnInit { this.key2copy = this.agent.key; this.copyCommandIcon = 'copy-outline'; this.copyKeyIcon = 'copy-outline'; + this.saveKeyIcon = 'save-outline'; } makeCommand2Copy() { @@ -65,4 +67,13 @@ orbcommunity/orb-agent`; onClose() { this.dialogRef.close(false); } + downloadCommand() { + const blob = new Blob([this.command2copy], { type: 'text/plain' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${this.agent.id}.txt`; + a.click(); + window.URL.revokeObjectURL(url); + } } From 27b5005f6fccefe39d0858de26e24ff99b0e612f Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Wed, 28 Jun 2023 12:12:04 -0300 Subject: [PATCH 076/115] fix(deps): general bumps on dependencies which had vulnerabilities alerted by dependabot (#2468) * fix: bump ciso8601 from 2.2.0 to 2.3.0 Bumps [ciso8601](https://github.com/closeio/ciso8601) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/closeio/ciso8601/releases) - [Changelog](https://github.com/closeio/ciso8601/blob/master/CHANGELOG.md) - [Commits](https://github.com/closeio/ciso8601/compare/v2.2.0...v2.3.0) --- updated-dependencies: - dependency-name: ciso8601 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump actions/setup-go from 2 to 4 Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 4. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix: bump psutil from 5.9.2 to 5.9.5 Bumps [psutil](https://github.com/giampaolo/psutil) from 5.9.2 to 5.9.5. - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-5.9.2...release-5.9.5) --- updated-dependencies: - dependency-name: psutil dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: bump deepdiff from 5.8.1 to 6.3.0 Bumps [deepdiff](https://github.com/seperman/deepdiff) from 5.8.1 to 6.3.0. - [Release notes](https://github.com/seperman/deepdiff/releases) - [Changelog](https://github.com/seperman/deepdiff/blob/master/docs/changelog.rst) - [Commits](https://github.com/seperman/deepdiff/compare/v5.8.1...6.3.0) --- updated-dependencies: - dependency-name: deepdiff dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix: bump prometheus-client from 0.15.0 to 0.17.0 Bumps [prometheus-client](https://github.com/prometheus/client_python) from 0.15.0 to 0.17.0. - [Release notes](https://github.com/prometheus/client_python/releases) - [Commits](https://github.com/prometheus/client_python/compare/v0.15.0...v0.17.0) --- updated-dependencies: - dependency-name: prometheus-client dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump mkdocs-material from 8.3.3 to 9.1.17 Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 8.3.3 to 9.1.17. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Upgrade guide](https://github.com/squidfunk/mkdocs-material/blob/master/docs/upgrade.md) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/8.3.3...9.1.17) --- updated-dependencies: - dependency-name: mkdocs-material dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * fix: bump google.golang.org/protobuf from 1.30.0 to 1.31.0 Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump pyhamcrest from 2.0.3 to 2.0.4 Bumps [pyhamcrest](https://github.com/hamcrest/PyHamcrest) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/hamcrest/PyHamcrest/releases) - [Changelog](https://github.com/hamcrest/PyHamcrest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/hamcrest/PyHamcrest/compare/V2.0.3...V2.0.4) --- updated-dependencies: - dependency-name: pyhamcrest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: bump selenium from 4.3.0 to 4.10.0 Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.3.0 to 4.10.0. - [Release notes](https://github.com/SeleniumHQ/Selenium/releases) - [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.3.0...selenium-4.10.0) --- updated-dependencies: - dependency-name: selenium dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump jsonschema from 4.6.0 to 4.17.3 Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.6.0 to 4.17.3. - [Release notes](https://github.com/python-jsonschema/jsonschema/releases) - [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst) - [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.6.0...v4.17.3) --- updated-dependencies: - dependency-name: jsonschema dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump github.com/cenkalti/backoff/v4 from 4.2.0 to 4.2.1 Bumps [github.com/cenkalti/backoff/v4](https://github.com/cenkalti/backoff) from 4.2.0 to 4.2.1. - [Commits](https://github.com/cenkalti/backoff/compare/v4.2.0...v4.2.1) --- updated-dependencies: - dependency-name: github.com/cenkalti/backoff/v4 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: bump prometheus-client from 0.15.0 to 0.17.0 Bumps [prometheus-client](https://github.com/prometheus/client_python) from 0.15.0 to 0.17.0. - [Release notes](https://github.com/prometheus/client_python/releases) - [Commits](https://github.com/prometheus/client_python/compare/v0.15.0...v0.17.0) --- updated-dependencies: - dependency-name: prometheus-client dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * fix: bump webdriver-manager from 3.8.3 to 3.8.6 Bumps [webdriver-manager](https://github.com/SergeyPirogov/webdriver_manager) from 3.8.3 to 3.8.6. - [Release notes](https://github.com/SergeyPirogov/webdriver_manager/releases) - [Changelog](https://github.com/SergeyPirogov/webdriver_manager/blob/master/CHANGELOG.md) - [Commits](https://github.com/SergeyPirogov/webdriver_manager/compare/v3.8.3...v3.8.6) --- updated-dependencies: - dependency-name: webdriver-manager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: bump selenium from 4.3.0 to 4.10.0 Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.3.0 to 4.10.0. - [Release notes](https://github.com/SeleniumHQ/Selenium/releases) - [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.3.0...selenium-4.10.0) --- updated-dependencies: - dependency-name: selenium dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/agent.yml | 2 +- .github/workflows/go-develop.yml | 12 ++++++------ .github/workflows/go-main.yml | 12 ++++++------ .github/workflows/go-production.yml | 12 ++++++------ go.mod | 4 ++-- go.sum | 8 ++++---- python-test/requirements.txt | 20 ++++++++++---------- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/agent.yml b/.github/workflows/agent.yml index 23565ec43..89a7adc40 100644 --- a/.github/workflows/agent.yml +++ b/.github/workflows/agent.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 diff --git a/.github/workflows/go-develop.yml b/.github/workflows/go-develop.yml index 2d82ba152..984b20d0c 100644 --- a/.github/workflows/go-develop.yml +++ b/.github/workflows/go-develop.yml @@ -114,7 +114,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -153,7 +153,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -192,7 +192,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -231,7 +231,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -270,7 +270,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -309,7 +309,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 diff --git a/.github/workflows/go-main.yml b/.github/workflows/go-main.yml index a3c25918d..108fbe466 100644 --- a/.github/workflows/go-main.yml +++ b/.github/workflows/go-main.yml @@ -63,7 +63,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -76,7 +76,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -90,7 +90,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -104,7 +104,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -118,7 +118,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -132,7 +132,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 diff --git a/.github/workflows/go-production.yml b/.github/workflows/go-production.yml index 108470ff2..1b43dff8a 100644 --- a/.github/workflows/go-production.yml +++ b/.github/workflows/go-production.yml @@ -68,7 +68,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -82,7 +82,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -98,7 +98,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -112,7 +112,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -126,7 +126,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 @@ -140,7 +140,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: go-version: 1.19 diff --git a/go.mod b/go.mod index d16391756..7ec994846 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( go.uber.org/zap v1.24.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 google.golang.org/grpc v1.54.0 - google.golang.org/protobuf v1.30.0 + google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.26.3 @@ -69,7 +69,7 @@ require ( github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/alecthomas/participle/v2 v2.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cenkalti/backoff/v4 v4.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/continuity v0.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index ee2713401..131b061c3 100644 --- a/go.sum +++ b/go.sum @@ -101,8 +101,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -1232,8 +1232,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/python-test/requirements.txt b/python-test/requirements.txt index 7e5f54316..3f436595d 100644 --- a/python-test/requirements.txt +++ b/python-test/requirements.txt @@ -1,15 +1,15 @@ behave==1.2.6 -ciso8601==2.2.0 +ciso8601==2.3.0 docker==5.0.3 -PyHamcrest==2.0.3 +PyHamcrest==2.0.4 PyYAML==6.0 retry==0.9.2 -selenium==4.3.0 -behavex==1.5.4 -deepdiff==5.8.1 -jsonschema==4.6.0 +selenium==4.10.0 +behavex==2.0.1 +deepdiff==6.3.0 +jsonschema==4.17.3 mkdocs==1.4.3 -mkdocs-material==8.3.3 -prometheus-client==0.15.0 -psutil==5.9.2 -webdriver-manager==3.8.3 +mkdocs-material==9.1.17 +prometheus-client==0.17.0 +psutil==5.9.5 +webdriver-manager==3.8.6 From 9c3e093fc8f73592dd81cc0501b5eb0002a4e316 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 28 Jun 2023 14:41:43 -0300 Subject: [PATCH 077/115] fix(orb-ui): #73 add missing name validations policy edit (#2469) --- .../orb/policy/policy-details/policy-details.component.html | 6 ++++++ .../orb/policy/policy-details/policy-details.component.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.html b/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.html index 546a226c6..2b1966485 100644 --- a/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.html +++ b/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.html @@ -76,6 +76,12 @@
Name does not match the pattern.
+
+ Name must not exceed 64 characters. +
+
+ Name too short. +
diff --git a/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.ts b/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.ts index bbc9d3867..6bbbf71a3 100644 --- a/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.ts +++ b/ui/src/app/shared/components/orb/policy/policy-details/policy-details.component.ts @@ -59,6 +59,8 @@ export class PolicyDetailsComponent implements OnInit, OnChanges { [ Validators.required, Validators.pattern('^[a-zA-Z_][a-zA-Z0-9_-]*$'), + Validators.maxLength(64), + Validators.minLength(2), ], ], description: [description], From 09e404abbf19d81185722007aaf431356b96e054 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 28 Jun 2023 14:42:21 -0300 Subject: [PATCH 078/115] feat(orb-ui): #145 Create Policy, option to upload a policy configuration yaml file (#2470) --- .../add/agent.policy.add.component.html | 27 ++++++++++++------- .../add/agent.policy.add.component.scss | 15 ++++++++++- .../add/agent.policy.add.component.ts | 13 ++++++++- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html index 0a53a6200..7253eb0a2 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.html @@ -358,15 +358,24 @@

{{ isEdit ? 'Edit Agent Policy' : 'Create Agent Policy'}}

-
- - +
+
+

Paste or Upload your YAML configuration

+ + +
+
+ + +

diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss index 21425334c..0af6c504f 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.scss @@ -170,7 +170,6 @@ ngx-tag-control, ngx-tag-display { .code-editor { height: calc(100%); width: calc(100%); - padding: calc(1rem); } .code-editor-wrapper { @@ -194,3 +193,17 @@ ngx-tag-control, ngx-tag-display { margin-top: 1rem; margin: 10px 0; } + +.upload-button { + color: #3089fc; + background-color: transparent; + border: none; + font-weight: 600; + outline: none; +} +.summary-accent { + color: #969fb9 !important; +} +.align { + margin: 0px; +} \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts index 17f9dd6de..6b96e9ff3 100644 --- a/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/add/agent.policy.add.component.ts @@ -130,6 +130,8 @@ kind: collection`; selectedTags: Tags; + uploadIconKey = 'upload-outline' + constructor( private agentPoliciesService: AgentPoliciesService, private notificationsService: NotificationsService, @@ -453,7 +455,16 @@ kind: collection`; viewPolicy(id) { this.router.navigateByUrl(`/pages/datasets/policies/view/${id}`); } - + onFileSelected(event: any) { + const file: File = event.target.files[0]; + const reader: FileReader = new FileReader(); + + reader.onload = (e: any) => { + this.code = e.target.result; + }; + + reader.readAsText(file); + } onYAMLSubmit() { const payload = { name: this.detailsFG.controls.name.value, From 2e9ea29e78674a800a6726de86d2fb33d75dffe3 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Thu, 29 Jun 2023 09:25:30 -0300 Subject: [PATCH 079/115] feat: add custom headers support. (#2457) * feat(sinks): add proposed solution to accept custom http headers. * feat(maestro): add proposed solution to accept custom http headers. * feat(maestro): adapt headers to pass and build collector's config. * feat(sinks): change to current name `headers`. * feat(sinks): add authorization to block list custom headers. * feat(sinks): add error treatment for failed exporters. * feat(maestro): remove limits from resources. * feat(maestro): nil checks --------- Co-authored-by: Luiz Pegoraro --- maestro/config/config_builder.go | 24 ++++++------------ maestro/config/config_builder_test.go | 30 +++++++++++++++++++++++ maestro/config/exporter_builder.go | 19 +++++++++++++- maestro/config/types.go | 3 ++- sinks/backend/prometheus/configuration.go | 14 +++++++++++ sinks/backend/prometheus/type.go | 1 + 6 files changed, 72 insertions(+), 19 deletions(-) diff --git a/maestro/config/config_builder.go b/maestro/config/config_builder.go index 2f50674d0..11ffa76f6 100644 --- a/maestro/config/config_builder.go +++ b/maestro/config/config_builder.go @@ -307,16 +307,6 @@ var JsonDeployment = ` "protocol": "TCP" } ], - "resources": { - "limits": { - "cpu": "100m", - "memory": "200Mi" - }, - "requests": { - "cpu": "100m", - "memory": "200Mi" - } - }, "volumeMounts": [ { "name": "varlog", @@ -377,11 +367,8 @@ func GetDeploymentJson(kafkaUrl string, sink SinkData) (string, error) { // ReturnConfigYamlFromSink this is the main method, which will generate the YAML file from the func ReturnConfigYamlFromSink(_ context.Context, kafkaUrlConfig string, sink SinkData) (string, error) { authType := sink.Config.GetSubMetadata(AuthenticationKey)["type"] - var authTypeStr string - switch authType.(type) { - case string: - authTypeStr = authType.(string) - default: + authTypeStr, ok := authType.(string) + if !ok { return "", errors.New("failed to create config invalid authentication type") } authBuilder := GetAuthService(authTypeStr) @@ -391,10 +378,13 @@ func ReturnConfigYamlFromSink(_ context.Context, kafkaUrlConfig string, sink Sin exporterBuilder := FromStrategy(sink.Backend) extensions, extensionName := authBuilder.GetExtensionsFromMetadata(sink.Config) exporters, exporterName := exporterBuilder.GetExportersFromMetadata(sink.Config, extensionName) + if exporterName == "" { + return "", errors.New("failed to build exporter") + } // Add prometheus extension for metrics extensions.PProf = &PProfExtension{ - Endpoint: "0.0.0.0:1888", // Leaving default for now, will need to change with more processes + Endpoint: "0.0.0.0:1888", } serviceConfig := ServiceConfig{ Extensions: []string{"pprof", extensionName}, @@ -420,7 +410,7 @@ func ReturnConfigYamlFromSink(_ context.Context, kafkaUrlConfig string, sink Sin Kafka: KafkaReceiver{ Brokers: []string{kafkaUrlConfig}, Topic: fmt.Sprintf("otlp_metrics-%s", sink.SinkID), - ProtocolVersion: "2.0.0", // Leaving default of over 2.0.0 + ProtocolVersion: "2.0.0", }, }, Extensions: &extensions, diff --git a/maestro/config/config_builder_test.go b/maestro/config/config_builder_test.go index 6c7a53ad4..9e7cd2d04 100644 --- a/maestro/config/config_builder_test.go +++ b/maestro/config/config_builder_test.go @@ -47,6 +47,36 @@ func TestReturnConfigYamlFromSink(t *testing.T) { want: `---\nreceivers:\n kafka:\n brokers:\n - kafka:9092\n topic: otlp_metrics-sink-id-11\n protocol_version: 2.0.0\nextensions:\n pprof:\n endpoint: 0.0.0.0:1888\n basicauth/exporter:\n client_auth:\n username: prom-user\n password: dbpass\nexporters:\n prometheusremotewrite:\n endpoint: https://acme.com/prom/push\n auth:\n authenticator: basicauth/exporter\nservice:\n extensions:\n - pprof\n - basicauth/exporter\n pipelines:\n metrics:\n receivers:\n - kafka\n exporters:\n - prometheusremotewrite\n`, wantErr: false, }, + { + name: "prometheus, basicauth, with headers", + args: args{ + in0: context.Background(), + kafkaUrlConfig: "kafka:9092", + sink: SinkData{ + SinkID: "sink-id-11", + OwnerID: "11", + Backend: "prometheus", + Config: types.Metadata{ + "exporter": types.Metadata{ + "remote_host": "https://acme.com/prom/push", + "headers": map[string]interface{}{ + "X-Scope-OrgID": "TENANT_1", + }, + }, + "authentication": types.Metadata{ + "type": "basicauth", + "username": "prom-user", + "password": "dbpass", + }, + }, + State: 0, + Msg: "", + LastRemoteWrite: time.Time{}, + }, + }, + want: `---\nreceivers:\n kafka:\n brokers:\n - kafka:9092\n topic: otlp_metrics-sink-id-11\n protocol_version: 2.0.0\nextensions:\n pprof:\n endpoint: 0.0.0.0:1888\n basicauth/exporter:\n client_auth:\n username: prom-user\n password: dbpass\nexporters:\n prometheusremotewrite:\n endpoint: https://acme.com/prom/push\n headers:\n X-Scope-OrgID: TENANT_1\n auth:\n authenticator: basicauth/exporter\nservice:\n extensions:\n - pprof\n - basicauth/exporter\n pipelines:\n metrics:\n receivers:\n - kafka\n exporters:\n - prometheusremotewrite\n`, + wantErr: false, + }, { name: "otlp, basicauth", args: args{ diff --git a/maestro/config/exporter_builder.go b/maestro/config/exporter_builder.go index 4b11ec25e..56231ba42 100644 --- a/maestro/config/exporter_builder.go +++ b/maestro/config/exporter_builder.go @@ -21,11 +21,28 @@ type PrometheusExporterConfig struct { } func (p *PrometheusExporterConfig) GetExportersFromMetadata(config types.Metadata, authenticationExtensionName string) (Exporters, string) { - endpointCfg := config.GetSubMetadata("exporter")["remote_host"].(string) + exporterSubMeta := config.GetSubMetadata("exporter") + if exporterSubMeta == nil { + return Exporters{}, "" + } + endpointCfg, ok := exporterSubMeta["remote_host"].(string) + if !ok { + return Exporters{}, "" + } + customHeaders, ok := exporterSubMeta["headers"] + if !ok || customHeaders == nil { + return Exporters{ + PrometheusRemoteWrite: &PrometheusRemoteWriteExporterConfig{ + Endpoint: endpointCfg, + Auth: Auth{Authenticator: authenticationExtensionName}, + }, + }, "prometheusremotewrite" + } return Exporters{ PrometheusRemoteWrite: &PrometheusRemoteWriteExporterConfig{ Endpoint: endpointCfg, Auth: Auth{Authenticator: authenticationExtensionName}, + Headers: customHeaders.(map[string]interface{}), }, }, "prometheusremotewrite" } diff --git a/maestro/config/types.go b/maestro/config/types.go index 3c21ed13a..da3321da4 100644 --- a/maestro/config/types.go +++ b/maestro/config/types.go @@ -145,7 +145,8 @@ type Auth struct { } type PrometheusRemoteWriteExporterConfig struct { - Endpoint string `json:"endpoint" yaml:"endpoint"` + Endpoint string `json:"endpoint" yaml:"endpoint"` + Headers map[string]interface{} `json:"headers,omitempty" yaml:"headers,omitempty"` Auth struct { Authenticator string `json:"authenticator" yaml:"authenticator"` } diff --git a/sinks/backend/prometheus/configuration.go b/sinks/backend/prometheus/configuration.go index cbf40a462..ff302f198 100644 --- a/sinks/backend/prometheus/configuration.go +++ b/sinks/backend/prometheus/configuration.go @@ -8,6 +8,10 @@ import ( "net/url" ) +var invalidCustomHeaders = []string{ + "Content-Encoding", "Content-Type", "X-Prometheus-Remote-Write-Version", "User-Agent", "Authorization", +} + func (p *Backend) ConfigToFormat(format string, metadata types.Metadata) (string, error) { if format == "yaml" { remoteHost := metadata[RemoteHostURLConfigFeature].(string) @@ -50,6 +54,16 @@ func (p *Backend) ValidateConfiguration(config types.Metadata) error { if err != nil { return errors.New("must send valid URL for Remote Write") } + // check for custom http headers + customHeaders, customHeadersOk := config[CustomHeadersConfigFeature] + if customHeadersOk { + headersAsMap := customHeaders.(map[string]interface{}) + for _, header := range invalidCustomHeaders { + if _, ok := headersAsMap[header]; !ok { + return errors.New("invalid custom headers") + } + } + } return nil } diff --git a/sinks/backend/prometheus/type.go b/sinks/backend/prometheus/type.go index 73a7f40a7..1f274d6ed 100644 --- a/sinks/backend/prometheus/type.go +++ b/sinks/backend/prometheus/type.go @@ -13,6 +13,7 @@ var _ backend.Backend = (*Backend)(nil) const ( RemoteHostURLConfigFeature = "remote_host" ApiTokenConfigFeature = "api_token" + CustomHeadersConfigFeature = "headers" ) //type PrometheusConfigMetadata = types.Metadata From 8d7f410e33dfc97f6b004ac4691d1ecf9f36646f Mon Sep 17 00:00:00 2001 From: "Everton H. Taques" <97463920+etaques@users.noreply.github.com> Date: Thu, 29 Jun 2023 14:42:14 -0300 Subject: [PATCH 080/115] fix(ui-modues): update node to 14.17 (#2472) fix(ui-modues): update node to 14.17 (#2472) --- ui/docker/Dockerfile.buildyarn | 2 +- ui/package.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ui/docker/Dockerfile.buildyarn b/ui/docker/Dockerfile.buildyarn index 3f3760ca1..3e3721a3c 100644 --- a/ui/docker/Dockerfile.buildyarn +++ b/ui/docker/Dockerfile.buildyarn @@ -1,5 +1,5 @@ # Stage 0, based on Node.js, install all dependencies -FROM node:13-alpine +FROM node:14.17 WORKDIR /app COPY package.json /app/ diff --git a/ui/package.json b/ui/package.json index 204189256..392a46884 100644 --- a/ui/package.json +++ b/ui/package.json @@ -49,7 +49,6 @@ "@nebular/eva-icons": "5.0.0", "@nebular/security": "5.0.0", "@nebular/theme": "5.0.0", - "@pactsafe/pactsafe-angular-sdk": "^2.0.0", "@swimlane/ngx-charts": "^13.0.2", "bootstrap": "4.3.1", "classlist.js": "1.1.20150312", From cc9b3c301891cbe77d571dcf588bcbc1556a2efb Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Fri, 30 Jun 2023 09:07:19 -0300 Subject: [PATCH 081/115] improvement(orb-ui) Agent View, include policy backend on active policies list (#2471) --- .../agent-policies-datasets.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html index 4ef531ba8..9763d46c5 100644 --- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html +++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html @@ -20,6 +20,8 @@ {{ policy?.state }}    Version:  {{ policy?.version }} +    Backend:  + {{ policy?.backend }} From 8e67a11f41bb4bfaf68e11fc81cf93c333648efb Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Fri, 30 Jun 2023 10:36:58 -0300 Subject: [PATCH 082/115] fix(orb-ui): #90 Add elements name on delete modals (#2474) --- .../app/pages/fleet/agents/delete/agent.delete.component.html | 2 +- .../fleet/groups/delete/agent.group.delete.component.html | 4 +++- ui/src/app/pages/sinks/delete/sink.delete.component.html | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/src/app/pages/fleet/agents/delete/agent.delete.component.html b/ui/src/app/pages/fleet/agents/delete/agent.delete.component.html index 9f8b2add3..969c8afe4 100644 --- a/ui/src/app/pages/fleet/agents/delete/agent.delete.component.html +++ b/ui/src/app/pages/fleet/agents/delete/agent.delete.component.html @@ -12,7 +12,7 @@ -

Are you sure you want to delete this Agent? This action cannot be undone.*

+

Are you sure you want to delete Agent {{name}}? This action cannot be undone.*

*To confirm, type your Agent name exactly as it appears.

-

{{strings.delete.body}}*

+

Are you sure you want to delete Agent Group {{name}}? This may cause Datasets which + use this Agent Group to become invalid. + This action cannot be undone.*

{{strings.delete.warning}}

diff --git a/ui/src/app/pages/sinks/delete/sink.delete.component.html b/ui/src/app/pages/sinks/delete/sink.delete.component.html index 92a0fb5a9..f00e24ff3 100644 --- a/ui/src/app/pages/sinks/delete/sink.delete.component.html +++ b/ui/src/app/pages/sinks/delete/sink.delete.component.html @@ -10,7 +10,9 @@ -

{{strings.delete.body}}*

+

Are you sure you want to delete Sink {{sink?.name}}? + This may cause Datasets which use this Sink to become invalid. + This action cannot be undone.*

{{strings.delete.warning}}

From c9bcef4d957273645fb7cd488eedf9286ee8a5c4 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Fri, 30 Jun 2023 10:37:24 -0300 Subject: [PATCH 083/115] feat(orb-ui): Policy and Agent View, add refresh button (#2473) --- .../view/agent.policy.view.component.html | 47 +++++++--------- .../view/agent.policy.view.component.scss | 45 +++++++++++++++ .../view/agent.policy.view.component.ts | 3 + .../agents/view/agent.view.component.html | 22 +++++--- .../agents/view/agent.view.component.scss | 56 +++++++++++++++++++ .../fleet/agents/view/agent.view.component.ts | 11 +++- 6 files changed, 148 insertions(+), 36 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.html b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.html index 315bd53b5..18ffb341f 100644 --- a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.html +++ b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.html @@ -8,34 +8,25 @@

Policy View

- - - +
+ + + + Last Update: {{ lastUpdate | date: 'HH:mm:ss a' }} + + + + + +
diff --git a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss index 6fa3e165c..a7c18bc61 100644 --- a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss +++ b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.scss @@ -194,3 +194,48 @@ button { } } } +.refresh-button { + border: none !important; + box-sizing: border-box; + box-shadow: none !important; + margin-right: 0.3rem; + + &:active, &:focus { + background-color: unset !important; + } + + &:hover { + background-color: rgba(143, 155, 179, 0.16); + } +} + +.paused { + animation: rotation 750ms linear infinite; + animation-play-state: paused; +} + +.rotate { + animation: rotation 750ms linear infinite; + animation-play-state: running; + + &:hover { + background: unset !important; + } +} + +@keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } +} +.last-update { + color: #969fb9; + font-size: 14px; +} +.right-content { + display: flex; + justify-content: flex-end; +} diff --git a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts index 856af81e1..1d97d1884 100644 --- a/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts +++ b/ui/src/app/pages/datasets/policies.agent/view/agent.policy.view.component.ts @@ -50,6 +50,8 @@ export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { interface: false, }; + lastUpdate: Date | null = null; + @ViewChild(PolicyDetailsComponent) detailsComponent: PolicyDetailsComponent; @ViewChild(PolicyInterfaceComponent) @@ -72,6 +74,7 @@ export class AgentPolicyViewComponent implements OnInit, OnDestroy, OnChanges { this.isLoading = true; this.policyId = this.route.snapshot.paramMap.get('id'); this.retrievePolicy(); + this.lastUpdate = new Date(); } ngOnChanges(): void { diff --git a/ui/src/app/pages/fleet/agents/view/agent.view.component.html b/ui/src/app/pages/fleet/agents/view/agent.view.component.html index c0ea7b1bb..3cd7c0e11 100644 --- a/ui/src/app/pages/fleet/agents/view/agent.view.component.html +++ b/ui/src/app/pages/fleet/agents/view/agent.view.component.html @@ -1,14 +1,21 @@ -
-
+
+

Agent View

-
- - {{ agent?.state | ngxCapitalize }}. +
+ + + + Last Update: {{ lastUpdate | date: 'HH:mm:ss a' }} + +
+
+ + {{ agent?.state | ngxCapitalize }}.   Last activity @@ -23,6 +30,7 @@
+
diff --git a/ui/src/app/pages/fleet/agents/view/agent.view.component.scss b/ui/src/app/pages/fleet/agents/view/agent.view.component.scss index 4ef228886..e001af077 100644 --- a/ui/src/app/pages/fleet/agents/view/agent.view.component.scss +++ b/ui/src/app/pages/fleet/agents/view/agent.view.component.scss @@ -1,3 +1,18 @@ +header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.left-content { + flex: 1; +} + +.right-content { + display: flex; + align-items: center; +} + h4 { font-family: 'Montserrat', sans-serif; font-size: 1.5rem; @@ -142,3 +157,44 @@ nb-card { color: #df316f !important; } } +.refresh-button { + border: none !important; + box-sizing: border-box; + box-shadow: none !important; + margin-right: 0.3rem; + + &:active, &:focus { + background-color: unset !important; + } + + &:hover { + background-color: rgba(143, 155, 179, 0.16); + } +} + +.paused { + animation: rotation 750ms linear infinite; + animation-play-state: paused; +} + +.rotate { + animation: rotation 750ms linear infinite; + animation-play-state: running; + + &:hover { + background: unset !important; + } +} + +@keyframes rotation { + from { + transform: rotate(0deg); + } + to { + transform: rotate(359deg); + } +} +.last-update { + color: #969fb9; + font-size: 14px; +} diff --git a/ui/src/app/pages/fleet/agents/view/agent.view.component.ts b/ui/src/app/pages/fleet/agents/view/agent.view.component.ts index 18b4d6235..4bfd43204 100644 --- a/ui/src/app/pages/fleet/agents/view/agent.view.component.ts +++ b/ui/src/app/pages/fleet/agents/view/agent.view.component.ts @@ -6,7 +6,8 @@ import { Dataset } from 'app/common/interfaces/orb/dataset.policy.interface'; import { AgentsService } from 'app/common/services/agents/agents.service'; import { OrbService } from 'app/common/services/orb.service'; import { STRINGS } from 'assets/text/strings'; -import { Subscription } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; +import { shareReplay } from 'rxjs/operators'; @Component({ selector: 'ngx-agent-view', @@ -14,6 +15,9 @@ import { Subscription } from 'rxjs'; styleUrls: ['./agent.view.component.scss'], }) export class AgentViewComponent implements OnInit, OnDestroy { + + lastUpdate: Date | null = null; + strings = STRINGS.agents; agentStates = AgentStates; @@ -63,6 +67,7 @@ export class AgentViewComponent implements OnInit, OnDestroy { }, }); this.isLoading = true; + this.lastUpdate = new Date(); } isToday() { @@ -79,4 +84,8 @@ export class AgentViewComponent implements OnInit, OnDestroy { ngOnDestroy() { this.agentSubscription?.unsubscribe(); } + refreshAgent() { + this.isLoading = true; + this.retrieveAgent(); + } } From 2144f3c4ec55ba5bb6c495292f9d1e2edfcb2db9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 17:36:56 -0300 Subject: [PATCH 084/115] fix: bump go.uber.org/multierr from 1.10.0 to 1.11.0 (#2483) Bumps [go.uber.org/multierr](https://github.com/uber-go/multierr) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/uber-go/multierr/releases) - [Changelog](https://github.com/uber-go/multierr/blob/master/CHANGELOG.md) - [Commits](https://github.com/uber-go/multierr/compare/v1.10.0...v1.11.0) --- updated-dependencies: - dependency-name: go.uber.org/multierr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7ec994846..6ffdcece9 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( go.opentelemetry.io/collector/consumer v0.75.0 go.opentelemetry.io/collector/exporter v0.75.0 go.opentelemetry.io/collector/receiver v0.75.0 - go.uber.org/multierr v1.10.0 + go.uber.org/multierr v1.11.0 go.uber.org/zap v1.24.0 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 google.golang.org/grpc v1.54.0 diff --git a/go.sum b/go.sum index 131b061c3..9579cc6a6 100644 --- a/go.sum +++ b/go.sum @@ -805,8 +805,8 @@ go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= From e1a69eae3a74c1f4441ccbfed354b50d8b8b5989 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Wed, 5 Jul 2023 18:51:36 -0300 Subject: [PATCH 085/115] fix(maestro): add sink id to error message (#2486) --- maestro/config/config_builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maestro/config/config_builder.go b/maestro/config/config_builder.go index 11ffa76f6..5f105b8db 100644 --- a/maestro/config/config_builder.go +++ b/maestro/config/config_builder.go @@ -358,7 +358,7 @@ func GetDeploymentJson(kafkaUrl string, sink SinkData) (string, error) { manifest := strings.Replace(k8sOtelCollector, "SINK_ID", sink.SinkID, -1) config, err := ReturnConfigYamlFromSink(context.Background(), kafkaUrl, sink) if err != nil { - return "", errors.Wrap(errors.New("failed to build YAML"), err) + return "", errors.Wrap(errors.New(fmt.Sprintf("failed to build YAML, sink: %s", sink.SinkID)), err) } manifest = strings.Replace(manifest, "SINK_CONFIG", config, -1) return manifest, nil From 2d3bad376e6f4747f090500f10d95a9d883eb892 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Wed, 5 Jul 2023 18:51:43 -0300 Subject: [PATCH 086/115] fix(sinker): re-add the agentName in the scope attribute 'agent' (#2476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(sinker): replace err2 variable with common err. * fix(sinker): re-add attribute agent in metric scope with agent´s name. --------- Co-authored-by: Luiz Pegoraro --- sinker/message_handler.go | 18 ++++++++++-------- sinker/otel/orbreceiver/metrics.go | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/sinker/message_handler.go b/sinker/message_handler.go index fa1c060eb..1ede15553 100644 --- a/sinker/message_handler.go +++ b/sinker/message_handler.go @@ -117,13 +117,15 @@ func (svc SinkerService) handleMetrics(ctx context.Context, agentID string, chan return fleet.ErrSchemaMalformed } - agentPb, err2 := svc.ExtractAgent(ctx, channelID) - if err2 != nil { - return err2 + agentPb, err := svc.ExtractAgent(ctx, channelID) + if err != nil { + return err } - agentName, _ := types.NewIdentifier(agentPb.AgentName) - + agentName, err := types.NewIdentifier(agentPb.AgentName) + if err != nil { + return err + } agent := fleet.Agent{ Name: agentName, MFOwnerID: agentPb.OwnerID, @@ -138,9 +140,9 @@ func (svc SinkerService) handleMetrics(ctx context.Context, agentID string, chan // however, per policy, we want a unique set of sink IDs as we don't want to send the same metrics twice to the same sink for the same policy datasetSinkIDs := make(map[string]bool) // first go through the datasets and gather the unique set of sinks we need for this particular policy - err2 := svc.GetSinks(agent, metricsPayload, datasetSinkIDs) - if err2 != nil { - return err2 + err = svc.GetSinks(agent, metricsPayload, datasetSinkIDs) + if err != nil { + return err } // ensure there are sinks diff --git a/sinker/otel/orbreceiver/metrics.go b/sinker/otel/orbreceiver/metrics.go index e17bbe516..b5020ee5c 100644 --- a/sinker/otel/orbreceiver/metrics.go +++ b/sinker/otel/orbreceiver/metrics.go @@ -94,6 +94,7 @@ func (r *OrbReceiver) ProccessMetricsContext(scope pmetric.ScopeMetrics, channel for k, v := range agentPb.OrbTags { scope = r.injectScopeMetricsAttribute(scope, k, v) } + r.injectScopeMetricsAttribute(scope, "agent", agentPb.AgentName) scope = r.replaceScopeMetricsTimestamp(scope, pcommon.NewTimestampFromTime(time.Now())) sinkIds, err := r.sinkerService.GetSinkIdsFromDatasetIDs(execCtx, agentPb.OwnerID, datasetIDs) From cc8a9d39aad6605c5c208316878726db4f73b20c Mon Sep 17 00:00:00 2001 From: manrodrigues Date: Fri, 7 Jul 2023 10:37:49 -0300 Subject: [PATCH 087/115] Fix/eng 783 fix orbcommunity deploy (#2489) * fix sink open_api.yaml --- sinks/api/http/openapi.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sinks/api/http/openapi.yaml b/sinks/api/http/openapi.yaml index 21e7f27cb..b3f627f8e 100644 --- a/sinks/api/http/openapi.yaml +++ b/sinks/api/http/openapi.yaml @@ -295,6 +295,14 @@ components: type: http format: JWT required: true + AuthenticationTypeId: + name: id + description: Unique Sink auth identifier. + in: path + schema: + type: string + format: string + required: true SinkId: name: id description: Unique Sink identifier. @@ -337,6 +345,12 @@ components: schema: type: string format: byte + SinkAuthTypeObjRes: + description: Authentication object. + content: + application/json: + schema: + $ref: "#/components/schemas/SinkAuthTypeResSchema" SinkBackendObjRes: description: Backend object content: From 304a6da6859293de4a8b12c2bd3c847418b76718 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Mon, 10 Jul 2023 11:02:24 -0300 Subject: [PATCH 088/115] feat(sinker): add policy name and id to scope metrics. (#2488) * feat(sinker): add policy name and id to scope metrics. * feat(sinker): add cache mechanism using go-cache in memory cache to reduce amount of gRPC calls. * fix(maestro): solved issue with sinks update. --------- Co-authored-by: Luiz Pegoraro --- cmd/sinker/main.go | 4 +- go.mod | 1 + go.sum | 2 + maestro/redis/consumer/hashset.go | 11 +++- pkg/config/config.go | 16 ++++++ sinker/otel/bridgeservice/bridge.go | 81 +++++++++++++++++++++-------- sinker/otel/orbreceiver/logs.go | 2 +- sinker/otel/orbreceiver/metrics.go | 11 +++- sinker/otel/orbreceiver/traces.go | 2 +- sinker/service.go | 46 ++++++++-------- 10 files changed, 126 insertions(+), 50 deletions(-) diff --git a/cmd/sinker/main.go b/cmd/sinker/main.go index 078e1f710..e1ebf79cf 100644 --- a/cmd/sinker/main.go +++ b/cmd/sinker/main.go @@ -65,6 +65,7 @@ func main() { policiesGRPCCfg := config.LoadGRPCConfig("orb", "policies") sinksGRPCCfg := config.LoadGRPCConfig("orb", "sinks") otelCfg := config.LoadOtelConfig(envPrefix) + inMemoryCacheConfig := config.LoadInMemoryCacheConfig(envPrefix) // main logger var logger *zap.Logger @@ -191,7 +192,8 @@ func main() { otelEnabled := otelCfg.Enable == "true" otelKafkaUrl := otelCfg.KafkaUrl - svc := sinker.New(logger, pubSub, esClient, configRepo, policiesGRPCClient, fleetGRPCClient, sinksGRPCClient, otelKafkaUrl, otelEnabled, gauge, counter, inputCounter) + svc := sinker.New(logger, pubSub, esClient, configRepo, policiesGRPCClient, fleetGRPCClient, sinksGRPCClient, + otelKafkaUrl, otelEnabled, gauge, counter, inputCounter, inMemoryCacheConfig.DefaultExpiration) defer func(svc sinker.Service) { err := svc.Stop() if err != nil { diff --git a/go.mod b/go.mod index 6ffdcece9..44791ff7a 100644 --- a/go.mod +++ b/go.mod @@ -120,6 +120,7 @@ require ( github.com/opencontainers/image-spec v1.0.2 // indirect github.com/opencontainers/runc v1.1.5 // indirect github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect diff --git a/go.sum b/go.sum index 9579cc6a6..09c6ef051 100644 --- a/go.sum +++ b/go.sum @@ -603,6 +603,8 @@ github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246c github.com/ory/keto/proto/ory/keto/acl/v1alpha1 v0.0.0-20210616104402-80e043246cf9/go.mod h1:8IoeBQqIRKWU5L6dTKQTlTwVhlUawpqSBJZWfLLN4FM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= diff --git a/maestro/redis/consumer/hashset.go b/maestro/redis/consumer/hashset.go index 04348d4b8..26b31a995 100644 --- a/maestro/redis/consumer/hashset.go +++ b/maestro/redis/consumer/hashset.go @@ -97,10 +97,17 @@ func (es eventStore) handleSinksUpdateCollector(ctx context.Context, event redis if err != nil { es.logger.Error("could not fetch info for sink", zap.String("sink-id", event.SinkID), zap.Error(err)) } - var data config.SinkData - if err := json.Unmarshal(sinkData.Config, &data); err != nil { + var cfg types.Metadata + if err := json.Unmarshal(sinkData.Config, &cfg); err != nil { return err } + data := config.SinkData{ + SinkID: sinkData.Id, + OwnerID: sinkData.OwnerID, + Backend: sinkData.Backend, + Config: cfg, + } + _ = data.State.SetFromString(sinkData.State) deploy, err := config.GetDeploymentJson(es.kafkaUrl, data) if err != nil { diff --git a/pkg/config/config.go b/pkg/config/config.go index e6cf1aaf4..56c0eb8ca 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,6 +6,7 @@ package config import ( "fmt" + "time" "github.com/spf13/viper" ) @@ -39,6 +40,11 @@ type CacheConfig struct { Pass string `mapstructure:"pass"` DB string `mapstructure:"db"` } + +type InMemoryCacheConfig struct { + DefaultExpiration time.Duration `mapstructure:"default_expiration"` +} + type EsConfig struct { URL string `mapstructure:"url"` Pass string `mapstructure:"pass"` @@ -232,3 +238,13 @@ func LoadGRPCConfig(prefix string, svc string) GRPCConfig { cfg.Unmarshal(&aC) return aC } + +func LoadInMemoryCacheConfig(prefix string) InMemoryCacheConfig { + cfg := viper.New() + cfg.SetEnvPrefix(fmt.Sprintf("%s_cache", prefix)) + cfg.SetDefault("default_expiration", 2*time.Minute) + cfg.AutomaticEnv() + var icC InMemoryCacheConfig + cfg.Unmarshal(&icC) + return icC +} diff --git a/sinker/otel/bridgeservice/bridge.go b/sinker/otel/bridgeservice/bridge.go index 43aa759af..9c6763b74 100644 --- a/sinker/otel/bridgeservice/bridge.go +++ b/sinker/otel/bridgeservice/bridge.go @@ -2,6 +2,7 @@ package bridgeservice import ( "context" + "fmt" "sort" "time" @@ -9,11 +10,13 @@ import ( fleetpb "github.com/orb-community/orb/fleet/pb" policiespb "github.com/orb-community/orb/policies/pb" "github.com/orb-community/orb/sinker/config" + "github.com/patrickmn/go-cache" "go.uber.org/zap" ) type BridgeService interface { ExtractAgent(ctx context.Context, channelID string) (*fleetpb.AgentInfoRes, error) + GetPolicyName(ctx context.Context, policyId string) (*policiespb.PolicyRes, error) GetDataSetsFromAgentGroups(ctx context.Context, mfOwnerId string, agentGroupIds []string) (map[string]string, error) NotifyActiveSink(ctx context.Context, mfOwnerId, sinkId, state, message string) error GetSinkIdsFromPolicyID(ctx context.Context, mfOwnerId string, policyID string) (map[string]string, error) @@ -21,28 +24,33 @@ type BridgeService interface { } func NewBridgeService(logger *zap.Logger, + defaultCacheExpiration time.Duration, sinkerCache config.ConfigRepo, policiesClient policiespb.PolicyServiceClient, fleetClient fleetpb.FleetServiceClient, messageInputCounter metrics.Counter) SinkerOtelBridgeService { return SinkerOtelBridgeService{ - logger: logger, - sinkerCache: sinkerCache, - policiesClient: policiesClient, - fleetClient: fleetClient, - messageInputCounter: messageInputCounter, + defaultCacheExpiration: defaultCacheExpiration, + inMemoryCache: *cache.New(defaultCacheExpiration, defaultCacheExpiration*2), + logger: logger, + sinkerCache: sinkerCache, + policiesClient: policiesClient, + fleetClient: fleetClient, + messageInputCounter: messageInputCounter, } } type SinkerOtelBridgeService struct { - logger *zap.Logger - sinkerCache config.ConfigRepo - policiesClient policiespb.PolicyServiceClient - fleetClient fleetpb.FleetServiceClient - messageInputCounter metrics.Counter + inMemoryCache cache.Cache + defaultCacheExpiration time.Duration + logger *zap.Logger + sinkerCache config.ConfigRepo + policiesClient policiespb.PolicyServiceClient + fleetClient fleetpb.FleetServiceClient + messageInputCounter metrics.Counter } // Implementar nova funcao -func (bs *SinkerOtelBridgeService) IncreamentMessageCounter(publisher, subtopic, channel, protocol string) { +func (bs *SinkerOtelBridgeService) IncrementMessageCounter(publisher, subtopic, channel, protocol string) { labels := []string{ "method", "handleMsgFromAgent", "agent_id", publisher, @@ -104,11 +112,31 @@ func (bs *SinkerOtelBridgeService) NotifyActiveSink(ctx context.Context, mfOwner } func (bs *SinkerOtelBridgeService) ExtractAgent(ctx context.Context, channelID string) (*fleetpb.AgentInfoRes, error) { - agentPb, err := bs.fleetClient.RetrieveAgentInfoByChannelID(ctx, &fleetpb.AgentInfoByChannelIDReq{Channel: channelID}) - if err != nil { - return nil, err + cacheKey := fmt.Sprintf("agent-%s", channelID) + value, found := bs.inMemoryCache.Get(cacheKey) + if !found { + agentPb, err := bs.fleetClient.RetrieveAgentInfoByChannelID(ctx, &fleetpb.AgentInfoByChannelIDReq{Channel: channelID}) + if err != nil { + return nil, err + } + bs.inMemoryCache.Set(cacheKey, agentPb, cache.DefaultExpiration) + return agentPb, nil + } + return value.(*fleetpb.AgentInfoRes), nil +} + +func (bs *SinkerOtelBridgeService) GetPolicyName(ctx context.Context, policyId string) (*policiespb.PolicyRes, error) { + cacheKey := fmt.Sprintf("policy-%s", policyId) + value, found := bs.inMemoryCache.Get(cacheKey) + if !found { + policyPb, err := bs.policiesClient.RetrievePolicy(ctx, &policiespb.PolicyByIDReq{PolicyID: policyId}) + if err != nil { + return nil, err + } + bs.inMemoryCache.Set(cacheKey, policyPb, cache.DefaultExpiration) + return policyPb, nil } - return agentPb, nil + return value.(*policiespb.PolicyRes), nil } func (bs *SinkerOtelBridgeService) GetSinkIdsFromDatasetIDs(ctx context.Context, mfOwnerId string, datasetIDs []string) (map[string]string, error) { @@ -116,15 +144,22 @@ func (bs *SinkerOtelBridgeService) GetSinkIdsFromDatasetIDs(ctx context.Context, mapSinkIdPolicy := make(map[string]string) sort.Strings(datasetIDs) for i := 0; i < len(datasetIDs); i++ { - datasetRes, err := bs.policiesClient.RetrieveDataset(ctx, &policiespb.DatasetByIDReq{ - DatasetID: datasetIDs[i], - OwnerID: mfOwnerId, - }) - if err != nil { - bs.logger.Info("unable to retrieve datasets from policy") - return nil, err + datasetID := datasetIDs[i] + cacheKey := fmt.Sprintf("ds-%s-%s", mfOwnerId, datasetID) + value, found := bs.inMemoryCache.Get(cacheKey) + if !found { + datasetRes, err := bs.policiesClient.RetrieveDataset(ctx, &policiespb.DatasetByIDReq{ + DatasetID: datasetID, + OwnerID: mfOwnerId, + }) + if err != nil { + bs.logger.Info("unable to retrieve datasets from policy") + return nil, err + } + value = datasetRes.SinkIds + bs.inMemoryCache.Set(cacheKey, value, cache.DefaultExpiration) } - for _, sinkId := range datasetRes.SinkIds { + for _, sinkId := range value.([]string) { mapSinkIdPolicy[sinkId] = "active" } } diff --git a/sinker/otel/orbreceiver/logs.go b/sinker/otel/orbreceiver/logs.go index c2e418cab..3488ba1ab 100644 --- a/sinker/otel/orbreceiver/logs.go +++ b/sinker/otel/orbreceiver/logs.go @@ -38,7 +38,7 @@ func (r *OrbReceiver) MessageLogsInbound(msg messaging.Message) error { return } - r.sinkerService.IncreamentMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) + r.sinkerService.IncrementMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) if lr.Logs().ResourceLogs().Len() == 0 || lr.Logs().ResourceLogs().At(0).ScopeLogs().Len() == 0 { r.cfg.Logger.Info("No data information from logs request") diff --git a/sinker/otel/orbreceiver/metrics.go b/sinker/otel/orbreceiver/metrics.go index b5020ee5c..885d4bbbd 100644 --- a/sinker/otel/orbreceiver/metrics.go +++ b/sinker/otel/orbreceiver/metrics.go @@ -40,7 +40,7 @@ func (r *OrbReceiver) MessageMetricsInbound(msg messaging.Message) error { return } - r.sinkerService.IncreamentMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) + r.sinkerService.IncrementMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) if mr.Metrics().ResourceMetrics().Len() == 0 || mr.Metrics().ResourceMetrics().At(0).ScopeMetrics().Len() == 0 { r.cfg.Logger.Info("No data information from metrics request") @@ -94,7 +94,16 @@ func (r *OrbReceiver) ProccessMetricsContext(scope pmetric.ScopeMetrics, channel for k, v := range agentPb.OrbTags { scope = r.injectScopeMetricsAttribute(scope, k, v) } + + policyData, err := r.sinkerService.GetPolicyName(r.ctx, polID) + if err != nil { + execCancelF() + r.cfg.Logger.Info("policy was not found with the following id", zap.String("policy_id", polID)) + return + } r.injectScopeMetricsAttribute(scope, "agent", agentPb.AgentName) + r.injectScopeMetricsAttribute(scope, "policy_id", polID) + r.injectScopeMetricsAttribute(scope, "policy_name", policyData.Name) scope = r.replaceScopeMetricsTimestamp(scope, pcommon.NewTimestampFromTime(time.Now())) sinkIds, err := r.sinkerService.GetSinkIdsFromDatasetIDs(execCtx, agentPb.OwnerID, datasetIDs) diff --git a/sinker/otel/orbreceiver/traces.go b/sinker/otel/orbreceiver/traces.go index b47335863..f73530227 100644 --- a/sinker/otel/orbreceiver/traces.go +++ b/sinker/otel/orbreceiver/traces.go @@ -38,7 +38,7 @@ func (r *OrbReceiver) MessageTracesInbound(msg messaging.Message) error { return } - r.sinkerService.IncreamentMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) + r.sinkerService.IncrementMessageCounter(msg.Publisher, msg.Subtopic, msg.Channel, msg.Protocol) if tr.Traces().ResourceSpans().Len() == 0 || tr.Traces().ResourceSpans().At(0).ScopeSpans().Len() == 0 { r.cfg.Logger.Info("No data information from traces request") diff --git a/sinker/service.go b/sinker/service.go index 2835fcdcf..89260be98 100644 --- a/sinker/service.go +++ b/sinker/service.go @@ -49,9 +49,10 @@ type SinkerService struct { otelLogsCancelFunct context.CancelFunc otelKafkaUrl string - sinkerCache config.ConfigRepo - esclient *redis.Client - logger *zap.Logger + sinkerCache config.ConfigRepo + inMemoryCacheExpiration time.Duration + esclient *redis.Client + logger *zap.Logger hbTicker *time.Ticker hbDone chan bool @@ -71,7 +72,9 @@ type SinkerService struct { } func (svc SinkerService) Start() error { - svc.asyncContext, svc.cancelAsyncContext = context.WithCancel(context.WithValue(context.Background(), "routine", "async")) + ctx := context.WithValue(context.Background(), "routine", "async") + ctx = context.WithValue(ctx, "cache_expiry", svc.inMemoryCacheExpiration) + svc.asyncContext, svc.cancelAsyncContext = context.WithCancel(ctx) if !svc.otel { topic := fmt.Sprintf("channels.*.%s", BackendMetricsTopic) if err := svc.pubSub.Subscribe(topic, svc.handleMsgFromAgent); err != nil { @@ -96,13 +99,12 @@ func (svc SinkerService) Start() error { func (svc SinkerService) startOtel(ctx context.Context) error { if svc.otel { var err error - // starting Otel Metrics components - bridgeServiceMetrics := bridgeservice.NewBridgeService(svc.logger, svc.sinkerCache, svc.policiesClient, svc.fleetClient, svc.messageInputCounter) - svc.otelMetricsCancelFunct, err = otel.StartOtelMetricsComponents(ctx, &bridgeServiceMetrics, svc.logger, svc.otelKafkaUrl, svc.pubSub) + + bridgeService := bridgeservice.NewBridgeService(svc.logger, svc.inMemoryCacheExpiration, svc.sinkerCache, svc.policiesClient, svc.fleetClient, svc.messageInputCounter) + svc.otelMetricsCancelFunct, err = otel.StartOtelMetricsComponents(ctx, &bridgeService, svc.logger, svc.otelKafkaUrl, svc.pubSub) // starting Otel Logs components - bridgeServiceLogs := bridgeservice.NewBridgeService(svc.logger, svc.sinkerCache, svc.policiesClient, svc.fleetClient, svc.messageInputCounter) - svc.otelLogsCancelFunct, err = otel.StartOtelLogsComponents(ctx, &bridgeServiceLogs, svc.logger, svc.otelKafkaUrl, svc.pubSub) + svc.otelLogsCancelFunct, err = otel.StartOtelLogsComponents(ctx, &bridgeService, svc.logger, svc.otelKafkaUrl, svc.pubSub) if err != nil { svc.logger.Error("error during StartOtelComponents", zap.Error(err)) @@ -147,21 +149,23 @@ func New(logger *zap.Logger, requestGauge metrics.Gauge, requestCounter metrics.Counter, inputCounter metrics.Counter, + defaultCacheExpiration time.Duration, ) Service { pktvisor.Register(logger) return &SinkerService{ - logger: logger, - pubSub: pubSub, - esclient: esclient, - sinkerCache: configRepo, - policiesClient: policiesClient, - fleetClient: fleetClient, - sinksClient: sinksClient, - requestGauge: requestGauge, - requestCounter: requestCounter, - messageInputCounter: inputCounter, - otel: enableOtel, - otelKafkaUrl: otelKafkaUrl, + inMemoryCacheExpiration: defaultCacheExpiration, + logger: logger, + pubSub: pubSub, + esclient: esclient, + sinkerCache: configRepo, + policiesClient: policiesClient, + fleetClient: fleetClient, + sinksClient: sinksClient, + requestGauge: requestGauge, + requestCounter: requestCounter, + messageInputCounter: inputCounter, + otel: enableOtel, + otelKafkaUrl: otelKafkaUrl, } } From 3b11dae1461828ac51a3f81280ef3ea585785b9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 18:21:10 -0300 Subject: [PATCH 089/115] fix: bump mkdocs-material from 9.1.17 to 9.1.18 (#2479) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python-test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-test/requirements.txt b/python-test/requirements.txt index 3f436595d..3bae918ea 100644 --- a/python-test/requirements.txt +++ b/python-test/requirements.txt @@ -9,7 +9,7 @@ behavex==2.0.1 deepdiff==6.3.0 jsonschema==4.17.3 mkdocs==1.4.3 -mkdocs-material==9.1.17 +mkdocs-material==9.1.18 prometheus-client==0.17.0 psutil==5.9.5 webdriver-manager==3.8.6 From 1df483cd90e7d4022e4d16b25f55ee3483c2da51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 18:21:27 -0300 Subject: [PATCH 090/115] fix: bump docker from 5.0.3 to 6.1.3 (#2478) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- python-test/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-test/requirements.txt b/python-test/requirements.txt index 3bae918ea..b2e1fc660 100644 --- a/python-test/requirements.txt +++ b/python-test/requirements.txt @@ -1,6 +1,6 @@ behave==1.2.6 ciso8601==2.3.0 -docker==5.0.3 +docker==6.1.3 PyHamcrest==2.0.4 PyYAML==6.0 retry==0.9.2 From 9ea962a07c636ee647be51533b92701d250dad31 Mon Sep 17 00:00:00 2001 From: brnvalenca <79707831+brnvalenca@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:40:19 -0300 Subject: [PATCH 091/115] [ENG-166] Create sink error message (#2492) [ENG-166] Create sink error message - Adjusting returned error message in face of bad request error --- fleet/api/http/transport.go | 8 ++-- pkg/errors/types.go | 45 +++++++++++++++++++ pkg/types/maps.go | 2 + sinks/api/http/endpoint.go | 15 ++++--- sinks/api/http/endpoint_test.go | 2 +- sinks/api/http/requests.go | 35 +++++++++++---- sinks/api/http/transport.go | 29 ++++++++++++ .../basicauth/authentication.go | 14 ++++++ .../backend/otlphttpexporter/configuration.go | 14 ++++-- sinks/backend/prometheus/configuration.go | 8 ++-- sinks/sinks_service.go | 13 ++++-- 11 files changed, 157 insertions(+), 28 deletions(-) diff --git a/fleet/api/http/transport.go b/fleet/api/http/transport.go index 7fd929dc3..265f680bb 100644 --- a/fleet/api/http/transport.go +++ b/fleet/api/http/transport.go @@ -7,6 +7,10 @@ package http import ( "context" "encoding/json" + "io" + "net/http" + "strings" + kitot "github.com/go-kit/kit/tracing/opentracing" kithttp "github.com/go-kit/kit/transport/http" "github.com/go-zoo/bone" @@ -19,9 +23,6 @@ import ( "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/prometheus/client_golang/prometheus/promhttp" - "io" - "net/http" - "strings" ) const ( @@ -282,6 +283,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { case errors.Contains(errorVal, errors.ErrUnsupportedContentType): w.WriteHeader(http.StatusUnsupportedMediaType) + case errors.Contains(errorVal, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) case errors.Contains(errorVal, errors.ErrNotFound): diff --git a/pkg/errors/types.go b/pkg/errors/types.go index 73186e2bb..f09a283c4 100644 --- a/pkg/errors/types.go +++ b/pkg/errors/types.go @@ -21,6 +21,51 @@ var ( // ErrMalformedEntity indicates a malformed entity specification ErrMalformedEntity = New("malformed entity specification") + // ErrEntityNameNotFound indicates that the entity name was not found + ErrEntityNameNotFound = New("malformed entity specificiation. name not found") + + // ErrBackendNotFound indicates that the backend field was not found + ErrBackendNotFound = New("malformed entity specification. backend field is expected") + + // ErrInvalidBackend indicates a malformed entity specification on backend field + ErrInvalidBackend = New("malformed entity specification. backend field is invalid") + + // ErrConfigFieldNotFound indicates that configuration field was not found + ErrConfigFieldNotFound = New("malformed entity specification. configuration field is expected") + + // ErrExporterFieldNotFound indicates that exporter field was not found + ErrExporterFieldNotFound = New("malformed entity specification. exporter field is expected on configuration field") + + // ErrAuthFieldNotFound indicates that authentication field was not found on configuration field + ErrAuthFieldNotFound = New("malformed entity specification. authentication fields are expected on configuration field") + + // ErrAuthTypeNotFound indicates that authentication type field was not found on the authentication field + ErrAuthTypeNotFound = New("malformed entity specification: authentication type field is expected on configuration field") + + // ErrInvalidAuthType indicates invalid authentication type + ErrInvalidAuthType = New("malformed entity specification. type key on authentication field is invalid") + + // ErrPasswordNotFound indicates that password key was not found + ErrPasswordNotFound = New("malformed entity specification. password key is expected on authentication field") + + // ErrEndPointNotFound indicates that endpoint field was not found on exporter field for otlp backend + ErrEndpointNotFound = New("malformed entity specification. endpoint field is expected on exporter field") + + // ErrInvalidEndpoint indicates that endpoint field is not valid + ErrInvalidEndpoint = New("malformed entity specification. endpoint field is invalid") + + // ErrInvalidPasswordType indicates invalid password key on authentication field + ErrInvalidPasswordType = New("malformed entity specification. password key on authentication field is invalid") + + // ErrInvalidUsernameType indicates invalid username key on authentication field + ErrInvalidUsernameType = New("malformed entity specification. username key on authentication field is invalid") + + // ErrRemoteHostNotFound indicates that remote host field was not found + ErrRemoteHostNotFound = New("malformed entity specification. remote host is expected on exporter field") + + // ErrInvalidRemoteHost indicates that remote host field is invalid + ErrInvalidRemoteHost = New("malformed entity specification. remote host type is invalid") + // ErrNotFound indicates a non-existent entity request. ErrNotFound = New("non-existent entity") diff --git a/pkg/types/maps.go b/pkg/types/maps.go index 29c32e982..1e91f5230 100644 --- a/pkg/types/maps.go +++ b/pkg/types/maps.go @@ -6,6 +6,7 @@ package types import ( "encoding/json" + "github.com/orb-community/orb/pkg/errors" ) @@ -55,6 +56,7 @@ func (s *Metadata) GetSubMetadata(key string) Metadata { case Metadata: return v.(Metadata) } + return nil } diff --git a/sinks/api/http/endpoint.go b/sinks/api/http/endpoint.go index d699931fe..f3b59496f 100644 --- a/sinks/api/http/endpoint.go +++ b/sinks/api/http/endpoint.go @@ -47,7 +47,6 @@ func addEndpoint(svc sinks.SinkService) endpoint.Endpoint { svc.GetLogger().Error("got error in validating request", zap.Error(err)) return nil, err } - nID, err := types.NewIdentifier(req.Name) if err != nil { svc.GetLogger().Error("got error in creating new identifier", zap.Error(err)) @@ -58,20 +57,26 @@ func addEndpoint(svc sinks.SinkService) endpoint.Endpoint { var configSvc *sinks.Configuration if len(req.Format) > 0 && req.Format == "yaml" { if len(req.ConfigData) > 0 { + if req.Backend == "" { + return nil, errors.Wrap(errors.ErrBackendNotFound, errors.New("backend not found")) + } configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromYaml(req.Backend, req.ConfigData) if err != nil { svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) - return nil, errors.Wrap(errors.ErrMalformedEntity, err) + return nil, err } } else { - svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) - return nil, errors.Wrap(errors.ErrMalformedEntity, errors.New("missing required field when format is sent, config_data must be sent also")) + svc.GetLogger().Error("got error in parse and validate configuration. config_data field is expected", zap.Error(err)) + return nil, errors.New("malformed entity specification. configuration field is expected") } } else { + if req.Backend == "" { + return nil, errors.Wrap(errors.ErrBackendNotFound, errors.New("backend not found")) + } configSvc, exporterConfig, authConfig, err = GetConfigurationAndMetadataFromMeta(req.Backend, req.Config) if err != nil { svc.GetLogger().Error("got error in parse and validate configuration", zap.Error(err)) - return nil, errors.Wrap(errors.ErrMalformedEntity, err) + return nil, err } } config := types.Metadata{ diff --git a/sinks/api/http/endpoint_test.go b/sinks/api/http/endpoint_test.go index 68ca20fce..316885cfa 100644 --- a/sinks/api/http/endpoint_test.go +++ b/sinks/api/http/endpoint_test.go @@ -358,7 +358,7 @@ func TestCreateSinks(t *testing.T) { req: jsonSinkTestConfig2, contentType: contentType, auth: token, - status: http.StatusInternalServerError, + status: http.StatusBadRequest, location: "/sinks", }, "add sink with no authentication type within config": { diff --git a/sinks/api/http/requests.go b/sinks/api/http/requests.go index 0bf432b03..df5f336a0 100644 --- a/sinks/api/http/requests.go +++ b/sinks/api/http/requests.go @@ -39,20 +39,31 @@ type addReq struct { } func GetConfigurationAndMetadataFromMeta(backendName string, config types.Metadata) (configSvc *sinks.Configuration, exporter types.Metadata, authentication types.Metadata, err error) { - if backendName == "" || !backend.HaveBackend(backendName) { - return nil, nil, nil, errors.Wrap(errors.ErrMalformedEntity, errors.New("backend not found: "+backendName)) + + if !backend.HaveBackend(backendName) { + return nil, nil, nil, errors.Wrap(errors.ErrInvalidBackend, errors.New("invalid backend")) + } + + if config == nil { + return nil, nil, nil, errors.Wrap(errors.ErrConfigFieldNotFound, errors.New("backend must not be nil")) } configSvc = &sinks.Configuration{ Exporter: backend.GetBackend(backendName), } exporter = config.GetSubMetadata("exporter") + if exporter == nil { + return nil, nil, nil, errors.Wrap(errors.ErrExporterFieldNotFound, errors.New("exporter field must not be nil")) + } err = configSvc.Exporter.ValidateConfiguration(exporter) if err != nil { return } authentication = config.GetSubMetadata(authentication_type.AuthenticationKey) + if authentication == nil { + return nil, nil, nil, errors.Wrap(errors.ErrAuthFieldNotFound, errors.New("authentication field must not be nil")) + } authtype, ok := authentication["type"] if !ok { authtype = basicauth.AuthType @@ -61,12 +72,11 @@ func GetConfigurationAndMetadataFromMeta(backendName string, config types.Metada case string: break default: - err = errors.Wrap(errors.ErrMalformedEntity, errors.New("invalid config")) return } authTypeSvc, ok := authentication_type.GetAuthType(authtype.(string)) if !ok { - err = errors.Wrap(errors.ErrMalformedEntity, errors.New("invalid required field authentication type")) + err = errors.Wrap(errors.ErrInvalidAuthType, errors.New("invalid required field authentication type")) return } configSvc.Authentication = authTypeSvc @@ -75,8 +85,9 @@ func GetConfigurationAndMetadataFromMeta(backendName string, config types.Metada } func GetConfigurationAndMetadataFromYaml(backendName string, config string) (configSvc *sinks.Configuration, exporter types.Metadata, authentication types.Metadata, err error) { - if backendName == "" || !backend.HaveBackend(backendName) { - return nil, nil, nil, errors.Wrap(errors.ErrMalformedEntity, errors.New("backend not found")) + + if !backend.HaveBackend(backendName) { + return nil, nil, nil, errors.Wrap(errors.ErrInvalidBackend, errors.New("invalid backend")) } configSvc = &sinks.Configuration{ @@ -88,12 +99,18 @@ func GetConfigurationAndMetadataFromYaml(backendName string, config string) (con return } exporter = configStr.GetSubMetadata("exporter") + if exporter == nil { + return nil, nil, nil, errors.New("malformed entity specification. exporter field is expected on configuration field") + } err = configSvc.Exporter.ValidateConfiguration(exporter) if err != nil { return } authentication = configStr.GetSubMetadata(authentication_type.AuthenticationKey) + if authentication == nil { + return nil, nil, nil, errors.New("malformed entity specification. authentication fields are expected on configuration field") + } authtype, ok := authentication["type"] if !ok { authtype = basicauth.AuthType @@ -102,12 +119,12 @@ func GetConfigurationAndMetadataFromYaml(backendName string, config string) (con case string: break default: - err = errors.Wrap(errors.ErrMalformedEntity, errors.New("invalid config")) + err = errors.ErrInvalidAuthType return } authTypeSvc, ok := authentication_type.GetAuthType(authtype.(string)) if !ok { - err = errors.Wrap(errors.ErrMalformedEntity, errors.New("invalid required field authentication type")) + err = errors.Wrap(errors.ErrInvalidAuthType, errors.New("invalid required field authentication type")) return } configSvc.Authentication = authTypeSvc @@ -121,7 +138,7 @@ func (req addReq) validate() (err error) { } if req.Name == "" { - return errors.Wrap(errors.ErrMalformedEntity, errors.New("name not found")) + return errors.Wrap(errors.ErrEntityNameNotFound, errors.New("name not found")) } _, err = types.NewIdentifier(req.Name) diff --git a/sinks/api/http/transport.go b/sinks/api/http/transport.go index b96cc5dd8..8f0277f76 100644 --- a/sinks/api/http/transport.go +++ b/sinks/api/http/transport.go @@ -236,6 +236,35 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { case errors.Contains(errorVal, errors.ErrUnsupportedContentType): w.WriteHeader(http.StatusUnsupportedMediaType) + + case errors.Contains(errorVal, errors.ErrInvalidEndpoint): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrEndpointNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrBackendNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrPasswordNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrAuthTypeNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrInvalidUsernameType): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrInvalidPasswordType): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrInvalidAuthType): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrRemoteHostNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrAuthFieldNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrConfigFieldNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrExporterFieldNotFound): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrInvalidBackend): + w.WriteHeader(http.StatusBadRequest) + case errors.Contains(errorVal, errors.ErrEntityNameNotFound): + w.WriteHeader(http.StatusBadRequest) case errors.Contains(errorVal, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) case errors.Contains(errorVal, errors.ErrNotFound): diff --git a/sinks/authentication_type/basicauth/authentication.go b/sinks/authentication_type/basicauth/authentication.go index 181604a6d..71de2fa66 100644 --- a/sinks/authentication_type/basicauth/authentication.go +++ b/sinks/authentication_type/basicauth/authentication.go @@ -57,6 +57,17 @@ func (a *AuthConfig) ValidateConfiguration(inputFormat string, input interface{} switch inputFormat { case "object": for key, value := range input.(types.Metadata) { + if _, ok := value.(string); !ok { + if key == "password" { + return errors.Wrap(errors.ErrInvalidPasswordType, errors.New("invalid auth type for field: " + key)) + } + if key == "type" { + return errors.Wrap(errors.ErrInvalidAuthType, errors.New("invalid auth type for field: " + key)) + } + if key == "username" { + return errors.Wrap(errors.ErrInvalidUsernameType, errors.New("invalid auth type for field: " + key)) + } + } vs := value.(string) if key == UsernameConfigFeature { if len(vs) == 0 { @@ -144,6 +155,9 @@ func (a *AuthConfig) EncodeInformation(outputFormat string, input interface{}) ( case types.Metadata: inputMeta := input.(types.Metadata) authMeta := inputMeta.GetSubMetadata(authentication_type.AuthenticationKey) + if _, ok := authMeta[PasswordConfigFeature].(string); !ok { + return nil, errors.Wrap(errors.ErrPasswordNotFound, errors.New("password field was not found")) + } encoded, err := a.encryptionService.EncodePassword(authMeta[PasswordConfigFeature].(string)) if err != nil { return nil, err diff --git a/sinks/backend/otlphttpexporter/configuration.go b/sinks/backend/otlphttpexporter/configuration.go index b931603d1..87143dd80 100644 --- a/sinks/backend/otlphttpexporter/configuration.go +++ b/sinks/backend/otlphttpexporter/configuration.go @@ -1,6 +1,8 @@ package otlphttpexporter import ( + "net/url" + "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks/backend" @@ -77,9 +79,15 @@ func (b *OTLPHTTPBackend) CreateFeatureConfig() []backend.ConfigFeature { } func (b *OTLPHTTPBackend) ValidateConfiguration(config types.Metadata) error { - - if _, ok := config[EndpointFieldName]; !ok { - return errors.New("endpoint is required") + if config[EndpointFieldName] == "" { + return errors.New("malformed entity specification. endpoint must not be empty") + } + endpointUrl, endpointOk := config[EndpointFieldName] + if !endpointOk { + return errors.Wrap(errors.ErrEndpointNotFound, errors.New("endpoint not found")) + } + if _, err := url.ParseRequestURI(endpointUrl.(string)); err != nil { + return errors.Wrap(errors.ErrInvalidEndpoint, err) } return nil } diff --git a/sinks/backend/prometheus/configuration.go b/sinks/backend/prometheus/configuration.go index ff302f198..f4aac0529 100644 --- a/sinks/backend/prometheus/configuration.go +++ b/sinks/backend/prometheus/configuration.go @@ -1,11 +1,12 @@ package prometheus import ( + "net/url" + "github.com/orb-community/orb/pkg/errors" "github.com/orb-community/orb/pkg/types" "github.com/orb-community/orb/sinks/backend" "gopkg.in/yaml.v3" - "net/url" ) var invalidCustomHeaders = []string{ @@ -45,14 +46,15 @@ func (p *Backend) ParseConfig(format string, config string) (configReturn types. } func (p *Backend) ValidateConfiguration(config types.Metadata) error { + remoteUrl, remoteHostOk := config[RemoteHostURLConfigFeature] if !remoteHostOk { - return errors.New("must send valid URL for Remote Write") + return errors.ErrRemoteHostNotFound } // Validate remote_host _, err := url.ParseRequestURI(remoteUrl.(string)) if err != nil { - return errors.New("must send valid URL for Remote Write") + return errors.ErrInvalidRemoteHost } // check for custom http headers customHeaders, customHeadersOk := config[CustomHeadersConfigFeature] diff --git a/sinks/sinks_service.go b/sinks/sinks_service.go index 80d08a475..66d595e11 100644 --- a/sinks/sinks_service.go +++ b/sinks/sinks_service.go @@ -41,7 +41,7 @@ func (svc sinkService) CreateSink(ctx context.Context, token string, sink Sink) } at, err := validateAuthType(&sink) if err != nil { - return Sink{}, errors.Wrap(ErrCreateSink, err) + return Sink{}, err } cfg := Configuration{ Authentication: at, @@ -51,7 +51,7 @@ func (svc sinkService) CreateSink(ctx context.Context, token string, sink Sink) // encrypt data for the password sink, err = svc.encryptMetadata(cfg, sink) if err != nil { - return Sink{}, errors.Wrap(ErrCreateSink, err) + return Sink{}, err } //// add default values @@ -91,11 +91,16 @@ func validateAuthType(s *Sink) (authentication_type.AuthenticationType, error) { } authTypeStr, ok := authMetadata["type"] if !ok { - return nil, errors.New("authentication type not found") + return nil, errors.Wrap(errors.ErrAuthTypeNotFound, errors.New("authentication type not found")) } + + if _, ok := authTypeStr.(string); !ok { + return nil, errors.Wrap(errors.ErrInvalidAuthType, errors.New("invalid authentication type")) + } + authType, ok := authentication_type.GetAuthType(authTypeStr.(string)) if !ok { - return nil, errors.New("authentication type not found") + return nil, errors.Wrap(errors.ErrInvalidAuthType, errors.New("invalid authentication type")) } err := authType.ValidateConfiguration("object", authMetadata) From ca7cd06470373e4b76720e9ab709208261efb7f6 Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Tue, 11 Jul 2023 19:03:45 -0300 Subject: [PATCH 092/115] fix(sinker): add ownerID to policy call. (#2499) --- sinker/otel/bridgeservice/bridge.go | 6 +++--- sinker/otel/orbreceiver/logs.go | 2 ++ sinker/otel/orbreceiver/metrics.go | 7 ------- sinker/otel/orbreceiver/traces.go | 2 ++ 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/sinker/otel/bridgeservice/bridge.go b/sinker/otel/bridgeservice/bridge.go index 9c6763b74..4bb14c6f7 100644 --- a/sinker/otel/bridgeservice/bridge.go +++ b/sinker/otel/bridgeservice/bridge.go @@ -16,7 +16,7 @@ import ( type BridgeService interface { ExtractAgent(ctx context.Context, channelID string) (*fleetpb.AgentInfoRes, error) - GetPolicyName(ctx context.Context, policyId string) (*policiespb.PolicyRes, error) + GetPolicyName(ctx context.Context, policyId, ownerId string) (*policiespb.PolicyRes, error) GetDataSetsFromAgentGroups(ctx context.Context, mfOwnerId string, agentGroupIds []string) (map[string]string, error) NotifyActiveSink(ctx context.Context, mfOwnerId, sinkId, state, message string) error GetSinkIdsFromPolicyID(ctx context.Context, mfOwnerId string, policyID string) (map[string]string, error) @@ -125,11 +125,11 @@ func (bs *SinkerOtelBridgeService) ExtractAgent(ctx context.Context, channelID s return value.(*fleetpb.AgentInfoRes), nil } -func (bs *SinkerOtelBridgeService) GetPolicyName(ctx context.Context, policyId string) (*policiespb.PolicyRes, error) { +func (bs *SinkerOtelBridgeService) GetPolicyName(ctx context.Context, policyId, ownerID string) (*policiespb.PolicyRes, error) { cacheKey := fmt.Sprintf("policy-%s", policyId) value, found := bs.inMemoryCache.Get(cacheKey) if !found { - policyPb, err := bs.policiesClient.RetrievePolicy(ctx, &policiespb.PolicyByIDReq{PolicyID: policyId}) + policyPb, err := bs.policiesClient.RetrievePolicy(ctx, &policiespb.PolicyByIDReq{PolicyID: policyId, OwnerID: ownerID}) if err != nil { return nil, err } diff --git a/sinker/otel/orbreceiver/logs.go b/sinker/otel/orbreceiver/logs.go index 3488ba1ab..86f844499 100644 --- a/sinker/otel/orbreceiver/logs.go +++ b/sinker/otel/orbreceiver/logs.go @@ -92,6 +92,8 @@ func (r *OrbReceiver) ProccessLogsContext(scope plog.ScopeLogs, channel string) for k, v := range agentPb.OrbTags { scope = r.injectScopeLogsAttribute(scope, k, v) } + r.injectScopeLogsAttribute(scope, "agent", agentPb.AgentName) + r.injectScopeLogsAttribute(scope, "policy_id", polID) sinkIds, err := r.sinkerService.GetSinkIdsFromDatasetIDs(execCtx, agentPb.OwnerID, datasetIDs) if err != nil { diff --git a/sinker/otel/orbreceiver/metrics.go b/sinker/otel/orbreceiver/metrics.go index 885d4bbbd..90a851153 100644 --- a/sinker/otel/orbreceiver/metrics.go +++ b/sinker/otel/orbreceiver/metrics.go @@ -95,15 +95,8 @@ func (r *OrbReceiver) ProccessMetricsContext(scope pmetric.ScopeMetrics, channel scope = r.injectScopeMetricsAttribute(scope, k, v) } - policyData, err := r.sinkerService.GetPolicyName(r.ctx, polID) - if err != nil { - execCancelF() - r.cfg.Logger.Info("policy was not found with the following id", zap.String("policy_id", polID)) - return - } r.injectScopeMetricsAttribute(scope, "agent", agentPb.AgentName) r.injectScopeMetricsAttribute(scope, "policy_id", polID) - r.injectScopeMetricsAttribute(scope, "policy_name", policyData.Name) scope = r.replaceScopeMetricsTimestamp(scope, pcommon.NewTimestampFromTime(time.Now())) sinkIds, err := r.sinkerService.GetSinkIdsFromDatasetIDs(execCtx, agentPb.OwnerID, datasetIDs) diff --git a/sinker/otel/orbreceiver/traces.go b/sinker/otel/orbreceiver/traces.go index f73530227..13486c32d 100644 --- a/sinker/otel/orbreceiver/traces.go +++ b/sinker/otel/orbreceiver/traces.go @@ -92,6 +92,8 @@ func (r *OrbReceiver) ProccessTracesContext(scope ptrace.ScopeSpans, channel str for k, v := range agentPb.OrbTags { scope = r.injectScopeSpansAttribute(scope, k, v) } + r.injectScopeSpansAttribute(scope, "agent", agentPb.AgentName) + r.injectScopeSpansAttribute(scope, "policy_id", polID) sinkIds, err := r.sinkerService.GetSinkIdsFromDatasetIDs(execCtx, agentPb.OwnerID, datasetIDs) if err != nil { From 1e33b81106ccf12a8fbcd480e2aa88ab4bb8112f Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Fri, 14 Jul 2023 01:02:50 -0300 Subject: [PATCH 093/115] fix(sinks): overall sinks fixes with custom headers and a few sanity tests fixes (#2500) * fix(sinks): fixes on custom headers validation. * fix(sinks): general fixes on working. * fix(sinks): fix conflict error code. * fix(sinks): fix header not reaching redis cache. * fix(sinks): simplify config on pass-through. * fix(sinks): add better error messages. --- maestro/config/exporter_builder.go | 26 +++++-- maestro/config/types.go | 3 +- sinker/config/types.go | 15 +--- sinker/config_state_check.go | 4 +- sinker/message_handler.go | 21 +++-- sinker/redis/consumer/streams.go | 9 +-- sinker/redis/sinker_test.go | 78 ++++++++++++++----- .../backend/otlphttpexporter/configuration.go | 15 ++++ sinks/backend/prometheus/configuration.go | 2 +- sinks/sinks_service.go | 13 ++-- 10 files changed, 128 insertions(+), 58 deletions(-) diff --git a/maestro/config/exporter_builder.go b/maestro/config/exporter_builder.go index 56231ba42..a6f27af97 100644 --- a/maestro/config/exporter_builder.go +++ b/maestro/config/exporter_builder.go @@ -51,11 +51,23 @@ type OTLPHTTPExporterBuilder struct { } func (O *OTLPHTTPExporterBuilder) GetExportersFromMetadata(config types.Metadata, authenticationExtensionName string) (Exporters, string) { - endpointCfg := config.GetSubMetadata("exporter")["endpoint"].(string) - return Exporters{ - OTLPExporter: &OTLPExporterConfig{ - Endpoint: endpointCfg, - Auth: Auth{Authenticator: authenticationExtensionName}, - }, - }, "otlphttp" + exporterSubMeta := config.GetSubMetadata("exporter") + endpointCfg := exporterSubMeta["endpoint"].(string) + customHeaders, ok := exporterSubMeta["headers"] + if !ok || customHeaders == nil { + return Exporters{ + OTLPExporter: &OTLPExporterConfig{ + Endpoint: endpointCfg, + Auth: Auth{Authenticator: authenticationExtensionName}, + }, + }, "otlphttp" + } else { + return Exporters{ + OTLPExporter: &OTLPExporterConfig{ + Endpoint: endpointCfg, + Auth: Auth{Authenticator: authenticationExtensionName}, + Headers: customHeaders.(map[string]interface{}), + }, + }, "otlphttp" + } } diff --git a/maestro/config/types.go b/maestro/config/types.go index da3321da4..637abb2c2 100644 --- a/maestro/config/types.go +++ b/maestro/config/types.go @@ -134,7 +134,8 @@ type LoggingExporterConfig struct { } type OTLPExporterConfig struct { - Endpoint string `json:"endpoint" yaml:"endpoint"` + Endpoint string `json:"endpoint" yaml:"endpoint"` + Headers map[string]interface{} `json:"headers,omitempty" yaml:"headers,omitempty"` Auth struct { Authenticator string `json:"authenticator" yaml:"authenticator"` } diff --git a/sinker/config/types.go b/sinker/config/types.go index 53dfe5b93..59a39c8d1 100644 --- a/sinker/config/types.go +++ b/sinker/config/types.go @@ -6,22 +6,15 @@ package config import ( "database/sql/driver" + "github.com/orb-community/orb/pkg/types" "time" ) // SinkConfigParser to be compatible with new sinks config is coming from eventbus type SinkConfig struct { - SinkID string `json:"sink_id"` - OwnerID string `json:"owner_id"` - Authentication struct { - Type string `json:"type"` - Password string `json:"password"` - Username string `json:"username"` - } `json:"authentication"` - Exporter struct { - RemoteHost string `json:"remote_host"` - } `json:"exporter"` - OpenTelemetry string `json:"opentelemetry"` + SinkID string `json:"sink_id"` + OwnerID string `json:"owner_id"` + Config types.Metadata `json:"config"` State PrometheusState `json:"state,omitempty"` Msg string `json:"msg,omitempty"` LastRemoteWrite time.Time `json:"last_remote_write,omitempty"` diff --git a/sinker/config_state_check.go b/sinker/config_state_check.go index 4eb7f2af8..7a6301805 100644 --- a/sinker/config_state_check.go +++ b/sinker/config_state_check.go @@ -15,7 +15,7 @@ const ( streamID = "orb.sinker" streamLen = 1000 CheckerFreq = 5 * time.Minute - DefaultTimeout = 30 * time.Minute + DefaultTimeout = 5 * time.Minute ) func (svc *SinkerService) checkState(_ time.Time) { @@ -35,7 +35,7 @@ func (svc *SinkerService) checkState(_ time.Time) { // Set idle if the sinker is more than 30 minutes not sending metrics (Remove from Redis) if cfg.LastRemoteWrite.Add(DefaultTimeout).Before(time.Now()) { if cfg.State == config.Active { - if cfg.OpenTelemetry != "enabled" { + if v, ok := cfg.Config["opentelemetry"]; !ok || v != "enabled" { if err := svc.sinkerCache.Remove(cfg.OwnerID, cfg.SinkID); err != nil { svc.logger.Error("error updating sink config cache", zap.Error(err)) return diff --git a/sinker/message_handler.go b/sinker/message_handler.go index 1ede15553..7db500b25 100644 --- a/sinker/message_handler.go +++ b/sinker/message_handler.go @@ -29,12 +29,18 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner return err } ctx := context.Background() - if cfgRepo.OpenTelemetry == "enabled" { + otelMetadata, ok := cfgRepo.Config["opentelemetry"] + if ok && otelMetadata == "enabled" { svc.logger.Info("deprecate warning opentelemetry sink scraping legacy agent", zap.String("sink-ID", cfgRepo.SinkID)) ctx = context.WithValue(ctx, "deprecation", "opentelemetry") } + configMetadata := cfgRepo.Config.GetSubMetadata("exporter") + if configMetadata == nil { + svc.logger.Error("unable to find prometheus remote host", zap.Error(err)) + return err + } cfg := prometheus.NewConfig( - prometheus.WriteURLOption(cfgRepo.Exporter.RemoteHost), + prometheus.WriteURLOption(configMetadata["remote_host"].(string)), ) promClient, err := prometheus.NewClient(cfg) @@ -42,9 +48,13 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner svc.logger.Error("unable to construct client", zap.Error(err)) return err } - + authMetadata := cfgRepo.Config.GetSubMetadata("authentication") + if authMetadata == nil { + svc.logger.Error("unable to find prometheus remote host", zap.Error(err)) + return err + } var headers = make(map[string]string) - headers["Authorization"] = svc.encodeBase64(cfgRepo.Authentication.Username, cfgRepo.Authentication.Password) + headers["Authorization"] = svc.encodeBase64(authMetadata["username"].(string), authMetadata["password"].(string)) result, writeErr := promClient.WriteTimeSeries(ctx, tsList, prometheus.WriteOptions{Headers: headers}) if err := error(writeErr); err != nil { if cfgRepo.Msg != fmt.Sprint(err) { @@ -62,7 +72,8 @@ func (svc SinkerService) remoteWriteToPrometheus(tsList prometheus.TSList, owner return err } - svc.logger.Debug("successful sink", zap.Int("payload_size_b", result.PayloadSize), zap.String("sink_id", sinkID), zap.String("url", cfgRepo.Exporter.RemoteHost), zap.String("user", cfgRepo.Authentication.Username)) + svc.logger.Debug("successful sink", zap.Int("payload_size_b", result.PayloadSize), + zap.String("sink_id", sinkID)) if cfgRepo.State != config.Active { cfgRepo.State = config.Active diff --git a/sinker/redis/consumer/streams.go b/sinker/redis/consumer/streams.go index 95be472f5..a79b4760a 100644 --- a/sinker/redis/consumer/streams.go +++ b/sinker/redis/consumer/streams.go @@ -150,6 +150,7 @@ func (es eventStore) handleSinksRemove(_ context.Context, e updateSinkEvent) err if ok := es.configRepo.Exists(e.owner, e.sinkID); ok { err := es.configRepo.Remove(e.owner, e.sinkID) if err != nil { + es.logger.Error("error during remove sinker cache entry", zap.Error(err)) return err } } @@ -171,11 +172,9 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err if err != nil { return err } - sinkConfig.Authentication.Type = cfg.Authentication.Type - sinkConfig.Authentication.Username = cfg.Authentication.Username - sinkConfig.Authentication.Password = cfg.Authentication.Password - sinkConfig.Exporter.RemoteHost = cfg.Exporter.RemoteHost - sinkConfig.OpenTelemetry = cfg.OpenTelemetry + if sinkConfig.Config == nil { + sinkConfig.Config = cfg.Config + } if sinkConfig.OwnerID == "" { sinkConfig.OwnerID = e.owner } diff --git a/sinker/redis/sinker_test.go b/sinker/redis/sinker_test.go index 0ee54eb6c..2088cc9e7 100644 --- a/sinker/redis/sinker_test.go +++ b/sinker/redis/sinker_test.go @@ -2,7 +2,7 @@ package redis_test import ( "fmt" - "reflect" + "github.com/orb-community/orb/pkg/types" "testing" "time" @@ -21,10 +21,21 @@ func TestSinkerConfigSave(t *testing.T) { var config config2.SinkConfig config.SinkID = "123" config.OwnerID = "test" - config.Authentication.Type = "basic_auth" - config.Authentication.Username = "user" - config.Authentication.Password = "password" - config.Exporter.RemoteHost = "localhost" + config.Config = types.Metadata{ + "authentication": types.Metadata{ + "password": "password", + "type": "basicauth", + "username": "user", + }, + "exporter": types.Metadata{ + "headers": map[string]string{ + "X-Tenant": "MY_TENANT_1", + }, + "remote_host": "localhost", + }, + "opentelemetry": "enabled", + } + config.State = 0 config.Msg = "" config.LastRemoteWrite = time.Time{} @@ -40,8 +51,7 @@ func TestSinkerConfigSave(t *testing.T) { config: config2.SinkConfig{ SinkID: "124", OwnerID: "test", - Exporter: config.Exporter, - Authentication: config.Authentication, + Config: config.Config, State: 0, Msg: "", LastRemoteWrite: time.Time{}, @@ -67,10 +77,20 @@ func TestGetSinkerConfig(t *testing.T) { var config config2.SinkConfig config.SinkID = "123" config.OwnerID = "test" - config.Authentication.Type = "basic_auth" - config.Authentication.Username = "user" - config.Authentication.Password = "password" - config.Exporter.RemoteHost = "localhost" + config.Config = types.Metadata{ + "authentication": types.Metadata{ + "password": "password", + "type": "basicauth", + "username": "user", + }, + "exporter": types.Metadata{ + "headers": map[string]string{ + "X-Tenant": "MY_TENANT_1", + }, + "remote_host": "localhost", + }, + "opentelemetry": "enabled", + } config.State = 0 config.Msg = "" config.LastRemoteWrite = time.Time{} @@ -98,7 +118,17 @@ func TestGetSinkerConfig(t *testing.T) { for desc, tc := range cases { t.Run(desc, func(t *testing.T) { sinkConfig, err := sinkerCache.Get(tc.config.OwnerID, tc.sinkID) - assert.True(t, reflect.DeepEqual(tc.config, sinkConfig), fmt.Sprintf("%s: expected %v got %v", desc, tc.config, sinkConfig)) + assert.Equal(t, tc.config.SinkID, sinkConfig.SinkID, fmt.Sprintf("%s: expected %s got %s", desc, tc.config.SinkID, sinkConfig.SinkID)) + assert.Equal(t, tc.config.State, sinkConfig.State, fmt.Sprintf("%s: expected %s got %s", desc, tc.config.State, sinkConfig.State)) + assert.Equal(t, tc.config.OwnerID, sinkConfig.OwnerID, fmt.Sprintf("%s: expected %s got %s", desc, tc.config.OwnerID, sinkConfig.OwnerID)) + assert.Equal(t, tc.config.Msg, sinkConfig.Msg, fmt.Sprintf("%s: expected %s got %s", desc, tc.config.Msg, sinkConfig.Msg)) + assert.Equal(t, tc.config.LastRemoteWrite, sinkConfig.LastRemoteWrite, fmt.Sprintf("%s: expected %s got %s", desc, tc.config.LastRemoteWrite, sinkConfig.LastRemoteWrite)) + if tc.config.Config != nil { + _, ok := sinkConfig.Config["authentication"] + assert.True(t, ok, fmt.Sprintf("%s: should contain authentication metadata", desc)) + _, ok = sinkConfig.Config["exporter"] + assert.True(t, ok, fmt.Sprintf("%s: should contain exporter metadata", desc)) + } assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s", desc, tc.err, err)) }) } @@ -109,12 +139,22 @@ func TestGetAllSinkerConfig(t *testing.T) { var config config2.SinkConfig config.SinkID = "123" config.OwnerID = "test" - config.Authentication.Type = "basic_auth" - config.Authentication.Username = "user" - config.Authentication.Password = "password" - config.Exporter.RemoteHost = "localhost" config.State = 0 config.Msg = "" + config.Config = types.Metadata{ + "authentication": types.Metadata{ + "password": "password", + "type": "basicauth", + "username": "user", + }, + "exporter": types.Metadata{ + "headers": map[string]string{ + "X-Tenant": "MY_TENANT_1", + }, + "remote_host": "localhost", + }, + "opentelemetry": "enabled", + } config.LastRemoteWrite = time.Time{} sinksConfig := map[string]struct { config config2.SinkConfig @@ -123,8 +163,7 @@ func TestGetAllSinkerConfig(t *testing.T) { config: config2.SinkConfig{ SinkID: "123", OwnerID: "test", - Exporter: config.Exporter, - Authentication: config.Authentication, + Config: config.Config, State: 0, Msg: "", LastRemoteWrite: time.Time{}, @@ -134,8 +173,7 @@ func TestGetAllSinkerConfig(t *testing.T) { config: config2.SinkConfig{ SinkID: "134", OwnerID: "test", - Exporter: config.Exporter, - Authentication: config.Authentication, + Config: config.Config, State: 0, Msg: "", LastRemoteWrite: time.Time{}, diff --git a/sinks/backend/otlphttpexporter/configuration.go b/sinks/backend/otlphttpexporter/configuration.go index 87143dd80..48eec15f3 100644 --- a/sinks/backend/otlphttpexporter/configuration.go +++ b/sinks/backend/otlphttpexporter/configuration.go @@ -31,6 +31,11 @@ import ( // insecure_skip_verify: true const EndpointFieldName = "endpoint" +const CustomHeadersConfigFeature = "headers" + +var invalidCustomHeaders = []string{ + "Content-Encoding", "Content-Type", "User-Agent", "Authorization", +} type OTLPHTTPBackend struct { Endpoint string `yaml:"endpoint"` @@ -89,6 +94,16 @@ func (b *OTLPHTTPBackend) ValidateConfiguration(config types.Metadata) error { if _, err := url.ParseRequestURI(endpointUrl.(string)); err != nil { return errors.Wrap(errors.ErrInvalidEndpoint, err) } + // check for custom http headers + customHeaders, customHeadersOk := config[CustomHeadersConfigFeature] + if customHeadersOk { + headersAsMap := customHeaders.(map[string]interface{}) + for _, header := range invalidCustomHeaders { + if _, ok := headersAsMap[header]; ok { + return errors.New("invalid custom headers") + } + } + } return nil } diff --git a/sinks/backend/prometheus/configuration.go b/sinks/backend/prometheus/configuration.go index f4aac0529..81ccaf499 100644 --- a/sinks/backend/prometheus/configuration.go +++ b/sinks/backend/prometheus/configuration.go @@ -61,7 +61,7 @@ func (p *Backend) ValidateConfiguration(config types.Metadata) error { if customHeadersOk { headersAsMap := customHeaders.(map[string]interface{}) for _, header := range invalidCustomHeaders { - if _, ok := headersAsMap[header]; !ok { + if _, ok := headersAsMap[header]; ok { return errors.New("invalid custom headers") } } diff --git a/sinks/sinks_service.go b/sinks/sinks_service.go index 66d595e11..3792230c4 100644 --- a/sinks/sinks_service.go +++ b/sinks/sinks_service.go @@ -91,7 +91,7 @@ func validateAuthType(s *Sink) (authentication_type.AuthenticationType, error) { } authTypeStr, ok := authMetadata["type"] if !ok { - return nil, errors.Wrap(errors.ErrAuthTypeNotFound, errors.New("authentication type not found")) + return nil, errors.Wrap(errors.ErrAuthTypeNotFound, errors.New("authentication type not found")) } if _, ok := authTypeStr.(string); !ok { @@ -295,11 +295,11 @@ func (svc sinkService) UpdateSink(ctx context.Context, token string, sink Sink) sink.Backend = currentSink.Backend be, err := validateBackend(&sink) if err != nil { - return Sink{}, errors.Wrap(ErrMalformedEntity, err) + return Sink{}, errors.Wrap(errors.New("incorrect backend and exporter configuration"), err) } at, err := validateAuthType(&sink) if err != nil { - return Sink{}, errors.Wrap(ErrMalformedEntity, err) + return Sink{}, errors.Wrap(errors.New("incorrect authentication configuration"), err) } cfg = Configuration{ Authentication: at, @@ -313,7 +313,8 @@ func (svc sinkService) UpdateSink(ctx context.Context, token string, sink Sink) if sink.Format == "yaml" { configDataByte, err := yaml.Marshal(sink.Config) if err != nil { - return Sink{}, errors.Wrap(ErrMalformedEntity, err) + svc.logger.Error("failed to marshal config data", zap.Error(err)) + return Sink{}, errors.Wrap(errors.New("configuration is invalid for yaml format"), err) } sink.ConfigData = string(configDataByte) } @@ -341,11 +342,11 @@ func (svc sinkService) UpdateSink(ctx context.Context, token string, sink Sink) } err = svc.sinkRepo.Update(ctx, sink) if err != nil { - return Sink{}, errors.Wrap(ErrUpdateEntity, err) + return Sink{}, err } sinkEdited, err := svc.sinkRepo.RetrieveById(ctx, sink.ID) if err != nil { - return Sink{}, errors.Wrap(ErrUpdateEntity, err) + return Sink{}, err } sinkEdited, err = svc.decryptMetadata(cfg, sinkEdited) if err != nil { From c0390646a042d77bc424a7fd28a55ec42c0469d2 Mon Sep 17 00:00:00 2001 From: brnvalenca <79707831+brnvalenca@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:24:53 -0300 Subject: [PATCH 094/115] [ENG-16] Agent is exiting with error "BUG reconnection function is nil" --- agent/backend/diode/scrape.go | 2 +- agent/backend/pktvisor/scrape.go | 10 +++++----- agent/otel/bridgeservice.go | 9 ++++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/agent/backend/diode/scrape.go b/agent/backend/diode/scrape.go index b1fdfba9d..c4a2d86e2 100644 --- a/agent/backend/diode/scrape.go +++ b/agent/backend/diode/scrape.go @@ -26,7 +26,7 @@ const ( func (d *diodeBackend) createOtlpMqttExporter(ctx context.Context, cancelFunc context.CancelFunc) (exporter.Logs, error) { - bridgeService := otel.NewBridgeService(ctx, &d.policyRepo, d.agentTags) + bridgeService := otel.NewBridgeService(ctx, cancelFunc, &d.policyRepo, d.agentTags) if d.mqttClient != nil { cfg := otlpmqttexporter.CreateConfigClient(d.mqttClient, d.logTopic, d.version, bridgeService) set := otlpmqttexporter.CreateDefaultSettings(d.logger) diff --git a/agent/backend/pktvisor/scrape.go b/agent/backend/pktvisor/scrape.go index 120e42473..2c0423efd 100644 --- a/agent/backend/pktvisor/scrape.go +++ b/agent/backend/pktvisor/scrape.go @@ -37,26 +37,26 @@ func (p *pktvisorBackend) scrapeMetrics(period uint) (map[string]interface{}, er func (p *pktvisorBackend) createOtlpMqttExporter(ctx context.Context, cancelFunc context.CancelFunc) (exporter.Metrics, error) { - bridgeService := otel.NewBridgeService(ctx, &p.policyRepo, p.agentTags) + bridgeService := otel.NewBridgeService(ctx, cancelFunc, &p.policyRepo, p.agentTags) if p.mqttClient != nil { cfg := otlpmqttexporter.CreateConfigClient(p.mqttClient, p.otlpMetricsTopic, p.pktvisorVersion, bridgeService) set := otlpmqttexporter.CreateDefaultSettings(p.logger) // Create the OTLP metrics exporter that'll receive and verify the metrics produced. - exporter, err := otlpmqttexporter.CreateMetricsExporter(ctx, set, cfg) + metricsExporter, err := otlpmqttexporter.CreateMetricsExporter(ctx, set, cfg) if err != nil { return nil, err } - return exporter, nil + return metricsExporter, nil } else { cfg := otlpmqttexporter.CreateConfig(p.mqttConfig.Address, p.mqttConfig.Id, p.mqttConfig.Key, p.mqttConfig.ChannelID, p.pktvisorVersion, p.otlpMetricsTopic, bridgeService) set := otlpmqttexporter.CreateDefaultSettings(p.logger) // Create the OTLP metrics exporter that'll receive and verify the metrics produced. - exporter, err := otlpmqttexporter.CreateMetricsExporter(ctx, set, cfg) + metricsExporter, err := otlpmqttexporter.CreateMetricsExporter(ctx, set, cfg) if err != nil { return nil, err } - return exporter, nil + return metricsExporter, nil } } diff --git a/agent/otel/bridgeservice.go b/agent/otel/bridgeservice.go index 9e1ea7d2a..b933a344f 100644 --- a/agent/otel/bridgeservice.go +++ b/agent/otel/bridgeservice.go @@ -2,8 +2,9 @@ package otel import ( "context" - "github.com/orb-community/orb/agent/policies" "strings" + + "github.com/orb-community/orb/agent/policies" ) type AgentBridgeService interface { @@ -21,13 +22,15 @@ var _ AgentBridgeService = (*BridgeService)(nil) type BridgeService struct { bridgeContext context.Context + cancelFunc context.CancelFunc policyRepo policies.PolicyRepo AgentTags map[string]string } -func NewBridgeService(ctx context.Context, policyRepo *policies.PolicyRepo, agentTags map[string]string) *BridgeService { +func NewBridgeService(ctx context.Context, cancelFunc context.CancelFunc, policyRepo *policies.PolicyRepo, agentTags map[string]string) *BridgeService { return &BridgeService{ bridgeContext: ctx, + cancelFunc: cancelFunc, policyRepo: *policyRepo, AgentTags: agentTags, } @@ -47,5 +50,5 @@ func (b *BridgeService) RetrieveAgentInfoByPolicyName(policyName string) (*Agent func (b *BridgeService) NotifyAgentDisconnection(ctx context.Context, err error) { ctx.Done() - b.bridgeContext.Done() + b.cancelFunc() } From ac9e9345014fc7d2c5ba773b90c32b7384a158bc Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 19 Jul 2023 08:38:37 -0300 Subject: [PATCH 095/115] fix(orb-ui) All list pages, Add resizeble columns (#2507) --- .../list/agent.policy.list.component.html | 2 +- .../list/agent.policy.list.component.ts | 28 +++++++++---------- .../agents/list/agent.list.component.html | 2 +- .../fleet/agents/list/agent.list.component.ts | 24 ++++++++++------ .../list/agent.group.list.component.html | 2 +- .../groups/list/agent.group.list.component.ts | 23 ++++++++------- .../pages/sinks/list/sink.list.component.html | 2 +- .../pages/sinks/list/sink.list.component.ts | 26 ++++++++--------- 8 files changed, 58 insertions(+), 51 deletions(-) diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index ffe641d42..126d698b6 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -39,7 +39,7 @@

All Policies

All Agents
`${key}:${value}`) .join(','), ), + resizeable: true, }, { prop: 'version', - flexGrow: 5, + width: 200, minWidth: 150, canAutoResize: true, name: 'Version', sortable: true, cellTemplate: this.agentVersionTemplateCell, + resizeable: true, }, { prop: 'ts_last_hb', - flexGrow: 4, + width: 150, minWidth: 150, canAutoResize: true, name: 'Last Activity', sortable: true, cellTemplate: this.agentLastActivityTemplateCell, + resizeable: true, }, { name: '', prop: 'actions', - flexGrow: 2.5, + width: 150, minWidth: 150, canAutoResize: true, sortable: false, cellTemplate: this.actionsTemplateCell, + resizeable: true, }, ]; } diff --git a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html index e7b937953..70681af7e 100644 --- a/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html +++ b/ui/src/app/pages/fleet/groups/list/agent.group.list.component.html @@ -39,7 +39,7 @@

{{ strings.list.header }}

a.total - b.total, cellTemplate: this.agentGroupsTemplateCell, }, { prop: 'tags', - name: 'Tags', - flexGrow: 10, + width: 450, canAutoResize: true, - resizeable: false, + resizeable: true, cellTemplate: this.agentGroupTagsTemplateCell, comparator: (a, b) => Object.entries(a) @@ -223,8 +222,8 @@ export class AgentGroupListComponent { name: '', prop: 'actions', - flexGrow: 2.5, - resizeable: false, + width: 150, + resizeable: true, minWidth: 150, sortable: false, cellTemplate: this.actionsTemplateCell, diff --git a/ui/src/app/pages/sinks/list/sink.list.component.html b/ui/src/app/pages/sinks/list/sink.list.component.html index c9e2ab0a7..259af4732 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.html +++ b/ui/src/app/pages/sinks/list/sink.list.component.html @@ -39,7 +39,7 @@

{{ strings.list.header }}

Object.entries(a) @@ -227,9 +227,9 @@ export class SinkListComponent implements AfterViewInit, AfterViewChecked, OnDes name: '', prop: 'actions', minWidth: 150, - resizeable: false, + resizeable: true, sortable: false, - flexGrow: 1.75, + width: 150, cellTemplate: this.actionsTemplateCell, }, ]; From 704f3497475ea92880cefdf72aed3b8210d18ea5 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 19 Jul 2023 08:38:48 -0300 Subject: [PATCH 096/115] fix(orb-ui)> sink list, add sink view button on the sink name cell (#2506) --- ui/src/app/pages/sinks/list/sink.list.component.html | 10 +++++++--- ui/src/app/pages/sinks/list/sink.list.component.scss | 12 +++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ui/src/app/pages/sinks/list/sink.list.component.html b/ui/src/app/pages/sinks/list/sink.list.component.html index 259af4732..dbd7be2bc 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.html +++ b/ui/src/app/pages/sinks/list/sink.list.component.html @@ -58,10 +58,14 @@

{{ strings.list.header }}

- - + + diff --git a/ui/src/app/pages/sinks/list/sink.list.component.scss b/ui/src/app/pages/sinks/list/sink.list.component.scss index e2cd816f6..65beddd04 100644 --- a/ui/src/app/pages/sinks/list/sink.list.component.scss +++ b/ui/src/app/pages/sinks/list/sink.list.component.scss @@ -218,4 +218,14 @@ mat-chip-list { } input[type=checkbox] { margin-left: 10px; -} \ No newline at end of file +} +.view-sink-button { + background-color: transparent !important; + background-repeat: no-repeat !important; + border: none !important; + cursor: pointer !important; + outline: none !important; + overflow: hidden !important; + color: #ffffff; + text-align: left; +} From 82cd9a6c9944fd4953de730b8bb4a147a5951ee9 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Wed, 19 Jul 2023 08:39:01 -0300 Subject: [PATCH 097/115] fix(orb-ui): only expose last error field when the agent is recovery (#2505) --- .../orb/agent/agent-backends/agent-backends.component.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/app/shared/components/orb/agent/agent-backends/agent-backends.component.html b/ui/src/app/shared/components/orb/agent/agent-backends/agent-backends.component.html index ca3a4f459..d293d54a8 100644 --- a/ui/src/app/shared/components/orb/agent/agent-backends/agent-backends.component.html +++ b/ui/src/app/shared/components/orb/agent/agent-backends/agent-backends.component.html @@ -10,6 +10,8 @@

{{agent.last_hb_data.backend_state[backend.key].last_restart_ts | date:'full'}}

{{ agent.last_hb_data.backend_state[backend.key].error }}

+
+

{{ agent.last_hb_data.backend_state[backend.key].last_error }}

From 871fa3bfd58abbc713d512fa1f24bd95cc7fbc8f Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Wed, 19 Jul 2023 17:19:01 -0300 Subject: [PATCH 098/115] fix: smoke and sanity integration tests are failing. (#2501) * fix(sinks): fixes on custom headers validation. * fix(sinks): general fixes on working. * fix(sinks): fix conflict error code. * fix(sinks): fix header not reaching redis cache. * fix(sinks): simplify config on pass-through. * fix(sinks): add better error messages. * fix(sinker): fix handle config. * fix(sinks): fix delete event. * fix(sinker): fix not sending any feedback when delete key is not found. * fix(maestro): fix not removing the sink deployment after the sink is removed. * fix(agent): fix context cancellation. * fix(sinks): update sink will set state to unknown. * fix(agent): fix scrape for diode with context cancel func. * fix(sinker): fix update setting config to null. * fix(sinker): fix update setting config to null. * fix(sinker): fix timestamps. * fix(sinker): fix parsing. * fix: remove debug logs. * fix: remove debug logs. * fix(maestro): remove debug logs. * fix: add timeout and proper handling of when sink has no activity. * fix: remove redis entries before removing collector. * fix(maestro): add kill method for stale collectors without sink-id, happening when collector stays up even without a sink, wasting resources. * fix(maestro): remove unused method. * fix(maestro): fix monitor not getting the correct sink-id. * fix(maestro): remove unused method and use simpler form to get deployment name. * fix(sinker): fixed typos. * fix(maestro): fix deployment name. * fix(maestro): fix deployment name. * fix(maestro): fix delete deployment command. * fix(maestro): make monitor just look the last log line, instead of last 10. * fix(maestro): remove restriction on monitor to check collectors with error status. * fix(maestro): simplify check for activity to move sink to idle. * fix(sinker): simplify update activity. * fix(maestro): remove log that is not useful. --- agent/backend/pktvisor/scrape.go | 2 +- maestro/config/config_builder.go | 3 + maestro/kubecontrol/kubecontrol.go | 23 ++++++ maestro/monitor/monitor.go | 80 +++++++++----------- maestro/redis/consumer/hashset.go | 33 ++++---- maestro/service.go | 7 +- sinker/otel/bridgeservice/bridge.go | 4 +- sinker/redis/consumer/events.go | 10 +-- sinker/redis/consumer/streams.go | 112 ++++++++++++++-------------- sinker/redis/sinker.go | 3 +- sinks/redis/producer/events.go | 2 +- sinks/sinks_service.go | 6 +- 12 files changed, 149 insertions(+), 136 deletions(-) diff --git a/agent/backend/pktvisor/scrape.go b/agent/backend/pktvisor/scrape.go index 2c0423efd..60089085d 100644 --- a/agent/backend/pktvisor/scrape.go +++ b/agent/backend/pktvisor/scrape.go @@ -41,7 +41,7 @@ func (p *pktvisorBackend) createOtlpMqttExporter(ctx context.Context, cancelFunc if p.mqttClient != nil { cfg := otlpmqttexporter.CreateConfigClient(p.mqttClient, p.otlpMetricsTopic, p.pktvisorVersion, bridgeService) set := otlpmqttexporter.CreateDefaultSettings(p.logger) - // Create the OTLP metrics exporter that'll receive and verify the metrics produced. + // Create the OTLP metrics metricsExporter that'll receive and verify the metrics produced. metricsExporter, err := otlpmqttexporter.CreateMetricsExporter(ctx, set, cfg) if err != nil { return nil, err diff --git a/maestro/config/config_builder.go b/maestro/config/config_builder.go index 5f105b8db..7ec609f19 100644 --- a/maestro/config/config_builder.go +++ b/maestro/config/config_builder.go @@ -376,6 +376,9 @@ func ReturnConfigYamlFromSink(_ context.Context, kafkaUrlConfig string, sink Sin return "", errors.New("invalid authentication type") } exporterBuilder := FromStrategy(sink.Backend) + if exporterBuilder == nil { + return "", errors.New("invalid backend") + } extensions, extensionName := authBuilder.GetExtensionsFromMetadata(sink.Config) exporters, exporterName := exporterBuilder.GetExportersFromMetadata(sink.Config, extensionName) if exporterName == "" { diff --git a/maestro/kubecontrol/kubecontrol.go b/maestro/kubecontrol/kubecontrol.go index ffea58af8..edf83ab7c 100644 --- a/maestro/kubecontrol/kubecontrol.go +++ b/maestro/kubecontrol/kubecontrol.go @@ -49,6 +49,9 @@ type Service interface { // UpdateOtelCollector - update an existing collector by id UpdateOtelCollector(ctx context.Context, ownerID, sinkID, deploymentEntry string) error + + // KillOtelCollector - kill an existing collector by id, terminating by the ownerID, sinkID without the file + KillOtelCollector(ctx context.Context, ownerID, sinkID string) error } func (svc *deployService) collectorDeploy(ctx context.Context, operation, ownerID, sinkId, manifest string) error { @@ -157,3 +160,23 @@ func (svc *deployService) DeleteOtelCollector(ctx context.Context, ownerID, sink } return nil } + +func (svc *deployService) KillOtelCollector(ctx context.Context, deploymentName string, sinkId string) error { + stdOutListenFunction := func(out *bufio.Scanner, err *bufio.Scanner) { + for out.Scan() { + svc.logger.Info("Deploy Info: " + out.Text()) + } + for err.Scan() { + svc.logger.Info("Deploy Error: " + err.Text()) + } + } + + // execute action + cmd := exec.Command("kubectl", "delete", "deploy", deploymentName, "-n", namespace) + _, _, err := execCmd(ctx, cmd, svc.logger, stdOutListenFunction) + if err == nil { + svc.logger.Info(fmt.Sprintf("successfully killed the otel-collector for sink-id: %s", sinkId)) + } + + return nil +} diff --git a/maestro/monitor/monitor.go b/maestro/monitor/monitor.go index 5809c7d3b..c9fa10ccc 100644 --- a/maestro/monitor/monitor.go +++ b/maestro/monitor/monitor.go @@ -71,7 +71,7 @@ func (svc *monitorService) Start(ctx context.Context, cancelFunc context.CancelF } func (svc *monitorService) getPodLogs(ctx context.Context, pod k8scorev1.Pod) ([]string, error) { - maxTailLines := int64(10) + maxTailLines := int64(1) sinceSeconds := int64(300) podLogOpts := k8scorev1.PodLogOptions{TailLines: &maxTailLines, SinceSeconds: &sinceSeconds} config, err := rest.InClusterConfig() @@ -105,7 +105,6 @@ func (svc *monitorService) getPodLogs(ctx context.Context, pod k8scorev1.Pod) ([ } str := buf.String() splitLogs := strings.Split(str, "\n") - svc.logger.Info("logs length", zap.Int("amount line logs", len(splitLogs))) return splitLogs, nil } @@ -141,6 +140,7 @@ func (svc *monitorService) getRunningPods(ctx context.Context) ([]k8scorev1.Pod, } func (svc *monitorService) monitorSinks(ctx context.Context) { + runningCollectors, err := svc.getRunningPods(ctx) if err != nil { svc.logger.Error("error getting running pods on namespace", zap.Error(err)) @@ -160,17 +160,21 @@ func (svc *monitorService) monitorSinks(ctx context.Context) { var sink *sinkspb.SinkRes for _, sinkRes := range sinksRes.Sinks { if strings.Contains(collector.Name, sinkRes.Id) { - svc.logger.Warn("collector found for sink", zap.String("collector name", collector.Name), zap.String("sink", sinkRes.Id)) sink = sinkRes break } } if sink == nil { svc.logger.Warn("collector not found for sink, depleting collector", zap.String("collector name", collector.Name)) - sinkId := collector.Name[5:51] + sinkId := collector.Name[5:41] deploymentEntry, err := svc.eventStore.GetDeploymentEntryFromSinkId(ctx, sinkId) if err != nil { svc.logger.Error("did not find collector entry for sink", zap.String("sink-id", sinkId)) + deploymentName := "otel-" + sinkId + err = svc.kubecontrol.KillOtelCollector(ctx, deploymentName, sinkId) + if err != nil { + svc.logger.Error("error removing otel collector, manual intervention required", zap.Error(err)) + } continue } err = svc.kubecontrol.DeleteOtelCollector(ctx, "", sinkId, deploymentEntry) @@ -186,52 +190,38 @@ func (svc *monitorService) monitorSinks(ctx context.Context) { } data.SinkID = sink.Id data.OwnerID = sink.OwnerID - // only analyze logs if current status is "active" or "warning" var logsErr error var status string - if sink.GetState() == "active" || sink.GetState() == "warning" { - logs, err := svc.getPodLogs(ctx, collector) - if err != nil { - svc.logger.Error("error on getting logs, skipping", zap.Error(err)) - continue - } - status, logsErr = svc.analyzeLogs(logs) - if status == "fail" { - svc.logger.Error("error during analyze logs", zap.Error(logsErr)) - continue - } + logs, err := svc.getPodLogs(ctx, collector) + if err != nil { + svc.logger.Error("error on getting logs, skipping", zap.Error(err)) + continue + } + status, logsErr = svc.analyzeLogs(logs) + if status == "fail" { + svc.logger.Error("error during analyze logs", zap.Error(logsErr)) + continue } - var lastActivity int64 - var activityErr error - // if log analysis return active or warning we should check if have activity on collector - if status == "active" || status == "warning" { - lastActivity, activityErr = svc.eventStore.GetActivity(sink.Id) - // if logs reported 'active' status - // here we should check if LastActivity is up-to-date, otherwise we need to set sink as idle - var idleLimit int64 = 0 - if activityErr != nil || lastActivity == 0 { - svc.logger.Error("error on getting last collector activity", zap.Error(activityErr)) + lastActivity, activityErr := svc.eventStore.GetActivity(sink.Id) + // if logs reported 'active' status + // here we should check if LastActivity is up-to-date, otherwise we need to set sink as idle + idleLimit := time.Now().Unix() - idleTimeSeconds // within 10 minutes + if idleLimit >= lastActivity { + //changing state on sinks + svc.eventStore.PublishSinkStateChange(sink, "idle", logsErr, err) + //changing state on redis sinker + data.State.SetFromString("idle") + svc.eventStore.UpdateSinkStateCache(ctx, data) + deploymentEntry, errDeploy := svc.eventStore.GetDeploymentEntryFromSinkId(ctx, sink.Id) + if errDeploy != nil { + svc.logger.Error("Remove collector: error on getting collector deployment from redis", zap.Error(activityErr)) continue - } else { - idleLimit = time.Now().Unix() - idleTimeSeconds // within 10 minutes } - if idleLimit >= lastActivity { - //changing state on sinks - svc.eventStore.PublishSinkStateChange(sink, "idle", logsErr, err) - //changing state on redis sinker - data.State.SetFromString("idle") - svc.eventStore.UpdateSinkStateCache(ctx, data) - deploymentEntry, errDeploy := svc.eventStore.GetDeploymentEntryFromSinkId(ctx, sink.Id) - if errDeploy != nil { - svc.logger.Error("Remove collector: error on getting collector deployment from redis", zap.Error(activityErr)) - continue - } - err = svc.kubecontrol.DeleteOtelCollector(ctx, sink.OwnerID, sink.Id, deploymentEntry) - if err != nil { - svc.logger.Error("error removing otel collector", zap.Error(err)) - } - continue + err = svc.kubecontrol.DeleteOtelCollector(ctx, sink.OwnerID, sink.Id, deploymentEntry) + if err != nil { + svc.logger.Error("error removing otel collector", zap.Error(err)) } + continue } //set the new sink status if changed during checks if sink.GetState() != status && status != "" { @@ -283,7 +273,7 @@ func (svc *monitorService) analyzeLogs(logEntry []string) (status string, err er if strings.Contains(logLine, "400 Bad Request") { errorMessage := "error: remote write returned HTTP status 400 Bad Request" return "warning", errors.New(errorMessage) - } + } // other generic errors if strings.Contains(logLine, "error") { errStringLog := strings.TrimRight(logLine, "error") diff --git a/maestro/redis/consumer/hashset.go b/maestro/redis/consumer/hashset.go index 26b31a995..ba09caa0b 100644 --- a/maestro/redis/consumer/hashset.go +++ b/maestro/redis/consumer/hashset.go @@ -35,6 +35,14 @@ func (es eventStore) GetDeploymentEntryFromSinkId(ctx context.Context, sinkId st // handleSinksDeleteCollector will delete Deployment Entry and force delete otel collector func (es eventStore) handleSinksDeleteCollector(ctx context.Context, event redis.SinksUpdateEvent) error { es.logger.Info("Received maestro DELETE event from sinks ID", zap.String("sinkID", event.SinkID), zap.String("owner", event.Owner)) + err := es.sinkerKeyRedisClient.HDel(ctx, deploymentKey, event.SinkID).Err() + if err != nil { + return err + } + err = es.RemoveSinkActivity(ctx, event.SinkID) + if err != nil { + return err + } deploymentEntry, err := es.GetDeploymentEntryFromSinkId(ctx, event.SinkID) if err != nil { es.logger.Error("did not find collector entry for sink", zap.String("sink-id", event.SinkID)) @@ -97,48 +105,37 @@ func (es eventStore) handleSinksUpdateCollector(ctx context.Context, event redis if err != nil { es.logger.Error("could not fetch info for sink", zap.String("sink-id", event.SinkID), zap.Error(err)) } - var cfg types.Metadata - if err := json.Unmarshal(sinkData.Config, &cfg); err != nil { + var metadata types.Metadata + if err := json.Unmarshal(sinkData.Config, &metadata); err != nil { return err } data := config.SinkData{ SinkID: sinkData.Id, OwnerID: sinkData.OwnerID, Backend: sinkData.Backend, - Config: cfg, + Config: metadata, } _ = data.State.SetFromString(sinkData.State) deploy, err := config.GetDeploymentJson(es.kafkaUrl, data) + if err != nil { es.logger.Error("error trying to get deployment json for sink ID", zap.String("sinkId", event.SinkID), zap.Error(err)) return err } - es.sinkerKeyRedisClient.HSet(ctx, deploymentKey, event.SinkID, deploy) - err = es.kubecontrol.UpdateOtelCollector(ctx, event.Owner, event.SinkID, deploy) + err = es.sinkerKeyRedisClient.HSet(ctx, deploymentKey, event.SinkID, deploy).Err() if err != nil { + es.logger.Error("error trying to update deployment json for sink ID", zap.String("sinkId", event.SinkID), zap.Error(err)) return err } - // changing state on updated sink to unknown - sinkData.OwnerID = event.Owner - es.PublishSinkStateChange(sinkData, "unknown", err, err) - data.SinkID = sinkData.Id - data.OwnerID = sinkData.OwnerID - err = data.State.SetFromString("unknown") - if err != nil { - es.logger.Error("error setting state as unknown", zap.Error(err)) - return err - } - err = es.UpdateSinkStateCache(ctx, data) + err = es.kubecontrol.UpdateOtelCollector(ctx, event.Owner, event.SinkID, deploy) if err != nil { - es.logger.Error("error update sink cache state as unknown", zap.Error(err)) return err } return nil } func (es eventStore) UpdateSinkCache(ctx context.Context, data config.SinkData) (err error) { - data.State = config.Unknown keyPrefix := "sinker_key" skey := fmt.Sprintf("%s-%s:%s", keyPrefix, data.OwnerID, data.SinkID) bytes, err := json.Marshal(data) diff --git a/maestro/service.go b/maestro/service.go index bfa09ea08..6a0b94a64 100644 --- a/maestro/service.go +++ b/maestro/service.go @@ -12,6 +12,7 @@ import ( "context" "encoding/json" "github.com/orb-community/orb/maestro/monitor" + "github.com/orb-community/orb/pkg/types" "strings" "github.com/go-redis/redis/v8" @@ -81,15 +82,17 @@ func (svc *maestroService) Start(ctx context.Context, cancelFunction context.Can for _, sinkRes := range sinksRes.Sinks { sinkContext := context.WithValue(loadCtx, "sink-id", sinkRes.Id) - var data maestroconfig.SinkData - if err := json.Unmarshal(sinkRes.Config, &data); err != nil { + var metadata types.Metadata + if err := json.Unmarshal(sinkRes.Config, &metadata); err != nil { svc.logger.Warn("failed to unmarshal sink, skipping", zap.String("sink-id", sinkRes.Id)) continue } if val, _ := svc.eventStore.GetDeploymentEntryFromSinkId(ctx, sinkRes.Id); val != "" { svc.logger.Info("Skipping deploymentEntry because it is already created") } else { + var data maestroconfig.SinkData data.SinkID = sinkRes.Id + data.Config = metadata err := svc.eventStore.CreateDeploymentEntry(sinkContext, data) if err != nil { svc.logger.Warn("failed to create deploymentEntry for sink, skipping", zap.String("sink-id", sinkRes.Id)) diff --git a/sinker/otel/bridgeservice/bridge.go b/sinker/otel/bridgeservice/bridge.go index 4bb14c6f7..45753d7a3 100644 --- a/sinker/otel/bridgeservice/bridge.go +++ b/sinker/otel/bridgeservice/bridge.go @@ -97,15 +97,13 @@ func (bs *SinkerOtelBridgeService) NotifyActiveSink(ctx context.Context, mfOwner } bs.logger.Info("registering sink activity", zap.String("sinkID", sinkId), zap.String("newState", newState), zap.Any("currentState", cfgRepo.State)) } - } else if cfgRepo.State == config.Active || cfgRepo.State == config.Warning { + } else { err = bs.sinkerCache.AddActivity(mfOwnerId, sinkId) if err != nil { bs.logger.Error("error during update last remote write", zap.String("sinkId", sinkId), zap.Error(err)) return err } bs.logger.Info("registering sink activity", zap.String("sinkID", sinkId), zap.String("newState", newState), zap.Any("currentState", cfgRepo.State)) - } else if cfgRepo.State == config.Error { - cfgRepo.Msg = message } return nil diff --git a/sinker/redis/consumer/events.go b/sinker/redis/consumer/events.go index ea09af950..9d1639e90 100644 --- a/sinker/redis/consumer/events.go +++ b/sinker/redis/consumer/events.go @@ -14,9 +14,9 @@ import ( "github.com/orb-community/orb/pkg/types" ) -type updateSinkEvent struct { - sinkID string - owner string - config types.Metadata - timestamp time.Time +type UpdateSinkEvent struct { + SinkID string + Owner string + Config types.Metadata + Timestamp time.Time } diff --git a/sinker/redis/consumer/streams.go b/sinker/redis/consumer/streams.go index a79b4760a..2faae6d84 100644 --- a/sinker/redis/consumer/streams.go +++ b/sinker/redis/consumer/streams.go @@ -3,6 +3,8 @@ package consumer import ( "context" "encoding/json" + "fmt" + "github.com/orb-community/orb/pkg/errors" "time" "github.com/go-redis/redis/v8" @@ -69,11 +71,6 @@ func (es eventStore) Subscribe(context context.Context) error { break } err = es.handleSinksCreate(context, rte) - if err != nil { - es.logger.Error("Failed to handle event", zap.String("operation", event["operation"].(string)), zap.Error(err)) - break - } - es.client.XAck(context, stream, subGroup, msg.ID) case sinksUpdate: rte, derr := decodeSinksUpdate(event) if derr != nil { @@ -109,87 +106,83 @@ func NewEventStore(sinkerService sinker.Service, configRepo config.ConfigRepo, c } } -func decodeSinksCreate(event map[string]interface{}) (updateSinkEvent, error) { - val := updateSinkEvent{ - sinkID: read(event, "sink_id", ""), - owner: read(event, "owner", ""), - timestamp: time.Time{}, +func decodeSinksCreate(event map[string]interface{}) (UpdateSinkEvent, error) { + val := UpdateSinkEvent{ + SinkID: read(event, "sink_id", ""), + Owner: read(event, "owner", ""), + Config: readMetadata(event, "config"), + Timestamp: time.Now(), } var metadata types.Metadata if err := json.Unmarshal([]byte(read(event, "config", "")), &metadata); err != nil { - return updateSinkEvent{}, err + return UpdateSinkEvent{}, err } - val.config = metadata + val.Config = metadata return val, nil } -func decodeSinksUpdate(event map[string]interface{}) (updateSinkEvent, error) { - val := updateSinkEvent{ - sinkID: read(event, "sink_id", ""), - owner: read(event, "owner", ""), - timestamp: time.Time{}, +func decodeSinksUpdate(event map[string]interface{}) (UpdateSinkEvent, error) { + val := UpdateSinkEvent{ + SinkID: read(event, "sink_id", ""), + Owner: read(event, "owner", ""), + Timestamp: time.Now(), } var metadata types.Metadata if err := json.Unmarshal([]byte(read(event, "config", "")), &metadata); err != nil { - return updateSinkEvent{}, err + return UpdateSinkEvent{}, err } - val.config = metadata + val.Config = metadata return val, nil } -func decodeSinksRemove(event map[string]interface{}) (updateSinkEvent, error) { - val := updateSinkEvent{ - sinkID: read(event, "sink_id", ""), - owner: read(event, "owner", ""), - timestamp: time.Time{}, +func decodeSinksRemove(event map[string]interface{}) (UpdateSinkEvent, error) { + val := UpdateSinkEvent{ + SinkID: read(event, "sink_id", ""), + Owner: read(event, "owner", ""), + Timestamp: time.Now(), } return val, nil } -func (es eventStore) handleSinksRemove(_ context.Context, e updateSinkEvent) error { - if ok := es.configRepo.Exists(e.owner, e.sinkID); ok { - err := es.configRepo.Remove(e.owner, e.sinkID) +func (es eventStore) handleSinksRemove(_ context.Context, e UpdateSinkEvent) error { + if ok := es.configRepo.Exists(e.Owner, e.SinkID); ok { + err := es.configRepo.Remove(e.Owner, e.SinkID) if err != nil { es.logger.Error("error during remove sinker cache entry", zap.Error(err)) return err } + } else { + es.logger.Error("did not find any sinker cache entry for removal", + zap.String("key", fmt.Sprintf("sinker_key-%s-%s", e.Owner, e.SinkID))) + return errors.New("did not find any sinker cache entry for removal") } return nil } -func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) error { - data, err := json.Marshal(e.config) - if err != nil { - return err - } +func (es eventStore) handleSinksUpdate(_ context.Context, e UpdateSinkEvent) error { var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfg); err != nil { - return err - } - - if ok := es.configRepo.Exists(e.owner, e.sinkID); ok { - sinkConfig, err := es.configRepo.Get(e.owner, e.sinkID) + cfg.Config = types.FromMap(e.Config) + cfg.SinkID = e.SinkID + cfg.OwnerID = e.Owner + cfg.State = config.Unknown + if ok := es.configRepo.Exists(e.Owner, e.SinkID); ok { + sinkConfig, err := es.configRepo.Get(e.Owner, e.SinkID) if err != nil { return err } - if sinkConfig.Config == nil { - sinkConfig.Config = cfg.Config - } + sinkConfig.Config = cfg.Config if sinkConfig.OwnerID == "" { - sinkConfig.OwnerID = e.owner + sinkConfig.OwnerID = e.Owner } if sinkConfig.SinkID == "" { - sinkConfig.SinkID = e.sinkID + sinkConfig.SinkID = e.SinkID } err = es.configRepo.Edit(sinkConfig) if err != nil { return err } } else { - cfg.State = config.Unknown - cfg.SinkID = e.sinkID - cfg.OwnerID = e.owner - err = es.configRepo.Add(cfg) + err := es.configRepo.Add(cfg) if err != nil { return err } @@ -197,19 +190,13 @@ func (es eventStore) handleSinksUpdate(_ context.Context, e updateSinkEvent) err return nil } -func (es eventStore) handleSinksCreate(_ context.Context, e updateSinkEvent) error { - data, err := json.Marshal(e.config) - if err != nil { - return err - } +func (es eventStore) handleSinksCreate(_ context.Context, e UpdateSinkEvent) error { var cfg config.SinkConfig - if err := json.Unmarshal(data, &cfg); err != nil { - return err - } - cfg.SinkID = e.sinkID - cfg.OwnerID = e.owner + cfg.Config = types.FromMap(e.Config) + cfg.SinkID = e.SinkID + cfg.OwnerID = e.Owner cfg.State = config.Unknown - err = es.configRepo.Add(cfg) + err := es.configRepo.Add(cfg) if err != nil { return err } @@ -224,3 +211,12 @@ func read(event map[string]interface{}, key, def string) string { } return val } + +func readMetadata(event map[string]interface{}, key string) types.Metadata { + val, ok := event[key].(types.Metadata) + if !ok { + return types.Metadata{} + } + + return val +} diff --git a/sinker/redis/sinker.go b/sinker/redis/sinker.go index 97c3a4d39..d180f61e4 100644 --- a/sinker/redis/sinker.go +++ b/sinker/redis/sinker.go @@ -111,9 +111,10 @@ func (s *sinkerCache) AddActivity(ownerID string, sinkID string) error { if ownerID == "" || sinkID == "" { return errors.New("invalid parameters") } + defaultExpiration := time.Duration(10) * time.Minute skey := fmt.Sprintf("%s:%s", activityPrefix, sinkID) lastActivity := strconv.FormatInt(time.Now().Unix(), 10) - if err := s.client.Set(context.Background(), skey, lastActivity, 0).Err(); err != nil { + if err := s.client.Set(context.Background(), skey, lastActivity, defaultExpiration).Err(); err != nil { return err } s.logger.Info("added activity for owner and sink ids", zap.String("owner", ownerID), zap.String("sinkID", sinkID)) diff --git a/sinks/redis/producer/events.go b/sinks/redis/producer/events.go index a578ba648..acec59a7c 100644 --- a/sinks/redis/producer/events.go +++ b/sinks/redis/producer/events.go @@ -59,7 +59,7 @@ type deleteSinkEvent struct { func (dse deleteSinkEvent) Encode() (map[string]interface{}, error) { return map[string]interface{}{ "sink_id": dse.sinkID, - "owner_id": dse.ownerID, + "owner": dse.ownerID, "operation": SinkDelete, }, nil } diff --git a/sinks/sinks_service.go b/sinks/sinks_service.go index 3792230c4..e87941b66 100644 --- a/sinks/sinks_service.go +++ b/sinks/sinks_service.go @@ -218,7 +218,8 @@ func (svc sinkService) UpdateSinkInternal(ctx context.Context, sink Sink) (Sink, defaultMetadata := make(types.Metadata, 1) defaultMetadata["opentelemetry"] = "enabled" sink.Config.Merge(defaultMetadata) - currentSink.Error = "" + sink.State = Unknown + sink.Error = "" if sink.Format == "yaml" { configDataByte, err := yaml.Marshal(sink.Config) if err != nil { @@ -309,7 +310,8 @@ func (svc sinkService) UpdateSink(ctx context.Context, token string, sink Sink) defaultMetadata := make(types.Metadata, 1) defaultMetadata["opentelemetry"] = "enabled" sink.Config.Merge(defaultMetadata) - currentSink.Error = "" + sink.State = Unknown + sink.Error = "" if sink.Format == "yaml" { configDataByte, err := yaml.Marshal(sink.Config) if err != nil { From 4a10f7ab157d6e59c7733adf4002bf575c2fa45e Mon Sep 17 00:00:00 2001 From: Luiz Henrique Pegoraro Date: Thu, 20 Jul 2023 09:45:13 -0300 Subject: [PATCH 099/115] fix(policies): fixed not being able to handle event of sinks.remove (#2511) * fix(sinks): fixes on custom headers validation. * fix(sinks): general fixes on working. * fix(sinks): fix conflict error code. * fix(sinks): fix header not reaching redis cache. * fix(sinks): simplify config on pass-through. * fix(sinks): add better error messages. * fix(sinker): fix handle config. * fix(sinks): fix delete event. * fix(sinker): fix not sending any feedback when delete key is not found. * fix(maestro): fix not removing the sink deployment after the sink is removed. * fix(agent): fix context cancellation. * fix(sinks): update sink will set state to unknown. * fix(agent): fix scrape for diode with context cancel func. * fix(sinker): fix update setting config to null. * fix(sinker): fix update setting config to null. * fix(sinker): fix timestamps. * fix(sinker): fix parsing. * fix: remove debug logs. * fix: remove debug logs. * fix(maestro): remove debug logs. * fix: add timeout and proper handling of when sink has no activity. * fix: remove redis entries before removing collector. * fix(maestro): add kill method for stale collectors without sink-id, happening when collector stays up even without a sink, wasting resources. * fix(maestro): remove unused method. * fix(maestro): fix monitor not getting the correct sink-id. * fix(maestro): remove unused method and use simpler form to get deployment name. * fix(sinker): fixed typos. * fix(maestro): fix deployment name. * fix(maestro): fix deployment name. * fix(maestro): fix delete deployment command. * fix(maestro): make monitor just look the last log line, instead of last 10. * fix(maestro): remove restriction on monitor to check collectors with error status. * fix(maestro): simplify check for activity to move sink to idle. * fix(sinker): simplify update activity. * fix(maestro): remove log that is not useful. * fix(policies): fixed event input. --- policies/redis/consumer/streams.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/policies/redis/consumer/streams.go b/policies/redis/consumer/streams.go index 3b725b345..b9e54292f 100644 --- a/policies/redis/consumer/streams.go +++ b/policies/redis/consumer/streams.go @@ -131,7 +131,7 @@ func decodeAgentGroupRemove(event map[string]interface{}) removeAgentGroupEvent func decodeSinkRemove(event map[string]interface{}) removeSinkEvent { return removeSinkEvent{ sinkID: read(event, "sink_id", ""), - ownerID: read(event, "owner_id", ""), + ownerID: read(event, "owner", ""), } } From 15b287e63e4f61ab4f084b41dfa8815370d090a7 Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Thu, 20 Jul 2023 10:08:42 -0300 Subject: [PATCH 100/115] fix(orb-ui): On active datasets table, add resizeable columns (#2513) --- .../policy/policy-datasets/policy-datasets.component.html | 2 +- .../policy/policy-datasets/policy-datasets.component.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html index 67fe28c86..5cf951b72 100644 --- a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html +++ b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.html @@ -13,7 +13,7 @@
Date: Thu, 20 Jul 2023 12:00:12 -0300 Subject: [PATCH 101/115] fix(orb-ui): #900 On sink details modal, uptade fields to the new sink json (#2514) --- .../sinks/details/sink.details.component.html | 11 +++++++---- .../sinks/details/sink.details.component.ts | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/ui/src/app/pages/sinks/details/sink.details.component.html b/ui/src/app/pages/sinks/details/sink.details.component.html index ffc5fbc51..7a261a158 100644 --- a/ui/src/app/pages/sinks/details/sink.details.component.html +++ b/ui/src/app/pages/sinks/details/sink.details.component.html @@ -18,6 +18,7 @@

{{strings.propNames.description}}

{{ sink.description }}

+

No Description Added

@@ -26,14 +27,15 @@

{{ sink.backend }}

-

{{strings.propNames.config_remote_host}}

-

{{ sink.config.remote_host }}

+

{{ exporterField }}

+

{{ sink.config.exporter.remote_host }}

+

{{ sink.config.exporter.endpoint }}

{{strings.propNames.config_username}}

-

{{ sink.config.username }}

+

{{ sink.config.authentication.username }}

@@ -49,6 +51,7 @@
+

No tags Added

@@ -60,6 +63,6 @@ - + diff --git a/ui/src/app/pages/sinks/details/sink.details.component.ts b/ui/src/app/pages/sinks/details/sink.details.component.ts index 0efef925b..28c66ed29 100644 --- a/ui/src/app/pages/sinks/details/sink.details.component.ts +++ b/ui/src/app/pages/sinks/details/sink.details.component.ts @@ -1,15 +1,20 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; import { NbDialogRef } from '@nebular/theme'; import { STRINGS } from 'assets/text/strings'; import { ActivatedRoute, Router } from '@angular/router'; -import { Sink, SinkStates } from 'app/common/interfaces/orb/sink.interface'; +import { Sink, SinkBackends, SinkStates } from 'app/common/interfaces/orb/sink.interface'; @Component({ selector: 'ngx-sink-details-component', templateUrl: './sink.details.component.html', styleUrls: ['./sink.details.component.scss'], }) -export class SinkDetailsComponent { +export class SinkDetailsComponent implements OnInit { + + exporterField: string; + + sinkBackends = SinkBackends; + strings = STRINGS.sink; @Input() sink: Sink = {}; @@ -22,6 +27,7 @@ export class SinkDetailsComponent { protected router: Router, ) { !this.sink.tags ? this.sink.tags = {} : null; + this.exporterField = ""; } onOpenEdit(sink: any) { @@ -37,4 +43,8 @@ export class SinkDetailsComponent { this.router.navigateByUrl(`/pages/sinks/view/${sink.id}`); this.dialogRef.close(); } + ngOnInit() { + const exporter = this.sink.config.exporter; + this.exporterField = exporter.remote_host !== undefined ? "Remote Host URL" : "Endpoint URL"; + } } From c09315e7b91ae8986e63c4814641d3d6eb219c6a Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Thu, 20 Jul 2023 12:15:12 -0300 Subject: [PATCH 102/115] improvement(orb-ui): On active datasets, add hover on sink list (#2512) --- .../policy/policy-datasets/policy-datasets.component.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss index 906d45a62..8da3a1ec3 100644 --- a/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss +++ b/ui/src/app/shared/components/orb/policy/policy-datasets/policy-datasets.component.scss @@ -67,6 +67,11 @@ nb-card { overflow: hidden !important; color: #ffffff; } +.edit-dataset-button:hover { + + color: #969fb9; + font-size: 16px; +} .orb-service- { &true { From 2f293ef9359f1dae08eae345c4e7e086b228ad0c Mon Sep 17 00:00:00 2001 From: joaoguilherme2003 Date: Thu, 20 Jul 2023 12:15:30 -0300 Subject: [PATCH 103/115] improvement(orb-ui): On agent credentials, add tooltips on copy and save icons (#2510) --- ui/src/app/pages/fleet/agents/key/agent.key.component.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/src/app/pages/fleet/agents/key/agent.key.component.html b/ui/src/app/pages/fleet/agents/key/agent.key.component.html index 12a32ddcb..17cb55a95 100644 --- a/ui/src/app/pages/fleet/agents/key/agent.key.component.html +++ b/ui/src/app/pages/fleet/agents/key/agent.key.component.html @@ -35,11 +35,13 @@ for more advanced options.

-      
-      
       

From 7514bebd5d90439a223b2cdcdd2666eaed35b57a Mon Sep 17 00:00:00 2001
From: joaoguilherme2003 
Date: Thu, 20 Jul 2023 12:15:47 -0300
Subject: [PATCH 104/115] fix(orb-ui): On active policies, add max width for
 policy name (#2509)

---
 .../agent-policies-datasets.component.html                   | 5 +----
 .../agent-policies-datasets.component.scss                   | 3 +++
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
index 9763d46c5..7ffe544f9 100644
--- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
+++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
@@ -10,10 +10,7 @@
         
           
             Policy: 
-            
               Status: 
diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
index 461b01a77..11b952f30 100644
--- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
+++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
@@ -189,6 +189,9 @@ nb-list-item {
   outline: none !important;
   overflow: hidden !important;
   line-height: 1;
+  max-width: 360px !important;
+  text-align: left !important;
+  word-wrap: break-word !important;
 }
 
 .scroll {

From 063eef8a272b8bc04ccdd648dfad567dfc75c3b4 Mon Sep 17 00:00:00 2001
From: Luiz Pegoraro 
Date: Thu, 20 Jul 2023 15:44:22 -0300
Subject: [PATCH 105/115] chore(VERSION): upgrade version.

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 4e8f395fa..1b58cc101 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.26.0
+0.27.0

From 6f9271c2e8396eb91a7060171097693455e37381 Mon Sep 17 00:00:00 2001
From: Luiz Pegoraro 
Date: Thu, 20 Jul 2023 22:29:02 -0300
Subject: [PATCH 106/115] fix(maestro): not being able to create deployment
 from database.

---
 maestro/redis/consumer/hashset.go |  8 ++++----
 maestro/redis/consumer/streams.go | 28 +++++++++++++++++++++++++---
 maestro/service.go                |  1 +
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/maestro/redis/consumer/hashset.go b/maestro/redis/consumer/hashset.go
index ba09caa0b..3893c7fc4 100644
--- a/maestro/redis/consumer/hashset.go
+++ b/maestro/redis/consumer/hashset.go
@@ -35,17 +35,17 @@ func (es eventStore) GetDeploymentEntryFromSinkId(ctx context.Context, sinkId st
 // handleSinksDeleteCollector will delete Deployment Entry and force delete otel collector
 func (es eventStore) handleSinksDeleteCollector(ctx context.Context, event redis.SinksUpdateEvent) error {
 	es.logger.Info("Received maestro DELETE event from sinks ID", zap.String("sinkID", event.SinkID), zap.String("owner", event.Owner))
-	err := es.sinkerKeyRedisClient.HDel(ctx, deploymentKey, event.SinkID).Err()
+	err := es.RemoveSinkActivity(ctx, event.SinkID)
 	if err != nil {
 		return err
 	}
-	err = es.RemoveSinkActivity(ctx, event.SinkID)
+	deploymentEntry, err := es.GetDeploymentEntryFromSinkId(ctx, event.SinkID)
 	if err != nil {
+		es.logger.Error("did not find collector entry for sink", zap.String("sink-id", event.SinkID))
 		return err
 	}
-	deploymentEntry, err := es.GetDeploymentEntryFromSinkId(ctx, event.SinkID)
+	err = es.sinkerKeyRedisClient.HDel(ctx, deploymentKey, event.SinkID).Err()
 	if err != nil {
-		es.logger.Error("did not find collector entry for sink", zap.String("sink-id", event.SinkID))
 		return err
 	}
 	err = es.kubecontrol.DeleteOtelCollector(ctx, event.Owner, event.SinkID, deploymentEntry)
diff --git a/maestro/redis/consumer/streams.go b/maestro/redis/consumer/streams.go
index b1ecb6b20..c5eb0634f 100644
--- a/maestro/redis/consumer/streams.go
+++ b/maestro/redis/consumer/streams.go
@@ -2,6 +2,7 @@ package consumer
 
 import (
 	"context"
+	"encoding/json"
 	"time"
 
 	"github.com/orb-community/orb/maestro/config"
@@ -97,7 +98,7 @@ func (es eventStore) SubscribeSinkerEvents(ctx context.Context) error {
 					go func() {
 						err = es.handleSinkerCreateCollector(ctx, rte) //sinker request to create collector
 						if err != nil {
-							es.logger.Error("Failed to handle sinks event", zap.Any("operation", event["operation"]), zap.Error(err))
+							es.logger.Error("Failed to handle sinker event", zap.Any("operation", event["operation"]), zap.Error(err))
 						} else {
 							es.streamRedisClient.XAck(ctx, streamSinker, groupMaestro, msg.ID)
 						}
@@ -191,8 +192,29 @@ func (es eventStore) handleSinkerCreateCollector(ctx context.Context, event maes
 	es.logger.Info("Received maestro CREATE event from sinker, sink state", zap.String("state", event.State), zap.String("sinkID", event.SinkID), zap.String("ownerID", event.Owner))
 	deploymentEntry, err := es.GetDeploymentEntryFromSinkId(ctx, event.SinkID)
 	if err != nil {
-		es.logger.Error("could not find deployment entry from sink-id", zap.String("sinkID", event.SinkID), zap.Error(err))
-		return err
+		sink, err := es.sinksClient.RetrieveSink(ctx, &sinkspb.SinkByIDReq{
+			SinkID:  event.SinkID,
+			OwnerID: event.Owner,
+		})
+		if err != nil {
+			es.logger.Error("could not find deployment entry from sink-id", zap.String("sinkID", event.SinkID), zap.Error(err))
+			return err
+		}
+		var metadata types.Metadata
+		if err := json.Unmarshal(sink.Config, &metadata); err != nil {
+			return err
+		}
+		sinkData := config.SinkData{
+			SinkID:  sink.Id,
+			OwnerID: sink.OwnerID,
+			Backend: sink.Backend,
+			Config:  metadata,
+		}
+		err = es.CreateDeploymentEntry(ctx, sinkData)
+		if err != nil {
+			es.logger.Error("could not create deployment entry from sink", zap.String("sinkID", event.SinkID), zap.Error(err))
+			return err
+		}
 	}
 	err = es.kubecontrol.CreateOtelCollector(ctx, event.Owner, event.SinkID, deploymentEntry)
 	if err != nil {
diff --git a/maestro/service.go b/maestro/service.go
index 6a0b94a64..c30c61e20 100644
--- a/maestro/service.go
+++ b/maestro/service.go
@@ -93,6 +93,7 @@ func (svc *maestroService) Start(ctx context.Context, cancelFunction context.Can
 			var data maestroconfig.SinkData
 			data.SinkID = sinkRes.Id
 			data.Config = metadata
+			data.Backend = sinkRes.Backend
 			err := svc.eventStore.CreateDeploymentEntry(sinkContext, data)
 			if err != nil {
 				svc.logger.Warn("failed to create deploymentEntry for sink, skipping", zap.String("sink-id", sinkRes.Id))

From 55483e24b36ae689b90bc191b9b5dd7c481dc710 Mon Sep 17 00:00:00 2001
From: Luiz Pegoraro 
Date: Thu, 20 Jul 2023 22:30:35 -0300
Subject: [PATCH 107/115] revert: version upgrade

---
 VERSION | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/VERSION b/VERSION
index 1b58cc101..4e8f395fa 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.27.0
+0.26.0

From c732b5adc4a48c2ce1799f670f855584426986c8 Mon Sep 17 00:00:00 2001
From: joaoguilherme2003 
Date: Fri, 21 Jul 2023 13:32:47 -0300
Subject: [PATCH 108/115] fix(orb-ui): On view sink, fix cards width (#2518)

---
 ui/src/app/pages/sinks/view/sink.view.component.scss   |  2 +-
 .../orb/sink/sink-config/sink-config.component.scss    | 10 ++++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/ui/src/app/pages/sinks/view/sink.view.component.scss b/ui/src/app/pages/sinks/view/sink.view.component.scss
index c4c2f0351..e8f1b6e00 100644
--- a/ui/src/app/pages/sinks/view/sink.view.component.scss
+++ b/ui/src/app/pages/sinks/view/sink.view.component.scss
@@ -64,7 +64,7 @@ ngx-sink-config {
 }
 
 .row {
-  gap: 1rem;
+  gap: 10px;
 }
 
 header {
diff --git a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss
index e0bdbc3b9..0abd319d2 100644
--- a/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss
+++ b/ui/src/app/shared/components/orb/sink/sink-config/sink-config.component.scss
@@ -5,5 +5,11 @@ ngx-monaco-editor {
     color: #969fb9 !important;
 }
 nb-card {
-    width: 70em;
-}
\ No newline at end of file
+    width: 50vw;
+    min-width: 340px;
+}
+@media (max-width: 1500px) {
+    nb-card {
+      width: 35vw; 
+    }
+}

From 60bd412fdd5fa83e4cb8df27b74c5070bd939f56 Mon Sep 17 00:00:00 2001
From: joaoguilherme2003 
Date: Mon, 24 Jul 2023 13:56:08 -0300
Subject: [PATCH 109/115] fix(orb-ui) On active policies, width for low
 resolutions (#2520)

---
 .../agent-policies-datasets.component.html      | 15 +++++++++------
 .../agent-policies-datasets.component.scss      | 17 +++++++++++++----
 2 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
index 7ffe544f9..04a2a26cc 100644
--- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
+++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.html
@@ -10,15 +10,18 @@
         
           
             Policy: 
-            
-              Status: 
-            {{ policy?.state }}
-               Version: 
+             Status: 
+            {{ policy?.state }}
+              Version: 
             {{ policy?.version }}
-               Backend: 
-             {{ policy?.backend }}
+              Backend: 
+             
+              {{ policy?.backend }}
           
           
             
diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
index 11b952f30..e1c6e53eb 100644
--- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
+++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.scss
@@ -190,10 +190,19 @@ nb-list-item {
   overflow: hidden !important;
   line-height: 1;
   max-width: 360px !important;
-  text-align: left !important;
-  word-wrap: break-word !important;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
 }
-
+// nb-accordion-item-header {
+//   padding-right: 30px!important;
+// } 
 .scroll {
   max-height: 20em;
-}
\ No newline at end of file
+}
+.field{ 
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  min-width: 5ch;
+}

From 5efb53fa10e10ccf007cd365a4614041946a343f Mon Sep 17 00:00:00 2001
From: joaoguilherme2003 
Date: Mon, 24 Jul 2023 13:56:20 -0300
Subject: [PATCH 110/115] fix(orb-ui): #78 On agent view, remove error message
 when a deleted dataset is not found (#2519)

---
 .../services/dataset/dataset.policies.service.ts       | 10 ++++++----
 .../agent-policies-datasets.component.ts               |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/ui/src/app/common/services/dataset/dataset.policies.service.ts b/ui/src/app/common/services/dataset/dataset.policies.service.ts
index c1ec1a0ed..97697e5a4 100644
--- a/ui/src/app/common/services/dataset/dataset.policies.service.ts
+++ b/ui/src/app/common/services/dataset/dataset.policies.service.ts
@@ -40,10 +40,12 @@ export class DatasetPoliciesService {
       .get(`${environment.datasetPoliciesUrl}/${id}`)
       .pipe(
         catchError((err) => {
-          this.notificationsService.error(
-            'Failed to fetch Dataset of this Policy',
-            `Error: ${err.status} - ${err.statusText}`,
-          );
+          if (err.status !== 404 && err.error.error !== "non-existent entity") {
+            this.notificationsService.error(
+              'Failed to fetch Dataset of this Policy',
+              `Error: ${err.status} - ${err.statusText}`,
+            );
+          }
           err['id'] = id;
           return of(err);
         }),
diff --git a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts
index f665c0970..45f7f651c 100644
--- a/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts
+++ b/ui/src/app/shared/components/orb/agent/agent-policies-datasets/agent-policies-datasets.component.ts
@@ -52,7 +52,7 @@ export class AgentPoliciesDatasetsComponent implements OnInit, OnChanges {
   }
 
   ngOnInit(): void { 
-    this.getAmountRunningPolicies() 
+    this.getAmountRunningPolicies();
   }
   
   getAmountRunningPolicies() {
@@ -113,7 +113,7 @@ export class AgentPoliciesDatasetsComponent implements OnInit, OnChanges {
         closeOnBackdropClick: true,
       })
       .onClose.subscribe((resp) => {
-        if (resp === DATASET_RESPONSE.EDITED) {
+        if (resp === DATASET_RESPONSE.EDITED || resp === DATASET_RESPONSE.DELETED) {
           this.refreshAgent.emit('refresh-from-dataset');
         }
       });

From e04a4b1ba0ad7a4f5c6371714d355f6ba99e6908 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 24 Jul 2023 21:08:25 +0000
Subject: [PATCH 111/115] fix: bump jsonschema from 4.17.3 to 4.18.4

Bumps [jsonschema](https://github.com/python-jsonschema/jsonschema) from 4.17.3 to 4.18.4.
- [Release notes](https://github.com/python-jsonschema/jsonschema/releases)
- [Changelog](https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/python-jsonschema/jsonschema/compare/v4.17.3...v4.18.4)

---
updated-dependencies:
- dependency-name: jsonschema
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] 
---
 python-test/requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python-test/requirements.txt b/python-test/requirements.txt
index b2e1fc660..cd8a90e24 100644
--- a/python-test/requirements.txt
+++ b/python-test/requirements.txt
@@ -7,7 +7,7 @@ retry==0.9.2
 selenium==4.10.0
 behavex==2.0.1
 deepdiff==6.3.0
-jsonschema==4.17.3
+jsonschema==4.18.4
 mkdocs==1.4.3
 mkdocs-material==9.1.18
 prometheus-client==0.17.0

From eda840bc33bf0ae7856571b02150f8bd42b2a20c Mon Sep 17 00:00:00 2001
From: joaoguilherme2003 
Date: Tue, 25 Jul 2023 10:04:35 -0300
Subject: [PATCH 112/115] improvement(orb-ui): #34 New confirmation modal for
 policy duplication (#2526)

* improvement(orb-ui): #34 Implement confirmation modal for policy duplication

* feat(orb-ui): new modal confirmation modal
---
 .../agent.policy.duplicate.confirmation.html  | 25 +++++++++
 .../agent.policy.duplicate.confirmation.scss  | 51 ++++++++++++++++++
 .../agent.policy.duplicate.confirmation.ts    | 25 +++++++++
 .../list/agent.policy.list.component.html     |  2 +-
 .../list/agent.policy.list.component.ts       | 42 ++++++++++-----
 .../view/agent.policy.view.component.html     |  2 +-
 .../view/agent.policy.view.component.ts       | 52 +++++++++++++------
 ui/src/app/pages/pages.module.ts              |  3 ++
 8 files changed, 170 insertions(+), 32 deletions(-)
 create mode 100644 ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.html
 create mode 100644 ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.scss
 create mode 100644 ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.ts

diff --git a/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.html b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.html
new file mode 100644
index 000000000..aad567c19
--- /dev/null
+++ b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.html
@@ -0,0 +1,25 @@
+
+    
+      Duplicate Policy Confirmation
+      
+    
+    
+      

Are you sure you want to duplicate {{ policy }}?

+

*Please press the button to confirm. You will be redirected to the view page of the newly created policy.

+
+ + + +
\ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.scss b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.scss new file mode 100644 index 000000000..9b2c47f2a --- /dev/null +++ b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.scss @@ -0,0 +1,51 @@ +nb-card { + max-width: 38rem !important; + + nb-card-header { + background: #232940 !important; + color: #969fb9 !important; + } + + nb-card-body { + margin: 2rem 3rem !important; + padding: 0 !important; + + p { + color: #969fb9 !important; + } + + .ns1-red { + color: #df316f !important; + } + } + + nb-card-footer { + text-align: center !important; + padding: 1.5rem !important; + } + } + + // ORB + ::ng-deep { + .orb-close-dialog { + background-color: #23294000 !important; + border-radius: 4px !important; + display: contents !important; + float: right !important; + + > span { + float: right; + font-size: 1.5rem !important; + color: #3089fc !important; + font-weight: 900 !important; + } + } + .duplicate-button { + background-color: #3089fc !important; + color: #ffffff !important; + } + } + +span { + color: #3089fc; +} \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.ts b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.ts new file mode 100644 index 000000000..ce767ad28 --- /dev/null +++ b/ui/src/app/pages/datasets/policies.agent/duplicate/agent.policy.duplicate.confirmation.ts @@ -0,0 +1,25 @@ +import { Component, Input } from '@angular/core'; +import { NbDialogRef } from '@nebular/theme'; + +@Component({ + selector: 'ngx-policy-duplicate-component', + templateUrl: './agent.policy.duplicate.confirmation.html', + styleUrls: ['./agent.policy.duplicate.confirmation.scss'], +}) + +export class PolicyDuplicateComponent { + @Input() policy: string + constructor( + protected dialogRef: NbDialogRef, + ) { + } + + onDuplicate() { + this.dialogRef.close(true); + } + + onClose() { + this.dialogRef.close(false); + } + +} \ No newline at end of file diff --git a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html index 126d698b6..4d5060dbf 100644 --- a/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html +++ b/ui/src/app/pages/datasets/policies.agent/list/agent.policy.list.component.html @@ -118,7 +118,7 @@

All Policies