diff --git a/.github/workflows/workflows.json b/.github/workflows/workflows.json index 34815b49bc..cfd118cd08 100644 --- a/.github/workflows/workflows.json +++ b/.github/workflows/workflows.json @@ -7,7 +7,7 @@ "appengine/hello-world/flexible", "appengine/hello-world/standard", "appengine/memcached", - "apengine/metadata/flexible", + "appengine/metadata/flexible", "appengine/metadata/standard", "appengine/pubsub", "appengine/static-files", diff --git a/asset/snippets/analyzeIamPolicy.js b/asset/snippets/analyzeIamPolicy.js new file mode 100644 index 0000000000..44ea9f6a0e --- /dev/null +++ b/asset/snippets/analyzeIamPolicy.js @@ -0,0 +1,57 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Analyze Iam Policy +// description: Analyzes accessible IAM policies that match a request. +// usage: node analyzeIamPolicy + +async function main() { + // [START asset_quickstart_analyze_iam_policy] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + const projectId = await client.getProjectId(); + + async function analyzeIamPolicy() { + const request = { + analysisQuery: { + scope: `projects/${projectId}`, + resourceSelector: { + fullResourceName: `//cloudresourcemanager.googleapis.com/projects/${projectId}`, + }, + options: { + expandGroups: true, + outputGroupEdges: true, + }, + }, + }; + + // Handle the operation using the promise pattern. + const result = await client.analyzeIamPolicy(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + // [END asset_quickstart_analyze_iam_policy] + analyzeIamPolicy(); +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/asset/snippets/analyzeIamPolicyLongrunningBigquery.js b/asset/snippets/analyzeIamPolicyLongrunningBigquery.js new file mode 100644 index 0000000000..10eab93e7a --- /dev/null +++ b/asset/snippets/analyzeIamPolicyLongrunningBigquery.js @@ -0,0 +1,71 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Analyze Iam Policy Longrunning and write results to Bigquery +// description: Analyzes accessible IAM policies that match a request. +// usage: node analyzeIamPolicyLongrunningBigquery + +async function main(datasetId, tablePrefix) { + // [START asset_quickstart_analyze_iam_policy_longrunning_bigquery] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + const projectId = await client.getProjectId(); + + async function analyzeIamPolicyLongrunningBigquery() { + // TODO(developer): choose the dataset and table prefix + // const datasetId = '' + // const tablePrefix = '' + + const request = { + analysisQuery: { + scope: `projects/${projectId}`, + resourceSelector: { + fullResourceName: `//cloudresourcemanager.googleapis.com/projects/${projectId}`, + }, + options: { + expandGroups: true, + outputGroupEdges: true, + }, + }, + outputConfig: { + bigqueryDestination: { + dataset: `projects/${projectId}/datasets/${datasetId}`, + tablePrefix: tablePrefix, + }, + }, + }; + + // Handle the operation using the promise pattern. + const [operation] = await client.analyzeIamPolicyLongrunning(request); + + // Operation#promise starts polling for the completion of the operation. + const [result] = await operation.promise(); + + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + // [END asset_quickstart_analyze_iam_policy_longrunning_bigquery] + analyzeIamPolicyLongrunningBigquery(); +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/asset/snippets/analyzeIamPolicyLongrunningGcs.js b/asset/snippets/analyzeIamPolicyLongrunningGcs.js new file mode 100644 index 0000000000..df93e0c494 --- /dev/null +++ b/asset/snippets/analyzeIamPolicyLongrunningGcs.js @@ -0,0 +1,69 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Analyze Iam Policy Longrunning and write results to GCS +// description: Analyzes accessible IAM policies that match a request. +// usage: node analyzeIamPolicyLongrunningGcs + +async function main(gcsUri) { + // [START asset_quickstart_analyze_iam_policy_longrunning_gcs] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + const projectId = await client.getProjectId(); + + async function analyzeIamPolicyLongrunningGcs() { + // TODO(developer): choose the gcs path uri + // const gcsUri = 'Gcs path uri, e.g.: gs:///' + + const request = { + analysisQuery: { + scope: `projects/${projectId}`, + resourceSelector: { + fullResourceName: `//cloudresourcemanager.googleapis.com/projects/${projectId}`, + }, + options: { + expandGroups: true, + outputGroupEdges: true, + }, + }, + outputConfig: { + gcsDestination: { + uri: gcsUri, + }, + }, + }; + + // Handle the operation using the promise pattern. + const [operation] = await client.analyzeIamPolicyLongrunning(request); + + // Operation#promise starts polling for the completion of the operation. + const [result] = await operation.promise(); + + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + // [END asset_quickstart_analyze_iam_policy_longrunning_gcs] + analyzeIamPolicyLongrunningGcs(); +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/asset/snippets/createFeed.js b/asset/snippets/createFeed.js new file mode 100644 index 0000000000..e139d747cf --- /dev/null +++ b/asset/snippets/createFeed.js @@ -0,0 +1,68 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Create Feed +// description: Create Feed. +// usage: node createFeed "//storage.googleapis.com/", projects//topics/, "RESOURCE" + +async function main(feedId, assetNames, topicName, contentType) { + // [START asset_quickstart_create_feed] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const feedId = 'my feed'; + // const assetNames = '//storage.googleapis.com/,//storage.googleapis.com/'; + // const topicName = 'projects//topics/' + // const contentType = 'RESOURCE'; + + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function createFeed() { + const projectId = await client.getProjectId(); + // TODO(developer): Choose asset names, such as //storage.googleapis.com/[YOUR_BUCKET_NAME]. + // const assetNames = ['ASSET_NAME1', 'ASSET_NAME2', ...]; + + const request = { + parent: `projects/${projectId}`, + feedId: feedId, + feed: { + assetNames: assetNames.split(','), + contentType: contentType, + feedOutputConfig: { + pubsubDestination: { + topic: topicName, + }, + }, + }, + }; + + // Handle the operation using the promise pattern. + const result = await client.createFeed(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + // [END asset_quickstart_create_feed] + } + createFeed(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/deleteFeed.js b/asset/snippets/deleteFeed.js new file mode 100644 index 0000000000..35f2d3705e --- /dev/null +++ b/asset/snippets/deleteFeed.js @@ -0,0 +1,46 @@ +// Copyright 2019 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Delete Feed +// description: Delete Feed. +// usage: node deleteFeed "project//feeds/" + +async function main(feedName) { + // [START asset_quickstart_delete_feed] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function deleteFeed() { + const request = { + name: feedName, + }; + + // Handle the operation using the promise pattern. + const result = await client.deleteFeed(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + // [END asset_quickstart_delete_feed] + } + deleteFeed(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/exportAssets.js b/asset/snippets/exportAssets.js new file mode 100644 index 0000000000..176176f68d --- /dev/null +++ b/asset/snippets/exportAssets.js @@ -0,0 +1,67 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Export Assets +// description: Export asserts to specified dump file path. +// usage: node exportAssets.js + +async function main(dumpFilePath, contentType) { + // [START asset_quickstart_export_assets] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const dumpFilePath = 'gs://my-bucket/my-assets.txt'; + // const contentType = 'RESOURCE'; + + const {AssetServiceClient} = require('@google-cloud/asset'); + const client = new AssetServiceClient(); + + async function exportAssets() { + const projectId = await client.getProjectId(); + const projectResource = `projects/${projectId}`; + + // TODO(developer): choose the dump file path + // const dumpFilePath = 'Dump file path, e.g.: gs:///' + const request = { + parent: projectResource, + contentType: contentType, + outputConfig: { + gcsDestination: { + uri: dumpFilePath, + }, + }, + }; + + // Handle the operation using the promise pattern. + const [operation] = await client.exportAssets(request); + + // Operation#promise starts polling for the completion of the operation. + const [result] = await operation.promise(); + + // Do things with with the response. + console.log(result); + } + exportAssets().catch(err => { + throw err; + }); + // [END asset_quickstart_export_assets] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/exportAssetsBigquery.js b/asset/snippets/exportAssetsBigquery.js new file mode 100644 index 0000000000..5105fbe0db --- /dev/null +++ b/asset/snippets/exportAssetsBigquery.js @@ -0,0 +1,66 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Export Assets To BigQuery +// description: Export asserts to specified BigQuery table. +// usage: node exportAssetsBigquery.js + +async function main(dataSet, table) { + // [START asset_quickstart_export_assets_bigquery] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const dataSet = 'projects/project_id/datasets/dataset_id'; + // const table = 'mytable'; + + const {AssetServiceClient} = require('@google-cloud/asset'); + const client = new AssetServiceClient(); + + async function exportAssetsBigquery() { + const projectId = await client.getProjectId(); + const projectResource = client.projectPath(projectId); + const dataset = dataSet; + + const request = { + parent: projectResource, + outputConfig: { + bigqueryDestination: { + dataset: `projects/${projectId}/${dataset}`, + table: table, + force: true, + }, + }, + }; + + // Handle the operation using the promise pattern. + const [operation] = await client.exportAssets(request); + + // Operation#promise starts polling for the completion of the operation. + const [result] = await operation.promise(); + + // Do things with with the response. + console.log(result); + } + + exportAssetsBigquery(); + // [END asset_quickstart_export_assets_bigquery] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/getBatchAssetHistory.js b/asset/snippets/getBatchAssetHistory.js new file mode 100644 index 0000000000..1e664ff961 --- /dev/null +++ b/asset/snippets/getBatchAssetHistory.js @@ -0,0 +1,64 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Get Batch Asset History +// description: Batch get history of assets. +// usage: node getBatchAssetHistory "//storage.googleapis.com/" + +async function main(assetNames, contentType) { + // [START asset_quickstart_batch_get_assets_history] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const assetNames = '//storage.googleapis.com/,//storage.googleapis.com/'; + // const contentType = 'RESOURCE'; + + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function batchGetAssetsHistory() { + const projectId = await client.getProjectId(); + const projectResource = `projects/${projectId}`; + // TODO(developer): Choose asset names, such as //storage.googleapis.com/[YOUR_BUCKET_NAME]. + // const assetNames = ['ASSET_NAME1', 'ASSET_NAME2', ...]; + + const request = { + parent: projectResource, + assetNames: assetNames.split(','), + contentType: contentType, + readTimeWindow: { + startTime: { + seconds: Math.floor(new Date().getTime() / 1000), + }, + }, + }; + + // Handle the operation using the promise pattern. + const result = await client.batchGetAssetsHistory(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + // [END asset_quickstart_batch_get_assets_history] + } + batchGetAssetsHistory(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/getBatchEffectiveIamPolicies.js b/asset/snippets/getBatchEffectiveIamPolicies.js new file mode 100644 index 0000000000..27f9706479 --- /dev/null +++ b/asset/snippets/getBatchEffectiveIamPolicies.js @@ -0,0 +1,48 @@ +// Copyright 2022 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Batch Get Effective Iam Policies +// description: Batch get effective IAM policies that match a request. +// usage: node batchGetEffectiveIamPolicies + +async function main(assetNames) { + // [START asset_quickstart_batch_get_effective_iam_policies] + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function batchGetEffectiveIamPolicies() { + const projectId = await client.getProjectId(); + const request = { + scope: `projects/${projectId}`, + names: assetNames.split(','), + }; + + // Handle the operation using the promise pattern. + const result = await client.batchGetEffectiveIamPolicies(request); + // Handle the response. + console.dir(result, {depth: null}); + } + // [END asset_quickstart_batch_get_effective_iam_policies] + batchGetEffectiveIamPolicies(); +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/asset/snippets/getFeed.js b/asset/snippets/getFeed.js new file mode 100644 index 0000000000..073a6ef6ab --- /dev/null +++ b/asset/snippets/getFeed.js @@ -0,0 +1,46 @@ +// Copyright 2019 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Get Feed +// description: Get Feed. +// usage: node getFeed "project//feeds/" + +async function main(feedName) { + // [START asset_quickstart_get_feed] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function getFeed() { + const request = { + name: feedName, + }; + + // Handle the operation using the promise pattern. + const result = await client.getFeed(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + getFeed(); + // [END asset_quickstart_get_feed] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/listAssets.js b/asset/snippets/listAssets.js new file mode 100644 index 0000000000..36293caf81 --- /dev/null +++ b/asset/snippets/listAssets.js @@ -0,0 +1,64 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: List Assets +// description: List assets under the current project. +// usage: node listAssets +// example: node listAssets "storage.googleapis.com/Bucket,bigquery.googleapis.com/Table" 'RESOURCE' + +async function main(assetTypes, contentType) { + // [START asset_quickstart_list_assets] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const assetTypes = 'storage.googleapis.com/Bucket,bigquery.googleapis.com/Table'; + // const contentType = 'RESOURCE'; + + const util = require('util'); + const {v1} = require('@google-cloud/asset'); + const client = new v1.AssetServiceClient(); + + const projectId = await client.getProjectId(); + const projectResource = `projects/${projectId}`; + // TODO(developer): Choose types of assets to list, such as 'storage.googleapis.com/Bucket': + // const assetTypes = 'storage.googleapis.com/Bucket,bigquery.googleapis.com/Table'; + // Or simply use empty string to list all types of assets: + // const assetTypes = ''; + const assetTypesList = assetTypes ? assetTypes.split(',') : []; + + async function listAssets() { + const request = { + parent: projectResource, + assetTypes: assetTypesList, + contentType: contentType, + // (Optional) Add readTime parameter to list assets at the given time instead of current time: + // readTime: { seconds: 1593988758 }, + }; + + // Call cloud.assets.v1.ListAssets API. + const result = await client.listAssets(request); + // Handle the response. + console.log(util.inspect(result, {depth: null})); + } + listAssets(); + // [END asset_quickstart_list_assets] +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/listFeeds.js b/asset/snippets/listFeeds.js new file mode 100644 index 0000000000..301d80bbe2 --- /dev/null +++ b/asset/snippets/listFeeds.js @@ -0,0 +1,48 @@ +// Copyright 2019 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: List Feeds +// description: List Feeds. +// usage: node listFeeds + +async function main() { + // [START asset_quickstart_list_feeds] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function listFeeds() { + const projectId = await client.getProjectId(); + + const request = { + parent: `projects/${projectId}`, + }; + + // Handle the operation using the promise pattern. + const result = await client.listFeeds(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + // [END asset_quickstart_list_feeds] + } + listFeeds(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/package.json b/asset/snippets/package.json new file mode 100644 index 0000000000..3b3431fec6 --- /dev/null +++ b/asset/snippets/package.json @@ -0,0 +1,29 @@ +{ + "name": "@google-cloud/asset-samples", + "description": "Samples for the Cloud Asset API Client Library for Node.js.", + "license": "Apache-2.0", + "author": "Google LLC", + "engines": { + "node": ">=12.0.0" + }, + "files": [ + "*.js" + ], + "repository": "googleapis/nodejs-asset", + "private": true, + "scripts": { + "test": "mocha --timeout 600000" + }, + "dependencies": { + "@google-cloud/asset": "^4.5.0", + "@google-cloud/bigquery": "^6.0.0", + "@google-cloud/compute": "^3.0.0", + "@google-cloud/storage": "^6.0.0", + "uuid": "^9.0.0", + "yargs": "^16.0.0" + }, + "devDependencies": { + "chai": "^4.2.0", + "mocha": "^8.0.0" + } +} diff --git a/asset/snippets/searchAllIamPolicies.js b/asset/snippets/searchAllIamPolicies.js new file mode 100644 index 0000000000..965fd029f1 --- /dev/null +++ b/asset/snippets/searchAllIamPolicies.js @@ -0,0 +1,61 @@ +// Copyright 2020 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Search All Iam Policies +// description: Search All Iam Policies. +// usage: node searchAllIamPolicies + +async function main(scope, query, pageSize, pageToken) { + // [START asset_quickstart_search_all_iam_policies] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const scope = ''; + // const query = ''; + // const pageSize = 0; + // const pageToken = ''; + + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + const projectId = await client.getProjectId(); + + async function searchAllIamPolicies() { + const request = { + scope: `projects/${projectId}`, + query: query, + pageSize: pageSize, + pageToken: pageToken, + }; + const options = { + autoPaginate: false, + }; + + // Handle the operation using the promise pattern. + const result = await client.searchAllIamPolicies(request, options); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + // [END asset_quickstart_search_all_iam_policies] + searchAllIamPolicies(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/searchAllResources.js b/asset/snippets/searchAllResources.js new file mode 100644 index 0000000000..0fa25bbaa2 --- /dev/null +++ b/asset/snippets/searchAllResources.js @@ -0,0 +1,65 @@ +// Copyright 2020 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Search All Resources +// description: Search All Resources. +// usage: node searchAllResources + +async function main(scope, query, assetTypes, pageSize, pageToken, orderBy) { + // [START asset_quickstart_search_all_resources] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const scope = ''; + // const query = ''; + // const assetTypes = []; + // const pageSize = 0; + // const pageToken = ''; + // const orderBy = ''; + + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + const projectId = await client.getProjectId(); + + async function searchAllResources() { + const request = { + scope: `projects/${projectId}`, + query: query, + assetTypes: assetTypes, + pageSize: pageSize, + pageToken: pageToken, + orderBy: orderBy, + }; + const options = { + autoPaginate: false, + }; + + // Handle the operation using the promise pattern. + const result = await client.searchAllResources(request, options); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + } + // [END asset_quickstart_search_all_resources] + searchAllResources(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/asset/snippets/test/samples.test.js b/asset/snippets/test/samples.test.js new file mode 100644 index 0000000000..bbbea92822 --- /dev/null +++ b/asset/snippets/test/samples.test.js @@ -0,0 +1,262 @@ +// Copyright 2021 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 +// +// http://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. + +'use strict'; + +const {assert} = require('chai'); +const {after, before, describe, it} = require('mocha'); +const uuid = require('uuid'); +const cp = require('child_process'); +const {Storage} = require('@google-cloud/storage'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const storage = new Storage(); +const bucketName = `asset-nodejs-${uuid.v4()}`; +const bucket = storage.bucket(bucketName); +const fileSuffix = `${uuid.v4()}`; + +const {BigQuery} = require('@google-cloud/bigquery'); +const bigquery = new BigQuery(); +const options = { + location: 'US', +}; +const datasetId = `asset_nodejs_${uuid.v4()}`.replace(/-/gi, '_'); + +const compute = require('@google-cloud/compute'); +const instancesClient = new compute.InstancesClient(); + +// Some of these tests can take an extremely long time, and occasionally +// timeout, see: +// "Timeout of 180000ms exceeded. For async tests and hooks". +function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +describe('quickstart sample tests', () => { + let projectId; + let zone; + let instanceName; + let machineType; + let sourceImage; + let networkName; + before(async () => { + zone = 'us-central1-a'; + instanceName = `asset-nodejs-${uuid.v4()}`; + machineType = 'n1-standard-1'; + sourceImage = + 'projects/ubuntu-os-cloud/global/images/family/ubuntu-1804-lts'; + networkName = 'global/networks/default'; + projectId = await instancesClient.getProjectId(); + + await bucket.create(); + await bigquery.createDataset(datasetId, options); + await bigquery.dataset(datasetId).exists(); + + const [response] = await instancesClient.insert({ + instanceResource: { + name: instanceName, + disks: [ + { + // Describe the size and source image of the boot disk to attach to the instance. + initializeParams: { + diskSizeGb: '10', + sourceImage, + }, + autoDelete: true, + boot: true, + type: 'PERSISTENT', + }, + ], + machineType: `zones/${zone}/machineTypes/${machineType}`, + networkInterfaces: [ + { + // Use the network interface provided in the networkName argument. + name: networkName, + }, + ], + }, + project: projectId, + zone, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the create operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + }); + + after(async () => { + await bucket.delete(); + await bigquery.dataset(datasetId).delete({force: true}).catch(console.warn); + const [response] = await instancesClient.delete({ + instance: instanceName, + project: projectId, + zone, + }); + let operation = response.latestResponse; + const operationsClient = new compute.ZoneOperationsClient(); + + // Wait for the delete operation to complete. + while (operation.status !== 'DONE') { + [operation] = await operationsClient.wait({ + operation: operation.name, + project: projectId, + zone: operation.zone.split('/').pop(), + }); + } + }); + + it('should export assets to specified path', async () => { + const dumpFilePath = `gs://${bucketName}/my-assets-${fileSuffix}.txt`; + execSync(`node exportAssets ${dumpFilePath}`); + let waitMs = 4000; + let exists = false; + let file; + for (let retry = 0; retry < 3 && !exists; ++retry) { + await sleep((waitMs *= 2)); + file = await bucket.file(`my-assets-${fileSuffix}.txt`); + exists = await file.exists(); + } + assert.ok(exists); + await file.delete(); + }); + + it('should export asset relationships to specified path', async () => { + const dumpFilePath = `gs://${bucketName}/my-relationships-${fileSuffix}.txt`; + const contentType = 'RELATIONSHIP'; + execSync(`node exportAssets ${dumpFilePath} ${contentType}`); + let waitMs = 4000; + let exists = false; + let file; + for (let retry = 0; retry < 3 && !exists; ++retry) { + await sleep((waitMs *= 2)); + file = await bucket.file(`my-relationships-${fileSuffix}.txt`); + exists = await file.exists(); + } + assert.ok(exists); + await file.delete(); + }); + + // The assets returned within 'readTimeWindow' frequently do not include + // the newly created bucket: + it('should get assets history successfully', async () => { + const assetName = `//storage.googleapis.com/${bucketName}`; + let waitMs = 1000; + let included = false; + for (let retry = 0; retry < 3 && !included; ++retry) { + await sleep((waitMs *= 2)); + const stdout = execSync( + `node getBatchAssetHistory ${assetName} 'RESOURCE'` + ); + included = stdout.includes(assetName); + } + assert.ok(included); + }); + + it('should run the quickstart', async () => { + const assetName = `//storage.googleapis.com/${bucketName}`; + const stdout = execSync(`node quickstart ${assetName}`); + assert.include(stdout, assetName); + }); + + // https://github.com/googleapis/nodejs-asset/issues/650 + it.skip('should search all resources successfully', async () => { + const query = `name:${instanceName}`; + const stdout = execSync(`node searchAllResources '' ${query}`); + assert.include(stdout, instanceName); + }); + + it('should search all iam policies successfully', async () => { + const query = 'policy:roles/owner'; + const stdout = execSync(`node searchAllIamPolicies '' ${query}`); + assert.include(stdout, 'roles/owner'); + }); + + it('should list assets successfully', async () => { + const assetType = 'storage.googleapis.com/Bucket'; + const stdout = execSync(`node listAssets ${assetType} 'RESOURCE'`); + assert.include(stdout, assetType); + }); + + it('should list asset relationship successfully', async () => { + const stdout = execSync("node listAssets '' 'RELATIONSHIP'"); + assert.include(stdout, 'relatedAsset'); + }); + + it('should get effective iam policies successfully', async () => { + const assetName = `//storage.googleapis.com/${bucketName}`; + const stdout = execSync(`node getBatchEffectiveIamPolicies ${assetName}`); + assert.include(stdout, assetName); + }); + + it('should analyze iam policy successfully', async () => { + const stdout = execSync('node analyzeIamPolicy'); + assert.include(stdout, '//cloudresourcemanager.googleapis.com/projects'); + }); + + it('should analyze iam policy and write analysis results to gcs successfully', async () => { + const uri = `gs://${bucketName}/my-analysis.json`; + execSync(`node analyzeIamPolicyLongrunningGcs ${uri}`); + let waitMs = 1000; + let exists = false; + let file; + for (let retry = 0; retry < 3 && !exists; ++retry) { + await sleep((waitMs *= 2)); + file = await bucket.file('my-analysis.json'); + exists = await file.exists(); + } + assert.ok(exists); + await file.delete(); + }); + + it('should analyze iam policy and write analysis results to bigquery successfully', async () => { + const tablePrefix = 'analysis_nodejs'; + execSync( + `node analyzeIamPolicyLongrunningBigquery ${datasetId} ${tablePrefix}` + ); + let waitMs = 4000; + let metadataTable; + let metadataTable_exists = false; + let resultsTable; + let resultsTable_exists = false; + + for ( + let retry = 0; + retry < 3 && !(metadataTable_exists || resultsTable_exists); + ++retry + ) { + await sleep((waitMs *= 2)); + metadataTable = await bigquery + .dataset(datasetId) + .table('analysis_nodejs_analysis'); + metadataTable_exists = await metadataTable.exists(); + resultsTable = await bigquery + .dataset(datasetId) + .table('analysis_nodejs_analysis_result'); + resultsTable_exists = await resultsTable.exists(); + } + + assert.ok(metadataTable_exists); + assert.ok(resultsTable_exists); + await metadataTable.delete(); + await resultsTable.delete(); + }); +}); diff --git a/asset/snippets/updateFeed.js b/asset/snippets/updateFeed.js new file mode 100644 index 0000000000..db25a131fd --- /dev/null +++ b/asset/snippets/updateFeed.js @@ -0,0 +1,56 @@ +// Copyright 2019 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 +// +// http://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. + +'use strict'; + +// sample-metadata: +// title: Update Feed +// description: Update Feed. +// usage: node updateFeed "project//feeds/" projects//topics/ + +async function main(feedName, topicName) { + // [START asset_quickstart_update_feed] + const util = require('util'); + const {AssetServiceClient} = require('@google-cloud/asset'); + + const client = new AssetServiceClient(); + + async function updateFeed() { + const request = { + feed: { + name: feedName, + feedOutputConfig: { + pubsubDestination: { + topic: topicName, + }, + }, + }, + updateMask: { + paths: ['feed_output_config.pubsub_destination.topic'], + }, + }; + + // Handle the operation using the promise pattern. + const result = await client.updateFeed(request); + // Do things with with the response. + console.log(util.inspect(result, {depth: null})); + // [END asset_quickstart_update_feed] + } + updateFeed(); +} + +main(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +});