Статьи

Начало работы с микросервисами с использованием кодовых коробок Syncano

Эта статья была спонсирована Syncano . Спасибо за поддержку спонсоров, которые делают возможным использование SitePoint.

Syncano — это действительно увлекательная платформа, которая помогает вам с бэкэндом и промежуточным программным обеспечением приложений. Мы рассмотрели возможности Syncano в моей последней статье о том, как создать SMS-сервис для ежедневных подтверждений с помощью Stripe & Syncano, где мы собрали сервис, который рассылал ежедневные SMS-подтверждения в сервисе подписки. Syncano позаботится обо всем бэкэнде и промежуточном программном обеспечении. Очень аккуратный!

В этой статье мы более подробно остановимся на концепции CodeBox-ов Syncano — что такое CodeBox-ы, как мы их создаем и запускаем в Syncano, и как мы можем подключить их к внешним API-интерфейсам. Мы создадим демонстрацию с использованием API GitHub, чтобы продемонстрировать, что возможно.

Что такое CodeBox?

CodeBox — это фрагмент кода, который может быть запущен в облаке несколькими способами. Каждый CodeBox предназначен для того, чтобы предоставить одну часть нашей головоломки веб-приложения — один бит функциональности, которая вносит вклад в приложение в целом.

Чтобы предоставить подробности о том, что мы хотели бы, чтобы CodeBox делал в нашем веб-приложении, мы можем передавать аргументы CodeBox так же, как вы передаете аргументы HTTP-запросу. Например, у нас может быть CodeBox, который просматривает текст песни, хранящийся в базе данных. Он будет принимать два параметра, название песни и исполнителя. Примером ввода для этого CodeBox могут быть «Джек Воробей» и «Одинокий остров». CodeBox запускается с использованием этих параметров и предоставляет текст песни, если знает песню. Если нет, он вернет сообщение о том, что не может их найти.

Одна из моих любимых особенностей CodeBox — это то, что они могут быть созданы на нескольких языках. Syncano поддерживает CodeBox, написанные на Python, Golang, Node.js, Swift, PHP и Ruby. Мало того, что CodeBox, написанные на разных языках, могут работать вместе для создания работающего веб-приложения. Это невероятно гибкий!

Код

Для тех, кто хочет следовать примерам, рабочий код доступен на GitHub . Используй, наслаждайся, расширяй — делай как хочешь.

Как создать CodeBox

Чтобы проиллюстрировать использование CodeBoxes в приложении Syncano, мы соберем по-настоящему простое приложение, которое просматривает запросы на извлечение из репозитория GitHub. Пришло время, чтобы у нас был способ следить за тем, как работают наши командные проекты на GitHub?

Для начала мы направляемся в панель управления Syncano и создаем новое приложение. Если вы абсолютно новичок в Syncano и вам нужно немного советов по этому вопросу, взгляните на предыдущую статью SitePoint о Syncano — она ​​должна вам помочь.

Затем мы направляемся в раздел «CodeBoxes» слева и нажимаем любой из значков с плюсом, чтобы создать новый CodeBox:

Пустой экран CodeBoxes и с кнопками для создания нового CodeBox

Затем во всплывающем окне, которое появляется:

  • Введите название для своего CodeBox — это может быть короткий, но понятный ярлык, который поможет вам найти его на панели инструментов, например, «Найти GitHub Pull Requests».
  • Введите описание для вашего CodeBox — это не нужно, но я предпочитаю использовать его, чтобы включить больше подробностей о том, как именно будет работать CodeBox, например, «Поиск и фильтрация запросов извлечения из репозитория GitHub».
  • Выберите среду выполнения, в которой вы бы предпочли работать — в этой статье мы будем использовать Node.js, поэтому, если вы хотите следовать непосредственно, выберите это!
  • Нажмите «Подтвердить», чтобы создать этот CodeBox!

Новые опции всплывающего окна CodeBox

После того как вы создали свой CodeBox, Syncano должен сразу перейти к экрану редактирования CodeBox. Вы увидите пустую страницу с текстом # Start coding! , Мы должны следовать этой инструкции и добавить что-то простое в качестве начального теста.

Пустой CodeBox

Запуск CodeBox

Введите простой оператор console.log() а затем нажмите кнопку «Выполнить» справа, чтобы выполнить тестовый запуск:

Запуск образца CodeBox

Затем, если прокрутить страницу вниз, мы найдем экран результатов с успешным выводом:

Наш пример результата CodeBox

Запуск из-за пределов Синкано

Мы также можем запустить CodeBox за пределами Syncano. Вот в чем заключается истинная сила! Существует два способа получения доступа к нашим CodeBox за пределами Syncano — запуск CodeBox напрямую через cURL, JavaScript или Python или запуск CodeBox через Webhook. Запуск CodeBox напрямую требует ключ учетной записи (и, следовательно, доступ администратора) и вызывает запуск CodeBox в фоновом режиме. Ваш результат не возвращается сразу, что может быть грязно. Webhooks, с другой стороны, не требуют ключа учетной записи и работают синхронно — вы получите результат выполнения CodeBox в ответе.

В качестве двух примеров мы рассмотрим доступ к CodeBox напрямую с помощью команды cURL и через Webhook.

Чтобы получить доступ к CodeBox через cURL, нам нужен ключ учетной записи, чтобы подтвердить, что мы уполномочены на это. Webhooks не требуют ключей учетной записи, поэтому, если вам не интересно знать, как использовать cURL, не стесняйтесь переходить к следующему разделу! Тем не менее, это может быть очень удобно знать, где найти ключ вашей учетной записи.

Поиск ключа вашего аккаунта

Чтобы найти ключ своей учетной записи, нажмите на изображение своего профиля в правом верхнем углу панели управления Syncano и щелкните имя своей учетной записи:

Доступ к странице сведений об учетной записи

На этой странице щелкните раздел «Аутентификация» с правой стороны. На этом экране отображается ключ вашей учетной записи. Скопируйте эту клавишу, нажав кнопку «Копировать» на этом экране или скопировав ключ, который вы видите рядом с кнопкой, вручную:

Копирование ключа учетной записи

Храните этот ключ в надежном месте, мы будем использовать его на следующем шаге!

Запуск CodeBox через cURL

Наша первая опция для удаленного запуска CodeBox — с помощью команды cURL, которую вы можете запустить из командной строки. Для тех, кто заинтересован, вы можете установить его на 64-битной и 32-битной Windows, перейдя по этим ссылкам Для тех, кто использует OS X, Apple уже предоставила вам cURL как часть операционной системы.

Откройте командную строку и введите следующее, заменив YOUR_ACCOUNT_KEY_YOU_COPIED_EARLIER своим ключом учетной записи, а YOUR_INSTANCE_NAME именем вашего экземпляра (у меня был icy-frost-6999 ). 1 — это ваш код CodeBox. Если у вас есть только один CodeBox, его идентификатор будет 1:

 curl -X POST \ -H "X-API-KEY: YOUR_ACCOUNT_KEY_YOU_COPIED_EARLIER" \ -H "Content-Type: application/json" \ "https://api.syncano.io/v1/instances/YOUR_INSTANCE_NAME/codeboxes/1/run/" 

Когда это выполняется, это должно привести к следующему:

 {"status":"pending","links":{"self":"\/v1\/instances\/icy-frost-6999\/codeboxes\/1\/traces\/3\/"},"executed_at":null,"result":{},"duration":null,"id":3} 

