diff --git a/package-lock.json b/package-lock.json index 20fd60c8..439fa4be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3786,8 +3786,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -3801,6 +3800,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", @@ -4347,7 +4356,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4684,7 +4692,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -5637,6 +5644,25 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -5659,6 +5685,19 @@ "node": ">=8.0.0" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/formidable": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", @@ -7287,7 +7326,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -7296,7 +7334,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -9162,20 +9199,6 @@ "node": ">=6.4.0 <13 || >=14" } }, - "node_modules/superagent/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/superagent/node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -10120,6 +10143,7 @@ "@opentelemetry/sdk-node": "0.43.0", "@opentelemetry/sdk-trace-base": "1.17.0", "@opentelemetry/sdk-trace-node": "1.17.0", + "axios": "1.6.7", "error-stack-parser": "2.1.4", "google-auth-library": "9.0.0", "ts-proto": "1.148.1", @@ -10527,7 +10551,7 @@ }, "packages/synthetics-sdk-broken-links": { "name": "@google-cloud/synthetics-sdk-broken-links", - "version": "0.1.2", + "version": "0.2.0", "license": "Apache-2.0", "dependencies": { "@google-cloud/synthetics-sdk-api": "^0.5.1", @@ -11488,6 +11512,7 @@ "@types/node": "^18.15.10", "@types/sinon": "^10.0.16", "@types/supertest": "^2.0.12", + "axios": "1.6.7", "chai": "^4.3.7", "error-stack-parser": "2.1.4", "express": "^4.18.2", @@ -14369,8 +14394,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "available-typed-arrays": { "version": "1.0.5", @@ -14378,6 +14402,16 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, + "axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "requires": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "b4a": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.4.tgz", @@ -14791,7 +14825,6 @@ "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" } @@ -15040,8 +15073,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "depd": { "version": "2.0.0", @@ -15760,6 +15792,11 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, + "follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -15779,6 +15816,16 @@ "signal-exit": "^3.0.2" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "formidable": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", @@ -16973,14 +17020,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -18351,17 +18396,6 @@ "semver": "^7.3.8" }, "dependencies": { - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", diff --git a/packages/synthetics-sdk-api/package.json b/packages/synthetics-sdk-api/package.json index ca1cb9f4..23d0ff66 100644 --- a/packages/synthetics-sdk-api/package.json +++ b/packages/synthetics-sdk-api/package.json @@ -43,7 +43,8 @@ "error-stack-parser": "2.1.4", "google-auth-library": "9.0.0", "ts-proto": "1.148.1", - "winston": "3.10.0" + "winston": "3.10.0", + "axios": "1.6.7" }, "author": "Google Inc.", "license": "Apache-2.0" diff --git a/packages/synthetics-sdk-api/proto/synthetic_response.proto b/packages/synthetics-sdk-api/proto/synthetic_response.proto index 0584bf41..4a8ed4b5 100644 --- a/packages/synthetics-sdk-api/proto/synthetic_response.proto +++ b/packages/synthetics-sdk-api/proto/synthetic_response.proto @@ -53,7 +53,6 @@ message TestResult { // A list of StackFrame messages that indicate a single trace of code. repeated StackFrame stack_frames = 3; - // The raw stack trace associated with the error. string stack_trace = 4; } @@ -88,7 +87,6 @@ message GenericResultV1 { // The full error message. Eg. "The url that you are fetching failed DNS // lookup". string error_message = 2; - // The name of the function where the error occurred. string function_name = 3; // The name of the file that reported the error. @@ -132,6 +130,14 @@ message ResponseStatusCode { } } +// Information on an error that occurred. +message BaseError { + // The name of the error. + string error_type = 1; + // The full error message. + string error_message = 2; +} + // Aggregate and individual results of a Broken Link Synthetic execution message BrokenLinksResultV1 { // the total number of links checked as part of the execution @@ -198,12 +204,31 @@ message BrokenLinksResultV1 { // the given specified link passed in "per_link_options" map. optional int64 link_timeout_millis = 2; } + // individual link options, default None. string must be formatted as a // fully qualified url map per_link_options = 10; - // Timeout set for the entire Synthetic Monitor, default 60000 milliseconds optional int64 total_synthetic_timeout_millis = 11; + + // Required options for broken link checker screenshot capability. + message ScreenshotOptions { + // Input bucket or folder provided by the user. + string storage_location = 1; + + enum CaptureCondition { + NONE = 0; + FAILING = 1; + ALL = 2; + } + + // Controls when to capture screenshots during broken link checks, default + // is FAILING. + CaptureCondition capture_condition = 2; + } + + // Screenshot options, default to 'FAILING' and synthetic wide bucket. + ScreenshotOptions screenshot_options = 12; } // Options set for broken link synthetic. @@ -217,7 +242,7 @@ message BrokenLinksResultV1 { ResponseStatusCode expected_status_code = 2; // Source_uri from which the target_uri is navigated from. string source_uri = 3; - // target_uri navigated to from the source_uri. + // Target_uri navigated to from the source_uri. string target_uri = 4; // Anchor text on the source URI. string anchor_text = 5; @@ -235,15 +260,34 @@ message BrokenLinksResultV1 { string link_start_time = 10; // The end time of the link navigation in iso format. string link_end_time = 11; - // These fields only apply to the origin link. optional bool is_origin = 12; + + // Result of Screenshot Upload to GCS. + message ScreenshotOutput { + // Name of screenshot_file. + string screenshot_file = 1; + + // Error that occurred throughout screenshot workflow. + BaseError screenshot_error = 2; + } + + // Output of screenshot upload attempt. + ScreenshotOutput screenshot_output = 13; } - // link result for origin_uri + // link result for origin_uri. SyntheticLinkResult origin_link_result = 10; - // link results for all scraped and followed links + // link results for all scraped and followed links. repeated SyntheticLinkResult followed_link_results = 11; + + // Path to the Cloud Storage folder where all artifacts (e.g. screenshots) + // will be stored for this execution. e.g. + // gs:// runtime_metadata = 4; - // The start time of the synthetic in iso format. string start_time = 5; // The end time of the synthetic in iso format. diff --git a/packages/synthetics-sdk-api/src/cloud_region_resolver.ts b/packages/synthetics-sdk-api/src/cloud_region_resolver.ts new file mode 100644 index 00000000..1bdd3dee --- /dev/null +++ b/packages/synthetics-sdk-api/src/cloud_region_resolver.ts @@ -0,0 +1,48 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import axios, { AxiosResponse } from 'axios'; + +/** + * + * @public + * + * Retrieves the region in which the current Google Cloud Function (v2) is + * executing by querying the metadata server. + */ +export async function getExecutionRegion(): Promise { + const metadataServerUrl = + 'http://metadata.google.internal/computeMetadata/v1/instance/region'; + const headers = { 'Metadata-Flavor': 'Google' }; + + try { + const response: AxiosResponse = await axios.get(metadataServerUrl, { + headers, + }); + + // Extract region from the response (e.g., 'us-east1') + const regions = response.data.split('/'); + const region = regions[regions.length - 1]; + + return region; + } catch (error) { + if (axios.isAxiosError(error)) { + console.error('Error fetching region from metadata server:', error); + } else { + console.error('Unexpected error:', error); + } + } + + return null; +} diff --git a/packages/synthetics-sdk-api/src/generated/proto/synthetic_response.ts b/packages/synthetics-sdk-api/src/generated/proto/synthetic_response.ts index 01e7c4c1..a7ee2f06 100644 --- a/packages/synthetics-sdk-api/src/generated/proto/synthetic_response.ts +++ b/packages/synthetics-sdk-api/src/generated/proto/synthetic_response.ts @@ -212,6 +212,14 @@ export function responseStatusCode_StatusClassToJSON(object: ResponseStatusCode_ } } +/** Information on an error that occurred. */ +export interface BaseError { + /** The name of the error. */ + error_type: string; + /** The full error message. */ + error_message: string; +} + /** Aggregate and individual results of a Broken Link Synthetic execution */ export interface BrokenLinksResultV1 { /** the total number of links checked as part of the execution */ @@ -250,12 +258,20 @@ export interface BrokenLinksResultV1 { options: | BrokenLinksResultV1_BrokenLinkCheckerOptions | undefined; - /** link result for origin_uri */ + /** link result for origin_uri. */ origin_link_result: | BrokenLinksResultV1_SyntheticLinkResult | undefined; - /** link results for all scraped and followed links */ + /** link results for all scraped and followed links. */ followed_link_results: BrokenLinksResultV1_SyntheticLinkResult[]; + /** + * Path to the Cloud Storage folder where all artifacts (e.g. screenshots) + * will be stored for this execution. e.g. + * gs://>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.error_type = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.error_message = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): BaseError { + return { + error_type: isSet(object.error_type) ? String(object.error_type) : "", + error_message: isSet(object.error_message) ? String(object.error_message) : "", + }; + }, + + toJSON(message: BaseError): unknown { + const obj: any = {}; + message.error_type !== undefined && (obj.error_type = message.error_type); + message.error_message !== undefined && (obj.error_message = message.error_message); + return obj; + }, + + create, I>>(base?: I): BaseError { + return BaseError.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): BaseError { + const message = createBaseBaseError(); + message.error_type = object.error_type ?? ""; + message.error_message = object.error_message ?? ""; + return message; + }, +}; + function createBaseBrokenLinksResultV1(): BrokenLinksResultV1 { return { link_count: undefined, @@ -1193,6 +1350,8 @@ function createBaseBrokenLinksResultV1(): BrokenLinksResultV1 { options: undefined, origin_link_result: undefined, followed_link_results: [], + execution_data_storage_path: "", + errors: [], }; } @@ -1231,6 +1390,12 @@ export const BrokenLinksResultV1 = { for (const v of message.followed_link_results) { BrokenLinksResultV1_SyntheticLinkResult.encode(v!, writer.uint32(90).fork()).ldelim(); } + if (message.execution_data_storage_path !== "") { + writer.uint32(98).string(message.execution_data_storage_path); + } + for (const v of message.errors) { + BaseError.encode(v!, writer.uint32(106).fork()).ldelim(); + } return writer; }, @@ -1318,6 +1483,20 @@ export const BrokenLinksResultV1 = { message.followed_link_results.push(BrokenLinksResultV1_SyntheticLinkResult.decode(reader, reader.uint32())); continue; + case 12: + if (tag !== 98) { + break; + } + + message.execution_data_storage_path = reader.string(); + continue; + case 13: + if (tag !== 106) { + break; + } + + message.errors.push(BaseError.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -1346,6 +1525,10 @@ export const BrokenLinksResultV1 = { followed_link_results: Array.isArray(object?.followed_link_results) ? object.followed_link_results.map((e: any) => BrokenLinksResultV1_SyntheticLinkResult.fromJSON(e)) : [], + execution_data_storage_path: isSet(object.execution_data_storage_path) + ? String(object.execution_data_storage_path) + : "", + errors: Array.isArray(object?.errors) ? object.errors.map((e: any) => BaseError.fromJSON(e)) : [], }; }, @@ -1373,6 +1556,13 @@ export const BrokenLinksResultV1 = { } else { obj.followed_link_results = []; } + message.execution_data_storage_path !== undefined && + (obj.execution_data_storage_path = message.execution_data_storage_path); + if (message.errors) { + obj.errors = message.errors.map((e) => e ? BaseError.toJSON(e) : undefined); + } else { + obj.errors = []; + } return obj; }, @@ -1398,6 +1588,8 @@ export const BrokenLinksResultV1 = { : undefined; message.followed_link_results = object.followed_link_results?.map((e) => BrokenLinksResultV1_SyntheticLinkResult.fromPartial(e)) || []; + message.execution_data_storage_path = object.execution_data_storage_path ?? ""; + message.errors = object.errors?.map((e) => BaseError.fromPartial(e)) || []; return message; }, }; @@ -1414,6 +1606,7 @@ function createBaseBrokenLinksResultV1_BrokenLinkCheckerOptions(): BrokenLinksRe wait_for_selector: "", per_link_options: {}, total_synthetic_timeout_millis: undefined, + screenshot_options: undefined, }; } @@ -1452,6 +1645,12 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions = { if (message.total_synthetic_timeout_millis !== undefined) { writer.uint32(88).int64(message.total_synthetic_timeout_millis); } + if (message.screenshot_options !== undefined) { + BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.encode( + message.screenshot_options, + writer.uint32(98).fork(), + ).ldelim(); + } return writer; }, @@ -1538,6 +1737,16 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions = { message.total_synthetic_timeout_millis = longToNumber(reader.int64() as Long); continue; + case 12: + if (tag !== 98) { + break; + } + + message.screenshot_options = BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.decode( + reader, + reader.uint32(), + ); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -1570,6 +1779,9 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions = { total_synthetic_timeout_millis: isSet(object.total_synthetic_timeout_millis) ? Number(object.total_synthetic_timeout_millis) : undefined, + screenshot_options: isSet(object.screenshot_options) + ? BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.fromJSON(object.screenshot_options) + : undefined, }; }, @@ -1596,6 +1808,9 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions = { } message.total_synthetic_timeout_millis !== undefined && (obj.total_synthetic_timeout_millis = Math.round(message.total_synthetic_timeout_millis)); + message.screenshot_options !== undefined && (obj.screenshot_options = message.screenshot_options + ? BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.toJSON(message.screenshot_options) + : undefined); return obj; }, @@ -1626,6 +1841,9 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions = { return acc; }, {}); message.total_synthetic_timeout_millis = object.total_synthetic_timeout_millis ?? undefined; + message.screenshot_options = (object.screenshot_options !== undefined && object.screenshot_options !== null) + ? BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.fromPartial(object.screenshot_options) + : undefined; return message; }, }; @@ -1802,6 +2020,94 @@ export const BrokenLinksResultV1_BrokenLinkCheckerOptions_PerLinkOptionsEntry = }, }; +function createBaseBrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions(): BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions { + return { storage_location: "", capture_condition: 0 }; +} + +export const BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions = { + encode( + message: BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + if (message.storage_location !== "") { + writer.uint32(10).string(message.storage_location); + } + if (message.capture_condition !== 0) { + writer.uint32(16).int32(message.capture_condition); + } + return writer; + }, + + decode( + input: _m0.Reader | Uint8Array, + length?: number, + ): BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.storage_location = reader.string(); + continue; + case 2: + if (tag !== 16) { + break; + } + + message.capture_condition = reader.int32() as any; + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions { + return { + storage_location: isSet(object.storage_location) ? String(object.storage_location) : "", + capture_condition: isSet(object.capture_condition) + ? brokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions_CaptureConditionFromJSON( + object.capture_condition, + ) + : 0, + }; + }, + + toJSON(message: BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions): unknown { + const obj: any = {}; + message.storage_location !== undefined && (obj.storage_location = message.storage_location); + message.capture_condition !== undefined && + (obj.capture_condition = brokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions_CaptureConditionToJSON( + message.capture_condition, + )); + return obj; + }, + + create, I>>( + base?: I, + ): BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions { + return BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions.fromPartial(base ?? {}); + }, + + fromPartial, I>>( + object: I, + ): BrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions { + const message = createBaseBrokenLinksResultV1_BrokenLinkCheckerOptions_ScreenshotOptions(); + message.storage_location = object.storage_location ?? ""; + message.capture_condition = object.capture_condition ?? 0; + return message; + }, +}; + function createBaseBrokenLinksResultV1_SyntheticLinkResult(): BrokenLinksResultV1_SyntheticLinkResult { return { link_passed: undefined, @@ -1816,6 +2122,7 @@ function createBaseBrokenLinksResultV1_SyntheticLinkResult(): BrokenLinksResultV link_start_time: "", link_end_time: "", is_origin: undefined, + screenshot_output: undefined, }; } @@ -1857,6 +2164,12 @@ export const BrokenLinksResultV1_SyntheticLinkResult = { if (message.is_origin !== undefined) { writer.uint32(96).bool(message.is_origin); } + if (message.screenshot_output !== undefined) { + BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.encode( + message.screenshot_output, + writer.uint32(106).fork(), + ).ldelim(); + } return writer; }, @@ -1951,6 +2264,16 @@ export const BrokenLinksResultV1_SyntheticLinkResult = { message.is_origin = reader.bool(); continue; + case 13: + if (tag !== 106) { + break; + } + + message.screenshot_output = BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.decode( + reader, + reader.uint32(), + ); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -1976,6 +2299,9 @@ export const BrokenLinksResultV1_SyntheticLinkResult = { link_start_time: isSet(object.link_start_time) ? String(object.link_start_time) : "", link_end_time: isSet(object.link_end_time) ? String(object.link_end_time) : "", is_origin: isSet(object.is_origin) ? Boolean(object.is_origin) : undefined, + screenshot_output: isSet(object.screenshot_output) + ? BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.fromJSON(object.screenshot_output) + : undefined, }; }, @@ -1995,6 +2321,9 @@ export const BrokenLinksResultV1_SyntheticLinkResult = { message.link_start_time !== undefined && (obj.link_start_time = message.link_start_time); message.link_end_time !== undefined && (obj.link_end_time = message.link_end_time); message.is_origin !== undefined && (obj.is_origin = message.is_origin); + message.screenshot_output !== undefined && (obj.screenshot_output = message.screenshot_output + ? BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.toJSON(message.screenshot_output) + : undefined); return obj; }, @@ -2022,6 +2351,90 @@ export const BrokenLinksResultV1_SyntheticLinkResult = { message.link_start_time = object.link_start_time ?? ""; message.link_end_time = object.link_end_time ?? ""; message.is_origin = object.is_origin ?? undefined; + message.screenshot_output = (object.screenshot_output !== undefined && object.screenshot_output !== null) + ? BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.fromPartial(object.screenshot_output) + : undefined; + return message; + }, +}; + +function createBaseBrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput(): BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput { + return { screenshot_file: "", screenshot_error: undefined }; +} + +export const BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput = { + encode( + message: BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput, + writer: _m0.Writer = _m0.Writer.create(), + ): _m0.Writer { + if (message.screenshot_file !== "") { + writer.uint32(10).string(message.screenshot_file); + } + if (message.screenshot_error !== undefined) { + BaseError.encode(message.screenshot_error, writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseBrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.screenshot_file = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.screenshot_error = BaseError.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput { + return { + screenshot_file: isSet(object.screenshot_file) ? String(object.screenshot_file) : "", + screenshot_error: isSet(object.screenshot_error) ? BaseError.fromJSON(object.screenshot_error) : undefined, + }; + }, + + toJSON(message: BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput): unknown { + const obj: any = {}; + message.screenshot_file !== undefined && (obj.screenshot_file = message.screenshot_file); + message.screenshot_error !== undefined && + (obj.screenshot_error = message.screenshot_error ? BaseError.toJSON(message.screenshot_error) : undefined); + return obj; + }, + + create, I>>( + base?: I, + ): BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput { + return BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput.fromPartial(base ?? {}); + }, + + fromPartial, I>>( + object: I, + ): BrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput { + const message = createBaseBrokenLinksResultV1_SyntheticLinkResult_ScreenshotOutput(); + message.screenshot_file = object.screenshot_file ?? ""; + message.screenshot_error = (object.screenshot_error !== undefined && object.screenshot_error !== null) + ? BaseError.fromPartial(object.screenshot_error) + : undefined; return message; }, }; diff --git a/packages/synthetics-sdk-api/src/index.ts b/packages/synthetics-sdk-api/src/index.ts index 948a62b9..ff5d00ff 100644 --- a/packages/synthetics-sdk-api/src/index.ts +++ b/packages/synthetics-sdk-api/src/index.ts @@ -25,4 +25,6 @@ export { export { instantiateAutoInstrumentation, getInstrumentedLogger, + resolveProjectId, } from './auto_instrumentation'; +export { getExecutionRegion } from './cloud_region_resolver'; diff --git a/packages/synthetics-sdk-api/test/unit/cloud_region_resolver.spec.ts b/packages/synthetics-sdk-api/test/unit/cloud_region_resolver.spec.ts new file mode 100644 index 00000000..739160f2 --- /dev/null +++ b/packages/synthetics-sdk-api/test/unit/cloud_region_resolver.spec.ts @@ -0,0 +1,45 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import axios from 'axios'; +import * as sinon from 'sinon'; +import { expect } from 'chai'; +import { getExecutionRegion } from '../../src/cloud_region_resolver'; + +describe('getExecutionRegion', () => { + let axiosGetStub: sinon.SinonStub; + + beforeEach(() => { + axiosGetStub = sinon.stub(axios, 'get'); + }); + + afterEach(() => { + axiosGetStub.restore(); + }); + + it('should retrieve the region from the metadata server', async () => { + axiosGetStub.resolves({ data: 'projects/123456789/regions/us-east1' }); + + const region = await getExecutionRegion(); + expect(region).to.equal('us-east1'); + expect(axiosGetStub.calledOnce).to.be.true; + }); + + it('should handle errors from the metadata server', async () => { + axiosGetStub.rejects(new Error('Metadata server error')); + + const region = await getExecutionRegion(); + expect(region).to.be.null; + }); +});