在这篇文章中,我将研究一个非常简单的用例。 在执行部署管道时, FlexDeploy可能会产生一些应被批准或拒绝的人工任务。 例如,某人必须批准对生产环境的部署。 可以在FlexDeploy UI中或通过某些外部通信渠道来完成。 今天,我将重点介绍通过Slack批准/拒绝FlexDeploy人工任务的场景:
我想考虑一些要求和注意事项:
- 我不想教FlexDeploy与Slack通信
- 我不想向Slack提供FlexDeploy API的详细信息
- 我不想向公众公开FlexDeploy API
- 我确实希望能够轻松地将Slack更改为其他内容或添加其他通信工具,而无需接触FlexDeploy
基本上,我想使FlexDeploy与外部通信机制的细节脱钩。 因此,我将引入一个额外的层,即FlexDeploy和Slack之间的API 。 看起来无服务器范例是实现此API的一种非常有吸引力的方法。 今天,我将使用Azure Functions构建它,因为……为什么不呢?
因此,从技术上讲,该解决方案的Poc版本如下所示:
一旦出现新的人工任务,FlexDeploy会通知无服务器API有关提供内部任务ID和任务描述的API。 有一个SaveTask函数,将提供的任务详细信息以及生成的令牌(只是一些uid)保存到Azure Table存储中 。 该令牌具有到期时间,这意味着应该在该时间之前使用它来批准/拒绝任务。
const azure = require( 'azure-storage' ); const uuidv1 = require( 'uuid/v1' ); module.exports = async function (context, taskid) { var tableSvc = azure.createTableService( 'my_account' , 'my_key' ); var entGen = azure.TableUtilities.entityGenerator; var token = uuidv1(); var tokenEntity = { PartitionKey: entGen.String( 'tokens' ), RowKey: entGen.String(token), TaskId: entGen.String(taskid), dueDate: entGen.DateTime( new Date(Date.now() + 24 * 60 * 60 * 1000 )) }; tableSvc.insertEntity( 'tokens' ,tokenEntity, function (error, result, response) { }); return token; };
保存令牌后,将调用PostToSlack函数,将消息发布到Slack通道。 SaveTask和PostTo Slack函数被编排到一个持久函数 NotifyOnTask中 ,该函数实际上是由FlexDeploy调用的:
const df = require( "durable-functions" ); module.exports = df.orchestrator(function*(context){ var task = context.df.getInput() var token = yield context.df.callActivity( "SaveTask" , task.taskid) return yield context.df.callActivity( "PostToSlack" , { "token" : token, "description" : task.description}) });
Slack中的消息包含两个按钮来批准和拒绝任务。
这些按钮指向指向ActionOnToken持久功能的webhooks :
const df = require( "durable-functions" ); module.exports = df.orchestrator(function*(context){ var input = context.df.getInput() var taskId = yield context.df.callActivity( "GetTaskId" , input.token) if (input.action == 'approve' ) { yield context.df.callActivity( "ApproveTask" , taskId) } else if (input.action == 'reject' ) { yield context.df.callActivity( "RejectTask" , taskId) } });
ActionOnToken调用GetTaskId函数,通过给定令牌从存储中检索任务ID:
const azure = require( 'azure-storage' ); module.exports = async function (context, token) { var tableSvc = azure.createTableService( 'my_account' , 'my_key' ); function queryTaskID(token) { return new Promise(function (resolve, reject) { tableSvc.retrieveEntity( 'tokens' , 'tokens' , token, function (error, result, response) { if (error) { reject(error) } else { resolve(result) } }); }); } var tokenEntity = await queryTaskID(token); if (tokenEntity) { var dueDate = tokenEntity.dueDate._ if (dueDate > Date.now()) { return tokenEntity.TaskId._ } } };
完成此操作后,它要么通过调用要么批准或拒绝任务
ApproveTask或RejectTask函数。 这些功能依次调用FlexDeploy REST API。
const request = require( 'sync-request' ); const fd_url = ' http://dkrlp01.flexagon:8000 ' ; module.exports = async function (context, taskid) { var taskid = taskid; var res = request( 'PUT' , fd_url+ '/flexdeploy/rest/v1/tasks/approval/approve/' +taskid,{ }); };
我可以开始直接在云中开发无服务器应用程序
Azure Portal ,但是我决定实现所有功能并在本地使用它,然后再移至云中。 我可以做到这一点,在本地开发和测试功能的事实实际上非常酷,并不是每个无服务器平台都为您提供该功能。 我在云中配置的唯一内容是
带有表的Azure Table存储帐户,用于存储我的令牌和任务详细信息。
在本地开始使用Azure Functions的便捷方法是使用
Visual Studio Code作为开发工具。 我在Mac上工作,因此我下载并安装了Mac OS X版本。VS Code就是关于扩展的,对于与您一起使用的每种技术,您都将安装一个或几个扩展。 关于Azure函数也是如此。 有一个扩展:
完成此操作后,您将获得一个新选项卡,您可以在其中创建新的功能应用程序并开始实现您的功能:
在配置新项目时,向导会要求您选择一种语言,您希望该语言用于实现以下功能:
尽管我喜欢Java,但仍选择JavaScript是因为我想在常规函数之上实现持久性函数,并且它们支持C# ,
仅F#和JavaScript 。 在撰写本文时, JavaScript最接近我。
休息照常。 您可以创建函数,编写代码,调试,测试,修复,然后重新进行所有操作。 您只需单击F5,VS Code就可以在调试模式下启动整个应用程序:
首次启动该应用程序时,VS Code会建议您在计算机上安装函数运行时(如果该应用程序不存在)。 因此,基本上,假设您在笔记本电脑运行时上有了首选语言(Node.js),则只需要具有VS Code及其功能扩展即可开始使用Azure Functions 。 它将为您完成其余的安装。
因此,一旦应用程序启动,我就可以通过调用NotifyOnTask函数来对其进行测试,该函数将启动整个周期:
curl -X POST --data '{"taskid":"8900","description":"DiPocket v.1.0.0.1 is about to be deployed to PROD"}' -H "Content-type: application/json" http: //localhost:7071/api/orchestrators/NotifyOnTask
该应用程序的源代码可在GitHub上找到 。
好的,到目前为止, Azure Functions的总体观点是……这很好。 它只是工作。 到目前为止,在实施该解决方案时,我没有遇到任何烦人的问题(除了一些愚蠢的错误,因为我没有认真阅读本手册)。 我一定会继续在Azure Functions上进行发布和发布,以丰富该解决方案并将其迁移到云中,并可能实现一些不同的东西。
而已!
翻译自: https://www.javacodegeeks.com/2019/03/serverless-api-azure-functions.html