无法启动 backup:Request 失败,状态代码为 400 Google 云
Could not start backup:Request failed with status code 400 Google Cloud
我正在尝试为 Firestore 创建一个备份系统。
我遵循了这个 guide 的每一步,当我尝试部署代码时,它返回 Request failed with status code 400
PROJECT-ID@appspot.gserviceaccount.com 权限:Cloud Datastore Import Export Admin,
编辑,
存储管理员
这是app.js
的代码
'use strict';
const axios = require('axios');
const dateformat = require('dateformat');
const { google } = require('googleapis');
const express = require('express');
const util = require('util')
const request = require('request');
const admin = require('firebase-admin');
const {Storage} = require('@google-cloud/storage');
// Creates a client
const storage = new Storage();
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const db = admin.firestore();
const googleMapsClient = require('@google/maps').createClient({
key: 'AIza*****',
Promise: Promise
});
const app = express();
// Trigger a backup
app.get('/cloud-firestore-export', async (req, res) => {
const auth = await google.auth.getClient({
scopes: ['https://www.googleapis.com/auth/datastore'],
});
const accessTokenResponse = await auth.getAccessToken();
const accessToken = accessTokenResponse.token;
const headers = {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + accessToken,
};
const { outputUriPrefix } = req.query;
if (!outputUriPrefix) {
res.status(500).send('outputUriPrefix required');
} else if (outputUriPrefix && outputUriPrefix.indexOf('gs://') !== 0) {
res.status(500).send('Malformed outputUriPrefix: ${outputUriPrefix}');
}
// Construct a backup path folder based on the timestamp
const timestamp = dateformat(Date.now(), 'yyyy-mm-dd-HH-MM-ss');
let path = outputUriPrefix;
if (path.endsWith('/')) {
path += timestamp;
} else {
path += '/' + timestamp;
}
const body = {
outputUriPrefix: path,
};
// If specified, mark specific collections for backup
const { collections } = req.query;
if (collections) {
body.collectionIds = collections.split(',');
}
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
const url = 'https://firestore.googleapis.com/v1beta1/projects/' + projectId + '/databases/(default):exportDocuments';
try {
const response = await axios.post(url, body, { headers });
res
.status(200)
.send(response.data)
.end();
} catch (e) {
if (e.response) {
console.warn(e.response.data);
}
res
.status(500)
.send('Could not start backup:' + e.message)
.end();
}
});
°°°°
// Start the server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log('App listening on port ${PORT}');
console.log('Press Ctrl+C to quit.');
});
我有另一个正在监听“/”的函数。这可能会导致问题吗?
package.json:
{
"name": "solution-scheduled-backups",
"version": "1.0.0",
"description": "Scheduled Cloud Firestore backups via AppEngine cron",
"main": "app.js",
"engines": {
"node": "10.x.x"
},
"scripts": {
"deploy": "gcloud app deploy --quiet app.yaml cron.yaml",
"start": "node app.js"
},
"author": "Google, Inc.",
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/storage": "^3.2.1",
"@google/maps": "^0.5.5",
"axios": "^0.19.0",
"dateformat": "^3.0.3",
"express": "^4.17.1",
"firebase-admin": "^8.4.0",
"googleapis": "^42.0.0",
"request": "^2.88.0"
},
"devDependencies": {
"prettier": "^1.18.2"
}
}
我也查看了Cron日志,没有与错误相关的内容。它只有 returns 500 error
所以我一直在复制你的问题,我找到了解决方案。
我一直遇到和你一样的错误,我终于弄明白了。如果您查看 GAE 日志,您会看到错误提示 'Project \' "YOUR PROJECT" \' is not a Cloud Firestore enabled project.'.
这对我有用:
- 创建一个新项目。
- 转到 GCP 中的 API 库并启用 Firestore 安装 API。
- 转到 Firebase 并将您的 GCP 项目 link 转到 firebase 项目。
- 转到数据库并创建 Firestore 数据库。
- 按照 repo 的权限和对应用程序引擎的部署。
- 测试cron,会成功的。
如果您曾经在实际项目中启用过 DataStore,您将无法在第 3 步执行 Firestore 实例。
这将为您创建所需的存储桶,格式为 .appspot.com,您已授予权限。
转到 GAE 并创建您的 cron.yaml、app.js 和您需要的一切。我使用 this repo 进行测试。
在存储库的 readme.md 中,您拥有为您的服务帐户授予权限所必须执行的确切命令。
记得按照cron.yaml中的说明更改存储桶。
按照回购协议中提到的步骤进行操作,因为它们做得很好。
让我知道它是否适合您!
The main problem is the bucket location
当您创建备份存储桶时,您必须使用 Multi-Region
否则您将收到来自服务器的拒绝。
我认为这是 Google Cloud
的错误
Solution
删除存储桶并创建一个具有多区域位置的新存储桶
单一位置的错误:
'Bucket backup-bucket is in location EUR4. This project can only operate on buckets
spanning location europe-north1 or europe-west1 or eu or europe-west2 or
europe-west3 or europe-west4 or europe-west5 or europe-west6.',
我正在尝试为 Firestore 创建一个备份系统。
我遵循了这个 guide 的每一步,当我尝试部署代码时,它返回 Request failed with status code 400
PROJECT-ID@appspot.gserviceaccount.com 权限:Cloud Datastore Import Export Admin, 编辑, 存储管理员
这是app.js
的代码'use strict';
const axios = require('axios');
const dateformat = require('dateformat');
const { google } = require('googleapis');
const express = require('express');
const util = require('util')
const request = require('request');
const admin = require('firebase-admin');
const {Storage} = require('@google-cloud/storage');
// Creates a client
const storage = new Storage();
admin.initializeApp({
credential: admin.credential.applicationDefault()
});
const db = admin.firestore();
const googleMapsClient = require('@google/maps').createClient({
key: 'AIza*****',
Promise: Promise
});
const app = express();
// Trigger a backup
app.get('/cloud-firestore-export', async (req, res) => {
const auth = await google.auth.getClient({
scopes: ['https://www.googleapis.com/auth/datastore'],
});
const accessTokenResponse = await auth.getAccessToken();
const accessToken = accessTokenResponse.token;
const headers = {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + accessToken,
};
const { outputUriPrefix } = req.query;
if (!outputUriPrefix) {
res.status(500).send('outputUriPrefix required');
} else if (outputUriPrefix && outputUriPrefix.indexOf('gs://') !== 0) {
res.status(500).send('Malformed outputUriPrefix: ${outputUriPrefix}');
}
// Construct a backup path folder based on the timestamp
const timestamp = dateformat(Date.now(), 'yyyy-mm-dd-HH-MM-ss');
let path = outputUriPrefix;
if (path.endsWith('/')) {
path += timestamp;
} else {
path += '/' + timestamp;
}
const body = {
outputUriPrefix: path,
};
// If specified, mark specific collections for backup
const { collections } = req.query;
if (collections) {
body.collectionIds = collections.split(',');
}
const projectId = process.env.GOOGLE_CLOUD_PROJECT;
const url = 'https://firestore.googleapis.com/v1beta1/projects/' + projectId + '/databases/(default):exportDocuments';
try {
const response = await axios.post(url, body, { headers });
res
.status(200)
.send(response.data)
.end();
} catch (e) {
if (e.response) {
console.warn(e.response.data);
}
res
.status(500)
.send('Could not start backup:' + e.message)
.end();
}
});
°°°°
// Start the server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log('App listening on port ${PORT}');
console.log('Press Ctrl+C to quit.');
});
我有另一个正在监听“/”的函数。这可能会导致问题吗?
package.json:
{
"name": "solution-scheduled-backups",
"version": "1.0.0",
"description": "Scheduled Cloud Firestore backups via AppEngine cron",
"main": "app.js",
"engines": {
"node": "10.x.x"
},
"scripts": {
"deploy": "gcloud app deploy --quiet app.yaml cron.yaml",
"start": "node app.js"
},
"author": "Google, Inc.",
"license": "Apache-2.0",
"dependencies": {
"@google-cloud/storage": "^3.2.1",
"@google/maps": "^0.5.5",
"axios": "^0.19.0",
"dateformat": "^3.0.3",
"express": "^4.17.1",
"firebase-admin": "^8.4.0",
"googleapis": "^42.0.0",
"request": "^2.88.0"
},
"devDependencies": {
"prettier": "^1.18.2"
}
}
我也查看了Cron日志,没有与错误相关的内容。它只有 returns 500 error
所以我一直在复制你的问题,我找到了解决方案。
我一直遇到和你一样的错误,我终于弄明白了。如果您查看 GAE 日志,您会看到错误提示 'Project \' "YOUR PROJECT" \' is not a Cloud Firestore enabled project.'.
这对我有用:
- 创建一个新项目。
- 转到 GCP 中的 API 库并启用 Firestore 安装 API。
- 转到 Firebase 并将您的 GCP 项目 link 转到 firebase 项目。
- 转到数据库并创建 Firestore 数据库。
- 按照 repo 的权限和对应用程序引擎的部署。
- 测试cron,会成功的。
如果您曾经在实际项目中启用过 DataStore,您将无法在第 3 步执行 Firestore 实例。
这将为您创建所需的存储桶,格式为 .appspot.com,您已授予权限。
转到 GAE 并创建您的 cron.yaml、app.js 和您需要的一切。我使用 this repo 进行测试。
在存储库的 readme.md 中,您拥有为您的服务帐户授予权限所必须执行的确切命令。
记得按照cron.yaml中的说明更改存储桶。
按照回购协议中提到的步骤进行操作,因为它们做得很好。
让我知道它是否适合您!
The main problem is the bucket location
当您创建备份存储桶时,您必须使用 Multi-Region
否则您将收到来自服务器的拒绝。
我认为这是 Google Cloud
的错误Solution
删除存储桶并创建一个具有多区域位置的新存储桶
单一位置的错误:
'Bucket backup-bucket is in location EUR4. This project can only operate on buckets
spanning location europe-north1 or europe-west1 or eu or europe-west2 or
europe-west3 or europe-west4 or europe-west5 or europe-west6.',