Это еще не показывает нам результат, так как трассировка результата доступна с помощью другой команды. В этом ответе мы можем увидеть одну основную информацию, которая нам понадобится для отслеживания результата — "id":3 . Это идентификатор нашего следа, на который мы хотим посмотреть. Чтобы увидеть, выполнялся ли наш console.log() в этой трассировке, мы запускаем следующую команду cURL с нашим идентификатором CodeBox, равным 1, и нашим идентификатором трассировки, равным 3:

 curl \ -H "X-API-KEY: YOUR_ACCOUNT_KEY_YOUCOPIED_EARLIER" \ "https://api.syncano.io/v1/instances/YOUR_INSTANCE_NAME/codeboxes/1/traces/3/ 

Результат должен выглядеть так:

 {"status":"success","links":{"self":"\/v1\/instances\/icy-frost-6999\/codeboxes\/1\/traces\/3\/"},"executed_at":"2016-01-08T03:25:53.881717Z","result":{"stderr":"","stdout":"Hey there SitePoint world. I think this CodeBox is working."},"duration":1489,"id":3} 

Наш console.log() успешно запущен!

Запуск CodeBox через Webhooks

Для нашего веб-приложения мы хотим иметь возможность запускать наш CodeBox через интерфейс JavaScript. Чтобы публично запустить CodeBox без раскрытия ключа учетной записи, мы создали нечто, называемое Webhook. Webhook дает нам публичный URL для отправки запроса POST для запуска CodeBox.

Чтобы настроить общедоступный веб-крючок, перейдите на панель мониторинга Syncano для своего экземпляра и щелкните элемент меню «Веб-крючки» слева. Затем нажмите «Создать веб-крючок»:

Создание Webhook

В появившемся всплывающем окне мы называем Webhook «findpullrequests» и даем ему описание «Публичная ссылка на поиск наших запросов GitHub Pull». Описание предназначено исключительно для вашей справки, поэтому не стесняйтесь описывать его любым удобным для вас способом! Затем мы выбираем наш CodeBox в последнем поле, чтобы установить его как CodeBox, который будет запущен. Нажмите «Сделать этот Webhook общедоступным» и нажмите «Подтвердить», когда будете готовы:

Настройка параметров Webhook

Затем Syncano возвращает нас в наш список веб-крючков, показывая наш новый веб-крючок. В этом веб-крюке есть ссылка под столбцом URL — мы нажимаем ее, чтобы скопировать общедоступный URL-адрес, который мы будем использовать для запуска нашего CodeBox.

Копирование нашего URL Webhook

Стоит отметить — вы можете вставить эту ссылку в браузер, чтобы протестировать Webhooks без необходимости изначально создавать целое приложение.

Запуск CodeBox через JavaScript и Webhooks

Наш внешний интерфейс HTML будет невероятно простым. Вы можете использовать инфраструктуру JavaScript для различных примеров в этой статье, однако, чтобы сделать вещи простыми и общими, насколько это возможно, мы остановились на простом JavaScript на переднем конце с jQuery для нашего запроса POST.

 <!doctype html> <html> <head> <title>GitHub Pull Request Checker</title> </head> <body> <div id="main"> <h1>Pull Requests</h1> <div id="pull-requests"> </div><!-- pull-requests --> </div><!-- main --> <script src="js/vendor/jquery.min.js"></script> <script src="js/vendor/syncano.min.js"></script> <script src="js/app.js"></script> </body> </html> 

Основная строка кода, на которую следует обратить внимание, — это включение файла JavaScript Syncano после jQuery ( вы можете получить файл JavaScript Syncano из их GitHub ):

 <script src="js/syncano.min.js"></script> 

В нашем собственном JavaScript, который мы назвали app.js , мы создадим файл JavaScript со следующим кодом:

 (function() { $.ajax({ type: "POST", url: "https://api.syncano.io/v1/instances/YOUR-INSTANCE-NAME/webhooks/p/abcd/findpullrequests/" }) .done(function(res) { console.log('Response:'); console.log(res); }); }()); 

