Как подключить Google Cloud SQL к облачным функциям?

Я пытаюсь использовать Облачные функции для Firebase для создания API, который взаимодействует с экземпляром Google Cloud SQL (PostgreSQL).

Я использую триггер HTTP (S).

Когда я белым списком моего IP-адреса рабочего стола, я могу подключиться к Cloud SQL с помощью кода функции node.js с моей локальной машины. Но когда я развертываю, я не могу подключиться, и я не могу определить IP-адрес HOST сервера функций Firebase, в белый список.

Как вы разговариваете с Google Cloud SQL из облачных функций для Firebase?

Спасибо!

// Code Sample, of what working on Localhost.
var functions = require('firebase-functions');

var pg = require('pg');
var pgConfig = {
  user: functions.config().pg.user,
  database: functions.config().pg.database,
  password: functions.config().pg.password,
  host: functions.config().pg.host
}

exports.helloSql = functions.https.onRequest((request, response) => {
  console.log('connecting...');
  try {
    client.connect(function(err) {
      if (err) throw err;

      console.log('connection success');
      console.log('querying...');

      client.query('SELECT * FROM guestbook;', function(err, result){
        if (err) throw err;

        console.log('querying success.');
        console.log('Results: ', result);
        console.log('Ending...');

        client.end(function(err){
          if (err) throw err;
          console.log('End success.');
          response.send(result);
        });
      });

    });
  } catch(er) {
    console.error(er.stack)
    response.status(500).send(er);
  }
});

Ответ 1

В настоящее время это невозможно. Однако запрос функции на трекер проблемы # 36388165:

Подключение к Cloud SQL из облачных функций в настоящее время не поддерживается, поскольку UNIX-сокет не существует (вызывает ENOENT) и в белом списке нет определенного диапазона IP (вызывая ETIMEDOUT). Один возможность заключается в использовании белого списка 0.0.0.0/0 из экземпляра Cloud SQL, но это не рекомендуется по соображениям безопасности.

Если это важная функция для вас, я бы посоветовал вам посетить emetracker и запустить функцию, чтобы помочь ей получить популярность.

Ответ 2

Я нашел ответ в дальнейшем обсуждении # 36388165.

отказ от ответственности: это, похоже, официально не объявлено, поэтому впоследствии может измениться. также я только тестирую в mysql. но природа этого решения, я думаю, что такой же способ должен работать, как в модуле pg (кажется, принять путь к сокету домена в качестве параметра хоста)

EDIT (2017/12/7): Google, похоже, предоставляет официальный ранний доступ, и тот же метод все еще работает.

в https://issuetracker.google.com/issues/36388165#comment44 google guy говорит, что экземпляр облачной функции может разговаривать с облачным sql через сокет через специальный путь '/cloudsql/$PROJECT_ID: $РЕГИОН: $DBNAME.

Я действительно могу подключиться и управлять облачным SQL из-под кода облачной функции.

var mysql = require('mysql');
exports.handler = function handler(req, res) {
    var c = mysql.createConnection({
      socketPath: '/cloudsql/' + '$PROJECT_ID:$REGION:$DBNAME',
      user     : '$USER',
      password : '$PASS',
      database: '$DATABASE'
    });
    c.connect();
    c.query(`SELECT * FROM table where id = ?`, 
                                req.body.id, function (e, results) {
        //made reply here
    });
};

Надеюсь, это поможет тем, кто не может дождаться официального анонса из Google.

Ответ 4

Найдите область вашей базы данных и имя экземпляра на GCP > SQL > экземпляры:

введите описание изображения здесь

Сохраните пароль своей базы данных в Firebase environment, выполнив:

$ firebase functions:config:set db.password="<password>"

Тогда...

db.js

const { Pool } = require('pg');
const { config } = require('firebase-functions');

module.exports = new Pool({
  max: 1,
  user: '<username>',
  database: '<database>',
  password: config().db.password,
  host: `/cloudsql/${process.env.GCP_PROJECT}:<region>:<instance>`,
});

someFunction.js

const { https } = require('firebase-functions');
const db = require('./db');

module.exports = https.onRequest((req, res) =>
  db
    .query('SELECT version()')
    .then(({ rows: [{ version }]) => {
      res.send(version);
    }));

См. также fooobar.com/info/220694/... (используя современный синтаксис JavaScript через Babel)