From 93317625bc473ba9546e379fb9c7efff8bbb041d Mon Sep 17 00:00:00 2001 From: Simo Kinnunen Date: Wed, 29 Jan 2025 21:22:56 +0900 Subject: [PATCH] feat: add TcpCheck construct [sc-22430] (#1012) * feat: added tcp check construct [sc-22430] * feat: hide misleading url property from the user, use hostname instead * chore: add unit tests for TcpCheck (copied from ApiCheck) * chore: add a TcpCheck to e2e tests * feat: support all current TCP check features * fix: remove bodyType from TcpCheck, it has no purpose currently * refactor: update to new API schema * fix: responseData assertion does not have properties * Revert "fix: responseData assertion does not have properties" The property could be a regex, like with API checks and TEXT_BODY, so expose it after all. This reverts commit 2c7b8b8251caba94a44820d137239b56d789560d. * chore: fix variable name in tests * fix(tests): use our site for snapshots instead of an external page that's down --------- Co-authored-by: ejanusevicius --- packages/cli/e2e/__tests__/deploy.spec.ts | 2 + .../fixtures/deploy-project/tcp.check.ts | 13 ++ .../snapshot-project/snapshot-test.spec.ts | 4 +- .../WWW-Snapshot-Test-1-chromium-linux.png | Bin 78590 -> 0 bytes ...Welcome-Snapshot-Test-1-chromium-linux.png | Bin 0 -> 20328 bytes .../constructs/__tests__/tcp-check.spec.ts | 103 ++++++++++++ packages/cli/src/constructs/api-check.ts | 159 ++---------------- packages/cli/src/constructs/index.ts | 1 + .../cli/src/constructs/internal/assertion.ts | 137 +++++++++++++++ packages/cli/src/constructs/tcp-check.ts | 105 ++++++++++++ 10 files changed, 377 insertions(+), 147 deletions(-) create mode 100644 packages/cli/e2e/__tests__/fixtures/deploy-project/tcp.check.ts delete mode 100644 packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts-snapshots/WWW-Snapshot-Test-1-chromium-linux.png create mode 100644 packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts-snapshots/Welcome-Snapshot-Test-1-chromium-linux.png create mode 100644 packages/cli/src/constructs/__tests__/tcp-check.spec.ts create mode 100644 packages/cli/src/constructs/internal/assertion.ts create mode 100644 packages/cli/src/constructs/tcp-check.ts diff --git a/packages/cli/e2e/__tests__/deploy.spec.ts b/packages/cli/e2e/__tests__/deploy.spec.ts index 3e10777a..1686e951 100644 --- a/packages/cli/e2e/__tests__/deploy.spec.ts +++ b/packages/cli/e2e/__tests__/deploy.spec.ts @@ -240,6 +240,7 @@ Update and Unchanged: ApiCheck: api-check-high-freq HeartbeatCheck: heartbeat-check-1 BrowserCheck: homepage-browser-check + TcpCheck: tcp-check CheckGroup: my-group-1 Dashboard: dashboard-1 MaintenanceWindow: maintenance-window-1 @@ -252,6 +253,7 @@ Update and Unchanged: HeartbeatCheck: heartbeat-check-1 BrowserCheck: homepage-browser-check BrowserCheck: snapshot-test.test.ts + TcpCheck: tcp-check CheckGroup: my-group-1 Dashboard: dashboard-1 MaintenanceWindow: maintenance-window-1 diff --git a/packages/cli/e2e/__tests__/fixtures/deploy-project/tcp.check.ts b/packages/cli/e2e/__tests__/fixtures/deploy-project/tcp.check.ts new file mode 100644 index 00000000..8f45ea56 --- /dev/null +++ b/packages/cli/e2e/__tests__/fixtures/deploy-project/tcp.check.ts @@ -0,0 +1,13 @@ +/* eslint-disable no-new */ +import { TcpCheck } from 'checkly/constructs' + +new TcpCheck('tcp-check', { + name: 'TCP Check', + activated: false, + request: { + hostname: 'api.checklyhq.com', + port: 443, + }, + degradedResponseTime: 5000, + maxResponseTime: 20000, +}) diff --git a/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts b/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts index 0f86aca2..495b70fa 100644 --- a/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts +++ b/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts @@ -3,8 +3,8 @@ import { expect, test } from '@playwright/test' test.use({ actionTimeout: 10000 }) -test('WWW Snapshot Test', async ({ page }) => { - await page.goto('https://info.cern.ch/hypertext/WWW/TheProject.html') +test('Welcome Snapshot Test', async ({ page }) => { + await page.goto('https://welcome.checklyhq.com') await expect(page).toHaveScreenshot({ maxDiffPixels: 10000 }) console.log(process.env.SECRET_ENV) }) diff --git a/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts-snapshots/WWW-Snapshot-Test-1-chromium-linux.png b/packages/cli/e2e/__tests__/fixtures/snapshot-project/snapshot-test.spec.ts-snapshots/WWW-Snapshot-Test-1-chromium-linux.png deleted file mode 100644 index 2b89ae6b820f83f97415896d41ba7460d2eeadd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78590 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 Dj2{T5 literal 0 HcmV?d00001 diff --git a/packages/cli/src/constructs/__tests__/tcp-check.spec.ts b/packages/cli/src/constructs/__tests__/tcp-check.spec.ts new file mode 100644 index 00000000..aafe25ed --- /dev/null +++ b/packages/cli/src/constructs/__tests__/tcp-check.spec.ts @@ -0,0 +1,103 @@ +import { TcpCheck, CheckGroup, TcpRequest } from '../index' +import { Project, Session } from '../project' + +const runtimes = { + '2022.10': { name: '2022.10', default: false, stage: 'CURRENT', description: 'Main updates are Playwright 1.28.0, Node.js 16.x and Typescript support. We are also dropping support for Puppeteer', dependencies: { '@playwright/test': '1.28.0', '@opentelemetry/api': '1.0.4', '@opentelemetry/sdk-trace-base': '1.0.1', '@faker-js/faker': '5.5.3', aws4: '1.11.0', axios: '0.27.2', btoa: '1.2.1', chai: '4.3.7', 'chai-string': '1.5.0', 'crypto-js': '4.1.1', expect: '29.3.1', 'form-data': '4.0.0', jsonwebtoken: '8.5.1', lodash: '4.17.21', mocha: '10.1.0', moment: '2.29.2', node: '16.x', otpauth: '9.0.2', playwright: '1.28.0', typescript: '4.8.4', uuid: '9.0.0' } }, +} + +const request: TcpRequest = { + hostname: 'acme.com', + port: 443, +} + +describe('TcpCheck', () => { + it('should not synthesize runtime if not specified even if default runtime is set', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + Session.availableRuntimes = runtimes + Session.defaultRuntimeId = '2022.02' + const check = new TcpCheck('test-check', { + name: 'Test Check', + request, + }) + const payload = check.synthesize() + expect(payload.runtimeId).toBeUndefined() + delete Session.defaultRuntimeId + }) + + it('should synthesize runtime if specified', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + Session.availableRuntimes = runtimes + Session.defaultRuntimeId = '2022.02' + const check = new TcpCheck('test-check', { + name: 'Test Check', + runtimeId: '2022.02', + request, + }) + const payload = check.synthesize() + expect(payload.runtimeId).toEqual('2022.02') + delete Session.defaultRuntimeId + }) + + it('should apply default check settings', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + Session.checkDefaults = { tags: ['default tags'] } + const check = new TcpCheck('test-check', { + name: 'Test Check', + request, + }) + delete Session.checkDefaults + expect(check).toMatchObject({ tags: ['default tags'] }) + }) + + it('should overwrite default check settings with check-specific config', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + Session.checkDefaults = { tags: ['default tags'] } + const check = new TcpCheck('test-check', { + name: 'Test Check', + tags: ['test check'], + request, + }) + delete Session.checkDefaults + expect(check).toMatchObject({ tags: ['test check'] }) + }) + + it('should support setting groups with `groupId`', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + const group = new CheckGroup('main-group', { name: 'Main Group', locations: [] }) + const check = new TcpCheck('main-check', { + name: 'Main Check', + request, + groupId: group.ref(), + }) + expect(check.synthesize()).toMatchObject({ groupId: { ref: 'main-group' } }) + }) + + it('should support setting groups with `group`', () => { + Session.project = new Project('project-id', { + name: 'Test Project', + repoUrl: 'https://github.com/checkly/checkly-cli', + }) + const group = new CheckGroup('main-group', { name: 'Main Group', locations: [] }) + const check = new TcpCheck('main-check', { + name: 'Main Check', + request, + group, + }) + expect(check.synthesize()).toMatchObject({ groupId: { ref: 'main-group' } }) + }) +}) diff --git a/packages/cli/src/constructs/api-check.ts b/packages/cli/src/constructs/api-check.ts index 24b10363..2c356c35 100644 --- a/packages/cli/src/constructs/api-check.ts +++ b/packages/cli/src/constructs/api-check.ts @@ -6,172 +6,41 @@ import { QueryParam } from './query-param' import { pathToPosix } from '../services/util' import { printDeprecationWarning } from '../reporters/util' import { Content, Entrypoint } from './construct' +import { Assertion as CoreAssertion, NumericAssertionBuilder, GeneralAssertionBuilder } from './internal/assertion' -// eslint-disable-next-line no-restricted-syntax -enum AssertionSource { - STATUS_CODE = 'STATUS_CODE', - JSON_BODY = 'JSON_BODY', - HEADERS = 'HEADERS', - TEXT_BODY = 'TEXT_BODY', - RESPONSE_TIME = 'RESPONSE_TIME', -} - -// eslint-disable-next-line no-restricted-syntax -enum AssertionComparison { - EQUALS = 'EQUALS', - NOT_EQUALS = 'NOT_EQUALS', - HAS_KEY = 'HAS_KEY', - NOT_HAS_KEY = 'NOT_HAS_KEY', - HAS_VALUE = 'HAS_VALUE', - NOT_HAS_VALUE = 'NOT_HAS_VALUE', - IS_EMPTY = 'IS_EMPTY', - NOT_EMPTY = 'NOT_EMPTY', - GREATER_THAN = 'GREATER_THAN', - LESS_THAN = 'LESS_THAN', - CONTAINS = 'CONTAINS', - NOT_CONTAINS = 'NOT_CONTAINS', - IS_NULL = 'IS_NULL', - NOT_NULL = 'NOT_NULL', -} +type AssertionSource = + | 'STATUS_CODE' + | 'JSON_BODY' + | 'HEADERS' + | 'TEXT_BODY' + | 'RESPONSE_TIME' -export interface Assertion { - source: string, - property: string, - comparison: string, - target: string, - regex: string|null, -} +export type Assertion = CoreAssertion export class AssertionBuilder { static statusCode () { - return new NumericAssertionBuilder(AssertionSource.STATUS_CODE) + return new NumericAssertionBuilder('STATUS_CODE') } static jsonBody (property?: string) { - return new GeneralAssertionBuilder(AssertionSource.JSON_BODY, property) + return new GeneralAssertionBuilder('JSON_BODY', property) } static headers (property?: string, regex?: string) { - return new GeneralAssertionBuilder(AssertionSource.HEADERS, property, regex) + return new GeneralAssertionBuilder('HEADERS', property, regex) } static textBody (property?: string) { - return new GeneralAssertionBuilder(AssertionSource.TEXT_BODY, property) + return new GeneralAssertionBuilder('TEXT_BODY', property) } /** @deprecated Use responseTime() instead */ static responseTme () { - return new NumericAssertionBuilder(AssertionSource.RESPONSE_TIME) + return new NumericAssertionBuilder('RESPONSE_TIME') } static responseTime () { - return new NumericAssertionBuilder(AssertionSource.RESPONSE_TIME) - } -} - -class NumericAssertionBuilder { - source: AssertionSource - constructor (source: AssertionSource) { - this.source = source - } - - equals (target: number): Assertion { - return this._toAssertion(AssertionComparison.EQUALS, target) - } - - notEquals (target: number): Assertion { - return this._toAssertion(AssertionComparison.NOT_EQUALS, target) - } - - lessThan (target: number): Assertion { - return this._toAssertion(AssertionComparison.LESS_THAN, target) - } - - greaterThan (target: number): Assertion { - return this._toAssertion(AssertionComparison.GREATER_THAN, target) - } - - /** @private */ - private _toAssertion (comparison: AssertionComparison, target: number): Assertion { - return { source: this.source, comparison, property: '', target: target.toString(), regex: null } - } -} - -class GeneralAssertionBuilder { - source: AssertionSource - property?: string - regex?: string - constructor (source: AssertionSource, property?: string, regex?: string) { - this.source = source - this.property = property - this.regex = regex - } - - equals (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.EQUALS, target) - } - - notEquals (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.NOT_EQUALS, target) - } - - hasKey (target: string): Assertion { - return this._toAssertion(AssertionComparison.HAS_KEY, target) - } - - notHasKey (target: string): Assertion { - return this._toAssertion(AssertionComparison.NOT_HAS_KEY, target) - } - - hasValue (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.HAS_VALUE, target) - } - - notHasValue (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.NOT_HAS_VALUE, target) - } - - isEmpty () { - return this._toAssertion(AssertionComparison.IS_EMPTY) - } - - notEmpty () { - return this._toAssertion(AssertionComparison.NOT_EMPTY) - } - - lessThan (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.LESS_THAN, target) - } - - greaterThan (target: string|number|boolean): Assertion { - return this._toAssertion(AssertionComparison.GREATER_THAN, target) - } - - contains (target: string): Assertion { - return this._toAssertion(AssertionComparison.CONTAINS, target) - } - - notContains (target: string): Assertion { - return this._toAssertion(AssertionComparison.NOT_CONTAINS, target) - } - - isNull () { - return this._toAssertion(AssertionComparison.IS_NULL) - } - - isNotNull () { - return this._toAssertion(AssertionComparison.NOT_NULL) - } - - /** @private */ - private _toAssertion (comparison: AssertionComparison, target?: string|number|boolean): Assertion { - return { - source: this.source, - comparison, - property: this.property ?? '', - target: target?.toString() ?? '', - regex: this.regex ?? null, - } + return new NumericAssertionBuilder('RESPONSE_TIME') } } diff --git a/packages/cli/src/constructs/index.ts b/packages/cli/src/constructs/index.ts index f1c1a3b5..dd91eb10 100644 --- a/packages/cli/src/constructs/index.ts +++ b/packages/cli/src/constructs/index.ts @@ -25,3 +25,4 @@ export * from './phone-call-alert-channel' export * from './retry-strategy' export * from './multi-step-check' export * from './alert-escalation-policy' +export * from './tcp-check' diff --git a/packages/cli/src/constructs/internal/assertion.ts b/packages/cli/src/constructs/internal/assertion.ts new file mode 100644 index 00000000..07f97d50 --- /dev/null +++ b/packages/cli/src/constructs/internal/assertion.ts @@ -0,0 +1,137 @@ +type Comparison = + | 'EQUALS' + | 'NOT_EQUALS' + | 'HAS_KEY' + | 'NOT_HAS_KEY' + | 'HAS_VALUE' + | 'NOT_HAS_VALUE' + | 'IS_EMPTY' + | 'NOT_EMPTY' + | 'GREATER_THAN' + | 'LESS_THAN' + | 'CONTAINS' + | 'NOT_CONTAINS' + | 'IS_NULL' + | 'NOT_NULL' + +export interface Assertion { + source: Source + property: string + comparison: string + target: string + regex: string|null +} + +export class NumericAssertionBuilder { + source: Source + + constructor (source: Source) { + this.source = source + } + + equals (target: number): Assertion { + return this._toAssertion('EQUALS', target) + } + + notEquals (target: number): Assertion { + return this._toAssertion('NOT_EQUALS', target) + } + + lessThan (target: number): Assertion { + return this._toAssertion('LESS_THAN', target) + } + + greaterThan (target: number): Assertion { + return this._toAssertion('GREATER_THAN', target) + } + + /** @private */ + private _toAssertion (comparison: Comparison, target: number): Assertion { + return { + source: this.source, + comparison, + property: '', + target: target.toString(), + regex: null, + } + } +} + +export class GeneralAssertionBuilder { + source: Source + property?: string + regex?: string + + constructor (source: Source, property?: string, regex?: string) { + this.source = source + this.property = property + this.regex = regex + } + + equals (target: string|number|boolean): Assertion { + return this._toAssertion('EQUALS', target) + } + + notEquals (target: string|number|boolean): Assertion { + return this._toAssertion('NOT_EQUALS', target) + } + + hasKey (target: string): Assertion { + return this._toAssertion('HAS_KEY', target) + } + + notHasKey (target: string): Assertion { + return this._toAssertion('NOT_HAS_KEY', target) + } + + hasValue (target: string|number|boolean): Assertion { + return this._toAssertion('HAS_VALUE', target) + } + + notHasValue (target: string|number|boolean): Assertion { + return this._toAssertion('NOT_HAS_VALUE', target) + } + + isEmpty () { + return this._toAssertion('IS_EMPTY') + } + + notEmpty () { + return this._toAssertion('NOT_EMPTY') + } + + lessThan (target: string|number|boolean): Assertion { + return this._toAssertion('LESS_THAN', target) + } + + greaterThan (target: string|number|boolean): Assertion { + return this._toAssertion('GREATER_THAN', target) + } + + contains (target: string): Assertion { + return this._toAssertion('CONTAINS', target) + } + + notContains (target: string): Assertion { + return this._toAssertion('NOT_CONTAINS', target) + } + + isNull () { + return this._toAssertion('IS_NULL') + } + + isNotNull () { + return this._toAssertion('NOT_NULL') + } + + /** @private */ + private _toAssertion (comparison: Comparison, target?: string|number|boolean): Assertion { + return { + source: this.source, + comparison, + property: this.property ?? '', + target: target?.toString() ?? '', + regex: this.regex ?? null, + } + } +} diff --git a/packages/cli/src/constructs/tcp-check.ts b/packages/cli/src/constructs/tcp-check.ts new file mode 100644 index 00000000..f8f47143 --- /dev/null +++ b/packages/cli/src/constructs/tcp-check.ts @@ -0,0 +1,105 @@ +import { Check, CheckProps } from './check' +import { IPFamily } from './api-check' +import { Session } from './project' +import { Assertion as CoreAssertion, NumericAssertionBuilder, GeneralAssertionBuilder } from './internal/assertion' + +type TcpAssertionSource = 'RESPONSE_DATA' | 'RESPONSE_TIME' + +export type TcpAssertion = CoreAssertion + +export class TcpAssertionBuilder { + static responseData (property?: string) { + return new GeneralAssertionBuilder('RESPONSE_DATA', property) + } + + static responseTime () { + return new NumericAssertionBuilder('RESPONSE_TIME') + } +} + +export interface TcpRequest { + /** + * The hostname the connection should be made to. + * + * Do not include a scheme or a port in the hostname. + */ + hostname: string + /** + * The port the connection should be made to. + */ + port: number + /** + * Check the main Checkly documentation on TCP assertions for specific values + * that you can use in the "property" field. + */ + assertions?: Array + /** + * The IP family to use for the connection. + * + * @default "IPv4" + */ + ipFamily?: IPFamily + /** + * The data to send to the target host. + */ + data?: string +} + +export interface TcpCheckProps extends CheckProps { + /** + * Determines the request that the check is going to run. + */ + request: TcpRequest + /** + * The response time in milliseconds where a check should be considered degraded. + */ + degradedResponseTime?: number + /** + * The response time in milliseconds where a check should be considered failing. + */ + maxResponseTime?: number +} + +/** + * Creates an TCP Check + * + * @remarks + * + * This class make use of the TCP Checks endpoints. + */ +export class TcpCheck extends Check { + request: TcpRequest + degradedResponseTime?: number + maxResponseTime?: number + + /** + * Constructs the TCP Check instance + * + * @param logicalId unique project-scoped resource name identification + * @param props check configuration properties + * + * {@link https://checklyhq.com/docs/cli/constructs/#tcpcheck Read more in the docs} + */ + + constructor (logicalId: string, props: TcpCheckProps) { + super(logicalId, props) + + this.request = props.request + this.degradedResponseTime = props.degradedResponseTime + this.maxResponseTime = props.maxResponseTime + + Session.registerConstruct(this) + this.addSubscriptions() + this.addPrivateLocationCheckAssignments() + } + + synthesize () { + return { + ...super.synthesize(), + checkType: 'TCP', + request: this.request, + degradedResponseTime: this.degradedResponseTime, + maxResponseTime: this.maxResponseTime, + } + } +}