Мы копируем URL-адрес webhook в поле URL-адреса запроса JQuery AJAX POST:

 $.ajax({ type: "POST", url: "https://api.syncano.io/v1/instances/YOUR-INSTANCE-NAME/webhooks/p/abcd/findpullrequests/", 

.done() вызов .done() запускается, когда наш запрос успешно возвращается. В рамках нашей функции обратного вызова мы начинаем с регистрации, что она успешно запустилась, а затем регистрируем, какой был ответ. Ответ от нашего Syncano CodeBox возвращает переменную res с ответом на данные.

Если мы запустим наше веб-приложение с этим кодом, оно покажет console.log() во всей своей красе:

Вывод консоли CodeBox в браузере

Теперь мы готовы улучшить этот CodeBox, чтобы дать нам некоторую полезную информацию, давайте прочитаем ее в наших последних запросах GitHub.

Подключение нашего CodeBox к GitHub

Чтобы заставить наш CodeBox читать из Github, нам нужно добавить несколько функциональных возможностей. Нам нужна способность:

  • Делать HTTP-запросы — мы будем использовать модуль узла request для этого в нашем CodeBox.
  • Сделайте HTTP-запрос к GitHub API. В частности, мы хотим получить pull-запросы.
  • Сообщите CodeBox наше имя пользователя GitHub и имя репо. Мы хотим, чтобы этот CodeBox мог повторно использоваться любым репозиторием GitHub кем угодно, поэтому мы устанавливаем их в качестве аргументов для нашего CodeBox.
  • Отфильтруйте эти запросы по метке. Мы хотим, чтобы у CodeBox была возможность запрашивать запросы с определенной меткой, поэтому мы устанавливаем это в качестве необязательного аргумента для нашего CodeBox. Мы будем использовать lodash узла lodash для просмотра данных.
  • Возвращайте заголовок, URL-адрес и метки для каждого запроса извлечения — это то, что мы будем отображать в нашем веб-приложении. Нам не нужны никакие другие данные.

Для этого наш CodeBox выглядит так:

 var request = require("request"), _ = require("lodash"), username = ARGS.POST.username, repo = ARGS.POST.repo, pullLabel = ARGS.POST.label; var options = { url: "https://api.github.com/repos/" + username + "/" + repo + "/issues?state=all", headers: { "User-Agent": "syncano-sample-pull-app" } }; if (!username || !repo) { console.log("Error: Need more info!"); return false; } request(options, function (error, response, body) { if (error) { console.log("Error: ", JSON.stringify(error)); } else if (!error && response.statusCode == 200) { var pulls = JSON.parse(body), returnValue = "["; _(pulls).forEach(function(pull) { var display = false; if (pullLabel) { if (_.filter(pull.labels, _.matches({"name": pullLabel})).length > 0) { display = true; } } else { display = true; } if (display) { returnValue += "{\"title\":\"" + pull.title + "\", \"url\":\"" + pull.html_url + "\", \"state\":\"" + pull.state + "\", \"labels\":" + JSON.stringify(pull.labels) + "},"; } }).value(); returnValue = returnValue.substring(0, returnValue.length - 1); returnValue += "]"; console.log(returnValue); } }); 

Наш CodeBox объяснил

CodeBox начинается с инструкций require для модулей request и lodash которые мы упоминали выше:

 var request = require("request"), _ = require("lodash"), 

Затем мы устанавливаем аргументы, которые может принимать наш CodeBox, используя формат ARGS.POST.theargumentname . Чтобы он мог получать аргументы вне запросов POST, вместо этого вы можете использовать ARGS.theargumentname .

 username = ARGS.POST.username, repo = ARGS.POST.repo, pullLabel = ARGS.POST.label; 

Затем мы начинаем настраивать наш HTTP-запрос, который мы хотим сделать, к GitHub. Мы настроили URL, который хотим отправить HTTP-запрос в API проблем GitHub . В моем собственном примере я ищу запрос https://api.github.com/repos/patcat/GreatestRepoOfAllTime/issues?state=all . Я установил для all так, чтобы как открытые, так и закрытые запросы на получение ответов проходили. Технически этот вызов будет извлекать как проблемы, так и запросы извлечения, поэтому мы могли бы переименовать заголовок в «Проблемы и запросы извлечения» на нашей странице, если бы захотели! Я оставил все как есть, так как в моем репо нет проблем.

 var options = { url: "https://api.github.com/repos/" + username + "/" + repo + "/issues?state=all", 

Другая важная опция для нашего HTTP-запроса — включить заголовок User-Agent, поскольку GitHub использует их для отслеживания того, откуда поступают вызовы. Вы можете называть свое как угодно, просто попытайтесь сделать его уникальным.

 headers: { "User-Agent": "syncano-sample-pull-app" } }; 

Если нашему CodeBox не было присвоено имя пользователя или имя репо в аргументах, он возвращает ошибку и не идет дальше.

 if (!username || !repo) { console.log("Error: Need more info!"); return false; } 

В противном случае мы запускаем HTTP-запрос, который мы определили выше. Если есть ошибка, она появится в переменной error . Мы обнаружим эту переменную и зарегистрируем ее. Если ошибок нет и мы получили успешный ответ HTTP 200, наш CodeBox продолжит интерпретацию полученных данных запроса на извлечение.

 request(options, function (error, response, body) { if (error) { console.log("Error: ", JSON.stringify(error)); } else if (!error && response.statusCode == 200) { 

Наши данные запроса на получение будут находиться в возвращаемой переменной body . Он представлен в виде строки JSON, поэтому мы разбираем его во что-то, что JavaScript может просматривать, и сохраняем его в переменной, называемой pulls . Мы также запускаем новую переменную с именем returnValue которой мы скомпилируем массив данных JSON, которые мы предоставим в результате тому, кто запускает CodeBox.

 var pulls = JSON.parse(body), returnValue = "["; 

Затем мы используем функцию forEach() модуля lodash, чтобы просмотреть каждый запрос на выборку, который возвращает GitHub, и поработать с ним:

 _(pulls).forEach(function(pull) { ... } 

В этой функции forEach() мы устанавливаем новую переменную с именем display которая будет определять, следует ли отображать каждый запрос на извлечение тому, кто запрашивал запросы на извлечение из CodeBox. Если у CodeBox есть аргумент pullLabel , он знает, что мы ищем результаты по одной конкретной метке. В этом случае он проходит по каждой из меток в pull.labels возвращаемых из GitHub, и, если есть какие-либо совпадения, он устанавливает этот запрос извлечения для отображения.

 var display = false; if (pullLabel) { if (_.filter(pull.labels, _.matches({"name": pullLabel})).length > 0) { display = true; } } 

В противном случае, если нет аргумента pullLabel , мы не фильтруем по pullLabel , и мы определенно хотим, чтобы этот запрос показывался.

 else { display = true; } 

После принятия решения о том, хотим ли мы отображать запрос на извлечение, мы проверяем эту переменную display и затем добавляем строку JSON к нашему returnValue с помощью pull.title , pull.state и pull.labels . pull.labels превращается в строку JSON, поскольку из GitHub может быть возвращено несколько меток, и мы хотим, чтобы они хорошо вписывались в возвращаемый нами JSON.

 if (display) { returnValue += "{\"title\":\"" + pull.title + "\", \"url\":\"" + pull.html_url + "\", \"state\":\"" + pull.state + "\", \"labels\":" + JSON.stringify(pull.labels) + "},"; } }).value(); 

returnValue как мы просмотрели каждый запрос на извлечение, мы удаляем последний символ из returnValue (это запятая, потому что каждый цикл запроса на добавление добавляется через запятую к этой строке), и затем мы закрываем массив объектов JSON.

 returnValue = returnValue.substring(0, returnValue.length - 1); returnValue += "]"; 

Чтобы завершить это и отправить эти данные, мы регистрируем их в консоли, чтобы они могли быть получены нашим веб-приложением.

 console.log(returnValue); } }); 

Обновление HTML нашего приложения

Код интерфейса нашего приложения довольно прост. Мы добавили несколько стилей, чтобы он выглядел немного чище, и мы обновили JavaScript, чтобы он выглядел так:

 (function() { $.ajax({ type: "POST", url: "https://api.syncano.io/v1/instances/YOUR-INSTANCE-NAME/webhooks/p/abcd/findpullrequests/", data: {"username":"patcat", "repo":"GreatestRepoOfAllTime", "label":"invalid"} }) .done(function(res) { var pulls = JSON.parse(res.result.stdout), pullsHTML = ""; for (var i = 0; i " + pulls[i].labels[j].name + ""; } pullsHTML += " " + pulls[i].title + stateHTML + " " } document.getElementById('pull-requests').innerHTML = pullsHTML; }); }()); 

Объясненные обновления нашего интерфейса JavaScript

Части CodeBox, которые были настроены:

Наша выполняющая функция CodeBox теперь имеет полезную нагрузку аргументов, которые мы хотим отправить в значении data — это позволяет нам запрашивать конкретное имя пользователя, хранилище и метку, от которой мы хотим получать запросы извлечения. Для моего собственного примера я показываю только запросы извлечения с именем «invalid»:

 data: {"username":"patcat", "repo":"GreatestRepoOfAllTime", "label":"invalid"} 

После успешного выполнения запроса мы анализируем строку JSON из ответа res.result.stdout нашего res.result.stdout (именно здесь можно найти ответ console.log ) и сохраняем его в переменной с именем pulls . Мы также создали переменную с именем pullsHTML для вывода HTML, который мы будем помещать на страницу.

 var pulls = JSON.parse(res.result.stdout), pullsHTML = ""; 

Подобно тому, как мы просматривали наш массив GitHub, но без lodash (вы могли бы вводить lodash в свой интерфейс, если хотите!), Мы перебираем каждый запрос на извлечение и отображаем его в виде ссылки. Если есть какие-либо ярлыки, мы также добавляем их в смесь. Мы также определяем состояние запросов на удаление с помощью класса, называемого pull-open или pull-closed .

 for (var i = 0; i < pulls.length; i++) { var stateHTML = ""; for (var j = 0; j < pulls[i].labels.length; j++) { stateHTML += "<div class=\"label\">" + pulls[i].labels[j].name + "</div>"; } pullsHTML += "<a class=\"pull pull-" + pulls[i].state + "\" href=\"" + pulls[i].url + "\" target=\"_blank\">" + pulls[i].title + stateHTML + "</a>" } 

Наконец, мы помещаем этот код в наш элемент #pull-requests на странице:

 document.getElementById('pull-requests').innerHTML = pullsHTML; 

В бою

Если мы посмотрим на мой репозиторий GitHub, который мы будем использовать в качестве примера, мы увидим четыре ожидающих запроса. Два из них помечены как недействительные, и один из недействительных запросов извлечения закрыт:

Наши четыре запроса GitHub

Если мы запустим наше веб-приложение, загрузив index.html , Syncano предоставит нашему приложению только два из запросов извлечения GitHub — два запроса, помеченные как недействительные. Один из запросов вычеркнут, который является частью стилизации для закрытого билета в моем примере CSS (вы можете стилизовать все приложение в любом случае или посмотреть демонстрационный код!).

Наше приложение в действии показывает недействительные запросы

Вывод

CodeBoxes и Syncano предоставляют действительно хороший и простой способ настройки модульной и многоразовой бессерверной платформы для ваших веб-приложений. Пример запроса на загрузку GitHub полностью работает на службе Syncano, только со статической HTML-страницей и некоторым базовым JavaScript для извлечения данных. Для тех, кто не слишком взволнован идеей создания бэкэнд-среды для вашего следующего проекта, Syncano и его CodeBox могут быть идеальным выбором.