<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Live DevOps in Japan!</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/livedevopsinjapan/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/feed.xml</link>
    <description />
    <lastBuildDate>Tue, 23 Jan 2018 14:57:24 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Simulating 1000 agents using ACS, ACI, and Durable Functions - (1) ACI</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/simulating-1000-agents-using-acs-aci-and-durable-functions-1-aci</link>
      <pubDate>Tue, 23 Jan 2018 14:57:24 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2635</guid>
      <description><![CDATA[I did some experiment to simulate 1000 agents using several measures. I'd like to share some...]]></description>
      <content:encoded><![CDATA[I did some experiment to simulate 1000 agents using several measures. I'd like to share some learning and code in this post.

&nbsp;
<h1>Problem Overview</h1>
I wanted to simulate 1000 agents with cost effective way with the simplest solution.  Also, wanted to use .Net based technology as much as possible. In this case, How can we use Azure technologies?
On this experiment, I use ACI, ACS (Kubernetes with Go lang), Durable Functions.  This system is simple. Just want to printout when we've got a queue. They have 1000 client in on Premise. If possible we want to achieve less than 1 sec latency from sending message to the queue to store print state to the Storage Table.

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2018/01/StressTesting.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2018/01/StressTesting-1024x576.jpg" alt="" class="alignnone wp-image-2636" width="782" height="440" /></a>

The architecture is also simple. When customer want to print on a web server, send a message to Storage Queue. Then Azure Functions create data on a table storage. Print Agents are always polling the table storage. Once get a data, it print the data and sends a queue to Storage Queue. Then Azure Functions store the print status to the queue.
<h1>Simulator Candidates</h1>
Which technologies to use for this use case? Using a container is one idea. We use .Net framework this time, We convert it to the .NetCore then pack it using Visual Studio. You can refer <a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/visual-studio-tools-for-docker">Visual Studio Tools for Docker with ASP.NET Core</a>. We can use <a href="https://azure.microsoft.com/en-us/services/container-instances/?&amp;WT.srch=1&amp;WT.mc_id=AID631184_SEM_CSkwMHVP&amp;lnkd=Google_Azure_Brand&amp;gclid=EAIaIQobChMIxMzhneDq2AIVSZd-Ch1X4wqzEAAYASAAEgKUcPD_BwE">Azure Container Instances</a> or <a href="https://azure.microsoft.com/en-us/services/container-service/">Azure Container Service</a>. Also, <a href="https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-overview">Durable Functions </a>might be good since it has good orchestrator. I'm not sure if it fits for this use case, however, it worth trying. I can learn something at least.
<h1>Packing a docker image</h1>
Once you use Visual Studio Tools for Docker, Visual Studio automatically generate proper Dockerfile like this.

<em>Dockerfile</em>
<pre>FROM microsoft/dotnet:2.0-runtime AS base
WORKDIR /app

FROM microsoft/dotnet:2.0-sdk AS build
WORKDIR /src
COPY *.sln ./
COPY ClientAppNetCore/ClientAppNetCore.csproj ClientAppNetCore/
COPY CommonNetCore/CommonNetCore.csproj CommonNetCore/
RUN dotnet restore
COPY . .
WORKDIR /src/ClientAppNetCore
RUN dotnet build -c Release -o /app -c ClientAppNetCore.csproj

FROM build AS publish
RUN dotnet publish -c Release -o /app -c ClientAppNetCore.csproj

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ClientAppNetCore.dll"]</pre>
&nbsp;

It is using <a href="https://docs.docker.com/engine/userguide/eng-image/multistage-build/">multi staging build</a>, well created. All we need is to name it and push to public/private repository. If you want to push this one, move to the root directory which have *.sln file.
<pre>$ docker build . -f ClientAppNetCore/Dockerfile -t tsuyoshiushio/client:1.0.0 -t tsuyoshiushio/client:latest
$ docker push tsuyoshiushio/client:1.0.0
$ docker push tsuyoshiushio/client:latest</pre>
Now you are ready to use this agent simulator using docker. 'tsuyoshiushio' is my <a href="https://hub.docker.com/">DockerHub </a>repository name.
<h1>Azure Container Instance</h1>
This is the Serverless docker hosting service. If it works, it might be a very good solution. Since this client requires different environment variables for one by one containers, I need some code to control the containers. You can refer the whole source code on my GitHub. You can create containers quite easily.

First, Getting credentials for client
<pre> var credentials = SdkContext.AzureCredentialsFactory.FromServicePrincipal(clientId, clientSecret, tenantId, AzureEnvironment.AzureGlobalCloud);
 var client = new ContainerInstanceManagementClient(credentials);
 client.SubscriptionId = subsctiptionId;</pre>
Then configure container. Especially specify the resource you need.
<pre>var resources = new ResourceRequirements();
 var request = new ResourceRequests();
 request.Cpu = 0.2;
 request.MemoryInGB = 0.3; // once I tried 0.1 it cause a long execution time.

resources.Requests = request;
 
 var list = new List&lt;Container&gt;();
 for (int i = 0; i &lt; 5; i++)
 {
 list.Add(CreateClientContainer("DOCKERHUB_NAME/client", i, resources, $"{guid}-{i}"));
 }</pre>
Then create an instance.   On the actual code, I needed to deploy one more client called spammer. It sends a lot of queue. Once finished, I wanted to terminate. That is why I specify RestorePolicy = "Never".
<pre>await client.ContainerGroups.CreateOrUpdateAsync(resourceGroup, containerGroup,
 new ContainerGroup()
 {
 Containers = list,
 Location = location,
 OsType = "Linux",
 RestartPolicy = "Never" // try not to emit the message by restarting
 }
 );</pre>
This must be the best solution for this time! Very easy! However, it wasn't I can't generate enough performance for this. Since this is preview, we have some limitation.
By default, Container Group limitation is 20 for a subscription. Number of container per container group is 60. We can deploy 1200 containers by default. The biggest problem is container create 60 per hour. I can't create 1000 container. obviously. I needed to contact support service to expand the quotas. However, I'm not sure if we can try 1000 containers since this is preview. This is totally great for "Serverless" solution. However, I needed to give up this time.
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/azure/container-instances/container-instances-quotas">Quotas and region availability for Azure Container Instances</a></li>
 	<li><a href="https://github.com/TsuyoshiUshio/AzureContainerInstanceSample">Source Code (GitHub)</a></li>
</ul>
However, operating ACI with C# is very easy! We can use it for a lot of purposes!
<h1>Conclusion</h1>
ACI interface is very good and easy to operate using Azure SDK. However, it have some quota limitation. That is why, I give up this time. However ACI is very good tool to create a some containers with serverless architecture!

I ask the support to expand it, if I can do it, I'll edit this blog.

On the next blog, I'm talking about the k8s with go lang strategy to achieve this issue.
<h1>Resource</h1>
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/docker/visual-studio-tools-for-docker">Visual Studio Tools for Docker with ASP.NET Core</a></li>
</ul>
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/azure/container-instances/container-instances-quotas">Quotas and region availability for Azure Container Instances</a></li>
 	<li><a href="https://github.com/TsuyoshiUshio/AzureContainerInstanceSample">Sample Source Code (GitHub)</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Azure Functions dynamic queue message routing for Storage Queue and Service Bus samples</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/azure-functions-dynamic-queue-message-routing-for-storage-queue-and-service-bus-samples</link>
      <pubDate>Tue, 26 Dec 2017 14:49:49 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2615</guid>
      <description><![CDATA[Azure Functions bindings is super cool feature. However, I wanted to dynamically route the queue in...]]></description>
      <content:encoded><![CDATA[Azure Functions bindings is super cool feature. However, I wanted to dynamically route the queue in run time.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/2017-12-26_23h01_23.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/2017-12-26_23h01_23.png" alt="" class="alignnone size-full wp-image-2616" width="1017" height="682" /></a>

I want to queue to the agent_1 queue for Agent One, and the agent_2 queue for Agent Two. Azure Functions already has this functionality called <strong>Binder</strong>.
This is the function comes WebJobs. Until recently, we only have a documentation on webjobs GitHub. However, now we have it as the Azure Function documentation!

Let's try it. We can use IBinder interface and <strong>BindAsync&lt;T&gt;()</strong> method. However, problem is, we might not know which Class can we choose for type T. I'd like to share which class can we user for this purpose. One of the biggest pain of this issue is, there is no error if you use a wrong type for T. It looks success however, there are no queue has been emitted.

I'd like to share some successful scenarios. This function trigged by the "acceptprint" queue then send queue message to "agent_1" or "agent_2" queue according to the AgentId value.
<h1>Service Bus Queue</h1>
<pre> [FunctionName("RequestHandler")]
 public async static Task RunAsync([ServiceBusTrigger("acceptprint", AccessRights.Manage, Connection = "ServiceBus:Connection")]string myQueueItem,  TraceWriter log, IBinder binder)
 {
   var myQueueItemObject = JsonConvert.DeserializeObject&lt;PrintSpool&gt;(myQueueItem);
   var serviceBusQueueAttribute = new ServiceBusAttribute($"agent_{myQueueItemObject.AgentId}", AccessRights.Manage);
   serviceBusQueueAttribute.Connection = "ServiceBus:Connection";
   var queueMessageJson = JsonConvert.SerializeObject(myQueueItemObject);
   var outputMessages = await binder.BindAsync&lt;IAsyncCollector&lt;string&gt;&gt;(serviceBusQueueAttribute);
    await outputMessages.AddAsync(queueMessageJson);
}</pre>
According to the <a href="https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-service-bus#output">Service Bus output bindings</a> page, we can use these class as type T
<ul>
 	<li>T (some class which can JSON serialize)</li>
 	<li>string</li>
 	<li>byte[]</li>
 	<li>BrokeredMessage</li>
 	<li>ICollector&lt;T&gt; or IAsyncCollector&lt;T&gt;</li>
</ul>
However, we can't use T, string, byte[] and BrokerMessage as  type T in this case. BrokeredMessage doesn't have setter for message body.  I saw a sample for blob storage to use TextWriter or Stream. However, it works with no-error but it doesn't actually work. I recommend to use ICollector&lt;T&gt; or IAsyncCollector&lt;T&gt; in this case.
<h1>Storage Queue</h1>
I also tried Storage Queue. It was easy. I found a sample in this page. Although it is for Webjobs.
<ul>
 	<li><a href="https://github.com/Azure/azure-webjobs-sdk/wiki/Queues">https://github.com/Azure/azure-webjobs-sdk/wiki/Queues</a></li>
</ul>
<pre> var queueAttribute = new QueueAttribute($"agent{myQueueItemObject.AgentId}");
 queueAttribute.Connection = "BlobStorage:Connection";
 var outputQueue = await binder.BindAsync&lt;CloudQueue&gt;(queueAttribute);
 await outputQueue.AddMessageAsync(new CloudQueueMessage(queueMessageJson));</pre>
NOTE:  Service Bus can't use '_' as a queue name.

According to the <a href="https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-storage-queue#output">Storage Queue output bindings</a> page,  we can use there class as type T
<ul>
 	<li> JSON serializable POCO</li>
 	<li>string</li>
 	<li>byte[]</li>
 	<li>CloudQueueMessage</li>
 	<li>ICollector&lt;T&gt; or IAsyncCollector&lt;T&gt;</li>
 	<li>CloudQueue</li>
</ul>
In this case, we have several choice. Cloud Queue Messages, ICollector&lt;T&gt; or IAsyncCollector&lt;T&gt;
<h1>Blob Storage</h1>
I also dynamically change the blob name to store. I need to store pdf file. However, I want to decide the pdf file name in run time. We can also use Binder in this case as well.
<pre>// Upload to the Blob Storage
 var guid = Guid.NewGuid();
 var path = $"doc/{guid.ToString()}.pdf";
 var blobAttribute = new BlobAttribute(path, FileAccess.Write);
 blobAttribute.Connection = "BlobStorage:Connection";
 
 using (var writer = await binder.BindAsync&lt;Stream&gt;(blobAttribute))
 {
  await writer.WriteAsync(pdfBytes, 0, pdfBytes.Length);
 }</pre>
According to the <a href="https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-storage-blob#input--output">Blob Storage input-output bindings</a>, we can use these types.
<ul>
 	<li>out string</li>
 	<li>TextWriter</li>
 	<li>Stream</li>
 	<li>ICloudBlob</li>
 	<li>CloudBlockBlob</li>
 	<li>CloudPageBlob</li>
 	<li>CloudAppendBlob</li>
</ul>
I use Stream for this time. In this case, Stream or TextWriter might be handy. :)

2017/12/18 added

The Azure document team update this section. This is very useful for dynamic binding. :)
<ul>
 	<li><a href="https://review.docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library?branch=pr-en-us-30091">Binding at runtime</a></li>
</ul>
&nbsp;

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Azure Functions CI/CD pipeline for Node.js using VSTS</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/azure-functions-cicd-pipeline-for-node-js-using-vsts</link>
      <pubDate>Wed, 13 Dec 2017 11:59:35 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2475</guid>
      <description><![CDATA[In this blog post, I'd like to share how to create CI/CD pipeline for Azure Functions (Node.js). I...]]></description>
      <content:encoded><![CDATA[In this blog post, I'd like to share how to create CI/CD pipeline for Azure Functions (Node.js). I can find several posts for C#. However, we can't find it for Node.js.  I'd like to share some knowledge as a tutorial style to build whole pipeline.
<h1>Sample Project</h1>
You can find a sample project on the GitHub.  It includes source code, test code, package.json and exported file from my build / release definition. You can import the same CI/CD pipeline as me.

<a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode">https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode</a>
<h2>Prerequisite</h2>
<ul>
 	<li><a href="https://www.visualstudio.com/team-services/">Visual Studio Team Services account</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function">Azure Functions Function App</a></li>
</ul>
Now you are ready to start this tutorial.
<h1>Configure Build definition</h1>
<h2>Project structure</h2>
If you don't need extra package for your Azure Functions, you don't need package.json. However, if you want to add extra packages, execute unit testing, and static analysis, I recommend to have a package.json on your FunctionApp directory.  The sample package structure on the github is like this.
<pre>.
├── Pipelines
│   ├── Node.CI.json
│   ├── Node.Release.json
│   └── build.yaml
├── README.md
├── Scheduler
│   ├── function.json
│   ├── index.js
│   └── sample.dat
├── Tests
│   └── scheduler.spec.js
├── Worker
│   ├── function.json
│   ├── index.js
│   ├── readme.md
│   └── sample.dat
├── build.yaml
├── host.json
├── local.settings.json
├── package-lock.json
└── package.json</pre>
The sample  project have two functions.  Scheduler and Worker.  Scheduler get an request by HttpTrigger and pass the value to the QueueBindings. Worker receives Queue then emit a log message. Simple functions.  Tests directory include unit test for the functions.

&nbsp;
<h2>Import build definition</h2>
For your convenience, I export my Build/Release definition and put on my GitHub. You can import the definition on your VSTS account.
<h3>Clone my GitHub repo</h3>
You can find the sample GitHub repo in <a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode">here</a>.  Clone this repo.
<pre>git clone git@github.com:TsuyoshiUshio/AzureFunctionsCICDForNode.git</pre>
<h3>Select Builds then push Import button</h3>
<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Build01.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Build01-1024x334.png" alt="" class="alignnone wp-image-2536" width="763" height="249" /></a>
<h3>Import definition</h3>
Select Browse... button and select NodeCI.json file on my GitHub account.

You can find Pipelines/NodeCI.json on the repo which you cloned.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Build02.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Build02.png" alt="" class="alignnone wp-image-2546" width="439" height="237" /></a>
<h3>Configure source</h3>
You need to define repo which is the sample code is stored. e.g. You can folk <a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode">my repository</a> or push some other git repository then specify the repo.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Build03.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Build03-1024x502.png" alt="" class="alignnone wp-image-2555" width="599" height="294" /></a>
<h3>Select Hosted VS2017 Agent</h3>
Finally, select  Hosted &gt; Hosted VS2017. Now done the configuration, you can save &amp; queue the pipeline, also you can see the detail of the definition. Enjoy!

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Build04.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Build04-1024x506.png" alt="" class="alignnone wp-image-2567" width="479" height="237" /></a>

It works

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Build05.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Build05-1024x538.png" alt="" class="alignnone wp-image-2565" width="480" height="252" /></a>

&nbsp;
<h2>Build definition overview</h2>
<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-7.04.17-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-7.04.17-PM-635x1024.png" alt="" class="alignnone wp-image-2487" width="357" height="575" /></a>

I'd like to expand the detail of the pipeline. It has these steps.
<ol>
 	<li>Restore npm packages</li>
 	<li>Unit testing</li>
 	<li>Static Analysis</li>
 	<li>Bundle functions</li>
 	<li>Archive and publish</li>
</ol>
<h3>1.Restore npm packages</h3>
The sample package.json includes these packages.  It includes some packages for testing, linting and security checking.

<a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode/blob/master/package.json"><em>package.json</em></a>
<div>
<pre><span> </span><span>"dependencies"</span><span>: {</span>
<span> </span><span>"express"</span><span>: </span><span>"^4.16.2"</span>
<span> },</span>
<span> </span><span>"devDependencies"</span><span>: {</span>
<span> </span><span>"azure-functions-pack"</span><span>: </span><span>"^0.3.1"</span><span>,</span>
<span> </span><span>"chai"</span><span>: </span><span>"^4.1.2"</span><span>,</span>
<span> </span><span>"eslint"</span><span>: </span><span>"^4.13.1"</span><span>,</span>
<span> </span><span>"eslint-config-standard"</span><span>: </span><span>"^11.0.0-beta.0"</span><span>,</span>
<span> </span><span>"eslint-plugin-import"</span><span>: </span><span>"^2.8.0"</span><span>,</span>
<span> </span><span>"eslint-plugin-node"</span><span>: </span><span>"^5.2.1"</span><span>,</span>
<span> </span><span>"eslint-plugin-promise"</span><span>: </span><span>"^3.6.0"</span><span>,</span>
<span> </span><span>"eslint-plugin-standard"</span><span>: </span><span>"^3.0.1"</span><span>,</span>
<span> </span><span>"mocha"</span><span>: </span><span>"^4.0.1"</span><span>,</span>
<span> </span><span>"mocha-junit-reporter"</span><span>: </span><span>"^1.15.0"</span><span>,</span>
<span> </span><span>"nsp"</span><span>: </span><span>"^3.1.0"</span><span>,</span>
<span> </span><span>"sinon"</span><span>: </span><span>"^4.1.3"</span>
<span> }</span></pre>
</div>
On the VSTS, we have npm task with install Command. Then all npm packages are restored. It create node_modules package on the package root directory.
<h3>2.  Unit Testing</h3>
Writing Unit Testing for Azure Fucntions (Node.js) is not so difficult. Azure Functions has two parameter, one is <strong>context</strong> and the other is <strong>req</strong>. You just mock it using json object and check the value of output bindings. You can use <a href="https://sinonjs.org/">Sinon.JS</a> for if the some functions has been called.

&nbsp;

<a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode/blob/master/Tests/scheduler.spec.js"><em>scheduler.spec.js</em></a>
<div>
<pre><span>'use strict'</span>

<span>const</span><span> </span><span>Scheduler</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'../Scheduler/index.js'</span><span>)</span>
<span>const</span><span> </span><span>expect</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'chai'</span><span>).</span><span>expect</span>
<span>const</span><span> </span><span>sinon</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'sinon'</span><span>);</span>

<span>describe</span><span>(</span><span>'Scheduler function'</span><span>, () </span><span>=&gt;</span><span> {</span>
<span>  var</span><span> </span><span>req</span><span> </span><span>=</span><span> {};</span>
<span>  var</span><span> </span><span>context</span><span> </span><span>=</span><span> {};</span>

<span> </span><span>beforeEach</span><span>(</span><span>function</span><span>() {</span>
<span>   </span><span>req</span><span> </span><span>=</span><span> {</span>
<span>     </span><span>query:</span><span> {</span>
<span>       </span><span>name:</span><span> </span><span>"Azure"</span>
<span>     },</span>
<span>     </span><span>body:</span><span> {</span>
<span>       </span><span>name:</span><span> </span><span>"taro"</span>
<span>     }</span>
<span>   };</span>

<span> </span><span>context</span><span> </span><span>=</span><span> {</span>
<span>   </span><span>res:</span><span> {</span>
<span>     </span><span>status:</span><span> </span><span>200</span>
<span>   },</span>
<span>   </span><span>log:</span><span> </span><span>function</span><span> (</span><span>str</span><span>) {</span>
<span>     </span><span>console</span><span>.</span><span>log</span><span>(</span><span>str</span><span>); </span><span>// eslint-disable-line no-console</span>
<span>   },</span>
<span>   </span><span>bindings:</span><span> {</span>
<span>     </span><span>outputQueueItem:</span><span> </span><span>"fake_queue_value"</span>
<span>   },</span>
<span>   </span><span>done:</span><span> </span><span>function</span><span> () {</span>
<span>   }</span>
<span> };</span>
<span> });</span>

<span> </span><span>it</span><span>(</span><span>'should pass query name to queue bindings'</span><span>, (</span><span>done</span><span>) </span><span>=&gt;</span><span> {</span>
<span>   </span><span>sinon</span><span>.</span><span>spy</span><span>(</span><span>context</span><span>, </span><span>"done"</span><span>);</span>
<span>   </span><span>Scheduler</span><span>(</span><span>context</span><span>, </span><span>req</span><span>);</span>
<span>   </span><span>expect</span><span>(</span><span>context</span><span>.</span><span>bindings</span><span>.</span><span>outputQueueItem</span><span>).</span><span>to</span><span>.</span><span>equal</span><span>(</span><span>"Azure"</span><span>, </span><span>"Queue isn't set"</span><span>);</span>
<span>   </span><span>expect</span><span>(</span><span>context</span><span>.</span><span>done</span><span>.</span><span>called</span><span>).</span><span>to</span><span>.</span><span>be</span><span>.</span><span>true</span>
<span>   </span><span>context</span><span>.</span><span>done</span><span>.</span><span>restore</span><span>();</span>
<span>   </span><span>done</span><span>();</span>
<span> }) </span>

<span> </span><span>it</span><span> (</span><span>'should be ok if the query name has been passed'</span><span>, (</span><span>done</span><span>) </span><span>=&gt;</span><span> {</span>
<span>   </span><span>Scheduler</span><span>(</span><span>context</span><span>, </span><span>req</span><span>);</span>
<span>   </span><span>expect</span><span>(</span><span>context</span><span>.</span><span>res</span><span>.</span><span>body</span><span>).</span><span>to</span><span>.</span><span>equal</span><span>(</span><span>"Hello Azure"</span><span>);</span>
<span>   </span><span>done</span><span>();</span>
<span> })</span>

<span> </span><span>it</span><span> (</span><span>'should not be ok if the query name isnt supplied'</span><span>, (</span><span>done</span><span>) </span><span>=&gt;</span><span> {</span>
<span>   </span><span>req</span><span> </span><span>=</span><span> {</span>
<span>     </span><span>query:</span><span> {</span>
<span>     },</span>
<span>     </span><span>body:</span><span> {</span>
<span>     }</span>
<span>   };</span>
<span>   </span><span>Scheduler</span><span>(</span><span>context</span><span>, </span><span>req</span><span>);</span>
<span>   </span><span>expect</span><span>(</span><span>context</span><span>.</span><span>res</span><span>.</span><span>status</span><span>).</span><span>to</span><span>.</span><span>equal</span><span>(</span><span>400</span><span>);</span>
<span>   </span><span>expect</span><span>(</span><span>context</span><span>.</span><span>res</span><span>.</span><span>body</span><span>).</span><span>to</span><span>.</span><span>equal</span><span>(</span><span>"Please pass a name on the query string or in the request body"</span><span>);</span>
<span>   </span><span>done</span><span>();</span>
<span>   })</span>
<span>})</span></pre>
</div>
&nbsp;

I'm using <a href="https://www.npmjs.com/package/mocha-junit-reporter">mocha-junit-reporter</a> for export the test result. On the <a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode/blob/master/package.json">package.json</a> you can see the definition
<div>
<pre><span> </span><span>"report"</span><span>: </span><span>"mocha Tests/*.spec.js --reporter mocha-junit-reporter"</span><span>,</span></pre>
</div>
<div>On the pipeline, I simply call this script using npm task. It will create test-results.xml on the FunctionApp root directory.  Then using Publish Test Results task, you can push the result to the VSTS. Then you can see the test result on the VSTS.</div>
<div></div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-7.58.19-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-7.58.19-PM-1024x398.png" alt="" class="alignnone wp-image-2495" width="757" height="294" /></a></div>
<div></div>
<div></div>
<h3>3. Static Analysis</h3>
This step is optional. I use <a href="https://github.com/nodesecurity/nsp">nsp </a>for security checking. If the npm packages has <span>vulnerabilities, it stop the build.</span> <a href="https://eslint.org/">ESLint </a>for liniting. I just call these script by npm tasks.
<div>
<pre><span> </span><span>"security-check"</span><span>: </span><span>"nsp check"</span><span>,</span>
<span> </span><span>"lint"</span><span>: </span><span>"eslint ."</span></pre>
</div>
<h3>4. Bundle functions</h3>
This section is very important for performance. If you use npm packages with node_modules directory, it might cause a performance issue. It leads a long cold start time of a function. You can avoid this problem using <a href="https://github.com/Azure/azure-functions-pack">azure-functions-pack</a> packages. This package make a lot of files of a function with a lot of dependencies into single file just this command.
<div>
<pre><span> </span><span>"pack"</span><span>: </span><span>"funcpack pack ."</span><span>,</span></pre>
</div>
It create a .funcpack directory. It includes  a single fine which bundle all dependencies.  It improve a performance a lot.

On the pipeline,
<ol>
 	<li>Install Azure Functions Pack (npm task)</li>
 	<li>Exec funcpack pack . (npm task)</li>
 	<li>Delete node_modules ( Delete Files task)</li>
 	<li>Delete Tests directory ( Delete Files task)</li>
</ol>
This pipeline remove node_modules and Tests directory. It is not needed for deploy to azure after you use funcpack. Remove these.
<h3>5. Archive and publish</h3>
If you want to publish your functions to azure, you need to archive it using zip.  In this pipeline, I copy whole file to the $(Build.ArtifactStagingDirectory)/functionapp directory (Copy Files task), then Archive it (Archive files) into FunctionApp.zip file.  If you want to deploy Function App, you need to uncheck the "Prefix root folder name to archive paths" check box. If selected, the root folder name will be prefixed to the file paths within the archive.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.25.56-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.25.56-PM-1024x563.png" alt="" class="alignnone wp-image-2496" width="775" height="426" /></a>

Then publish the zip file to the drop directory. using Publish Artifact task. Then you can refer it from the Release definition.  If you enabled Continuous Integration on the Triggers tab, VSTS automatically start this pipeline when the new change introduced on your repo.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.32.07-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.32.07-PM.png" alt="" class="alignnone wp-image-2497" width="390" height="314" /></a>
<h1>Configure Release definition</h1>
<h3>Create a slot on your FunctionApp</h3>
Before starting the configuration, Let's create deployment slot. If you don't need the deployment slot, you can skip this step. However, if you use it, it might be very good way to deploy functions. Once you deploy to the Deployment slot, you can test it without affect to the production, once it becomes OK then swap it. Then the slot application turn into production with zero-downtime.  Go to the Function App on your azure, click Slots. Then create a slot.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.37.49-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.37.49-PM.png" alt="" class="alignnone wp-image-2505" width="559" height="359" /></a>
<h3>Deploy to the slot</h3>
Using the Azure App Service Deploy task, 1. Select your Subscription, App Type (Function App), App Service Name(Your Function App name). Then 2. Select Resource Group and slot name. Finally 3. Select the zip file which you created on the Build definition.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.44.03-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.44.03-PM-1024x547.png" alt="" class="alignnone wp-image-2515" width="614" height="328" /></a>

Then I add Manual Intervention to review the deployment. However it is optional.
<h3>Swap Slot</h3>
Swap slot is almost the same as the Deploy task. It swaps the slot into production.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.50.00-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.50.00-PM-1024x434.png" alt="" class="alignnone size-large wp-image-2516" width="1024" height="434" /></a>

You can configure Continuous deployment if you like.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.53.10-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.53.10-PM.png" alt="" class="alignnone size-full wp-image-2525" width="945" height="369" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.53.39-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-12-at-8.53.39-PM.png" alt="" class="alignnone size-full wp-image-2526" width="317" height="121" /></a>
<h2>Import Release definition (Optional)</h2>
You can also import release definition from my <a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode">GitHub</a>

You can find the Release Definition file on the repo. Just import Pipelines/Node.Release.json

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Release01.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Release01-1024x331.png" alt="" class="alignnone wp-image-2575" width="482" height="156" /></a>

Then you can configure the pipeline according to your environment.

Select The Hosted VS2017 agent

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Release-06.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Release-06-1024x475.png" alt="" class="alignnone wp-image-2576" width="446" height="207" /></a>

Change configuration  when you see the messages colored red.

You can select your own environment. like FunctionApp, Resource Group.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Release07.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Release07-1024x535.png" alt="" class="alignnone wp-image-2595" width="501" height="262" /></a>

For the manual intervention task, please change the approver.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Release05.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Release05-1024x526.png" alt="" class="alignnone wp-image-2586" width="414" height="213" /></a>
<h1>Conclusion</h1>
Now you have done advanced CI/CD pipeline with VSTS.  You can do Continuous Deployment using Function App feature, however, if you use VSTS push deployment model, you can control the pipeline more.
<h2>Tips</h2>
<ul>
 	<li>Use VSTS for complex pipeline</li>
 	<li>Zip your FunctionApp to deploy it</li>
 	<li>funckpack it to avoid performance issue</li>
 	<li>Unit Testing with Mock object and frameworks</li>
 	<li>Use Azure App Service Deploy task</li>
 	<li>Use Swap Slot for Blue Green Deployment</li>
</ul>
I hope you enjoy this post.
<h1>Resource</h1>
<ul>
 	<li><a href="https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode">https://github.com/TsuyoshiUshio/AzureFunctionsCICDForNode (Sample GitHub Repo)</a></li>
 	<li><a href="https://www.visualstudio.com/team-services/">Visual Studio Team Services account</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function">Azure Functions Function App</a></li>
 	<li><a href="https://github.com/nodesecurity/nsp">nsp</a></li>
 	<li><a href="https://eslint.org/">ESLint</a></li>
 	<li><a href="https://github.com/Azure/azure-functions-pack">azure-functions-pack</a></li>
 	<li><a href="https://www.npmjs.com/package/mocha-junit-reporter">mocha-junit-reporter</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Azure Functions v2 C# Script Async sample with SendGrid</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/azure-functions-v2-async-sample-with-sendgrid</link>
      <pubDate>Mon, 04 Dec 2017 21:15:03 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2446</guid>
      <description><![CDATA[I wanted to use Send Grid with Async method. However, all of the example on the Internet aim for...]]></description>
      <content:encoded><![CDATA[I wanted to use Send Grid with Async method. However, all of the example on the Internet aim for Sync method. I'd like to introduce how to write it.

Note, this example is for Azure Functions V2.
<h1>Prerequisite</h1>
You need FunctionApp with V2 and SendGrid extension. After creating a FunctionApp then go to portal. Then you can change the Runtime version. For the SendGrid extension, click the "Integrate", then choose SendGrid as out put bindings. Then it ask you if you install the SendGrid extension. Just install it.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-04-at-12.57.42-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-04-at-12.57.42-PM-1024x666.png" alt="" class="alignnone size-large wp-image-2455" width="1024" height="666" /></a>
<h1>Code</h1>
Azure Functions V2 for the C# Script we can see a lot of changes. It has several change from V1.  SendGrid provide Mail class now it is SendGridMessage class. Also, the HttpRequestMessage truns into Microsoft.AspNetCore.Mvc.HttpRequest. Return value is from HttpResponseMessage into IActionResults .

I can't find any example for Async functions for C# Script for V2, however, I just make it Async and returns Task&lt;IActionResults&gt;.

&nbsp;

Why it changed? The Azure Functions V2 uses ASP.NET Core MVC. You can refer this.

&nbsp;

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/actions

<strong><em>run.csx</em></strong>

&nbsp;
<div>
<div>
<pre><span>#r </span><span>"Newtonsoft.Json"</span>

<span>#r </span><span>"SendGrid"</span>

<span>using</span><span> </span><span>System</span><span>.</span><span>Net</span><span>;</span>

<span>using</span><span> </span><span>Microsoft</span><span>.</span><span>AspNetCore</span><span>.</span><span>Mvc</span><span>;</span>

<span>using</span><span> </span><span>Microsoft</span><span>.</span><span>Extensions</span><span>.</span><span>Primitives</span><span>;</span>

<span>using</span><span> </span><span>Newtonsoft</span><span>.</span><span>Json</span><span>; </span>

<span>using</span><span> </span><span>SendGrid</span><span>.</span><span>Helpers</span><span>.</span><span>Mail</span><span>; </span>

<span>using</span><span> </span><span>System</span><span>.</span><span>Text</span><span>;</span>

<span>public</span><span> </span><span>async</span><span> </span><span>static</span><span> </span><span>Task</span><span>&lt;</span><span>IActionResult</span><span>&gt; </span><span>Run</span><span>(</span><span>HttpRequest</span><span> req, </span><span>IAsyncCollector</span><span>&lt;</span><span>SendGridMessage</span><span>&gt; messages, </span><span>TraceWriter</span><span> log)</span>

<span>{</span>

<span> </span><span>log</span><span>.</span><span>Info</span><span>(</span><span>"SendGrid message"</span><span>); </span>

<span> </span><span>using</span><span> (</span><span>StreamReader</span><span> reader </span><span>=</span><span> </span><span>new</span><span> </span><span>StreamReader</span><span>(</span><span>req</span><span>.</span><span>Body</span><span>, </span><span>Encoding</span><span>.</span><span>UTF8</span><span>))</span>

<span> {</span>

<span> </span><span>var</span><span> body </span><span>=</span><span> </span><span>await</span><span> </span><span>reader</span><span>.</span><span>ReadToEndAsync</span><span>();</span>

<span> </span><span>var</span><span> message </span><span>=</span><span> </span><span>new</span><span> </span><span>SendGridMessage</span><span>();</span>

<span> </span><span>message</span><span>.</span><span>AddTo</span><span>(</span><span>"tsushi@microsoft.com"</span><span>);</span>

<span> </span><span>message</span><span>.</span><span>AddContent</span><span>(</span><span>"text/html"</span><span>, </span><span>body</span><span>);</span>

<span> </span><span>message</span><span>.</span><span>SetFrom</span><span>(</span><span>"iot@alert.com"</span><span>);</span>

<span> </span><span>message</span><span>.</span><span>SetSubject</span><span>(</span><span>"[Alert] IoT Hub Notrtification"</span><span>);</span>

<span> </span><span>await</span><span> </span><span>messages</span><span>.</span><span>AddAsync</span><span>(</span><span>message</span><span>); </span>

<span> </span><span>return</span><span> (</span><span>ActionResult</span><span>)</span><span>new</span><span> </span><span>OkObjectResult</span><span>(</span><span>"The E-mail has been sent."</span><span>);</span>

<span> }</span>

<span>}</span></pre>
</div>
<strong><em>function.json</em></strong>

</div>
<div></div>
<div>
<div>
<pre><span>{</span>

<span> </span><span>"bindings"</span><span>: [</span>

<span> {</span>

<span> </span><span>"authLevel"</span><span>: </span><span>"function"</span><span>,</span>

<span> </span><span>"name"</span><span>: </span><span>"req"</span><span>,</span>

<span> </span><span>"type"</span><span>: </span><span>"httpTrigger"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"in"</span>

<span> },</span>

<span> {</span>

<span> </span><span>"name"</span><span>: </span><span>"$return"</span><span>,</span>

<span> </span><span>"type"</span><span>: </span><span>"http"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"out"</span>

<span> },</span>

<span> {</span>

<span> </span><span>"type"</span><span>: </span><span>"sendGrid"</span><span>,</span>

<span> </span><span>"name"</span><span>: </span><span>"messages"</span><span>,</span>

<span> </span><span>"apiKey"</span><span>: </span><span>"SendGridAttribute.ApiKey"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"out"</span>

<span> }</span>

<span> ],</span>

<span> </span><span>"disabled"</span><span>: </span><span>false</span>

<span>}</span></pre>
</div>
</div>
<div></div>
<div>You can also specify the e-mail settings on the function.json like this.</div>
<div></div>
<pre>{
 "bindings": [
 {
 "authLevel": "function",
 "name": "req",
 "type": "httpTrigger",
 "direction": "in"
 },
 {
 "name": "$return",
 "type": "http",
 "direction": "out"
 },
 {
 "type": "sendGrid",
 "name": "messages",
 "apiKey": "SendGridAttribute.ApiKey",
 "to": "some@e-mail.com",
 "from": "iot@alert.com",
 "subject": "IoT Humidity Alert",
 "direction": "out"
 }
 ],
 "disabled": false
}</pre>
<div></div>
<div></div>
<h1>Resource</h1>
<ul>
 	<li><a href="https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/azure-functions/functions-bindings-sendgrid.md">Azure Functions SendGrid bindings</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp">Azure Functions C# script developer reference</a></li>
 	<li><a href="https://msdn.microsoft.com/en-us/library/hh137813(v=vs.110).aspx">Stream.ReadAsync Method (Byte[], Int32, Int32)</a></li>
 	<li><a href="https://msdn.microsoft.com/en-us/library/system.text.encoding(v=vs.110).aspx">Encoding Class</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/actions">Handling requests with controllers in ASP.NET Core MVC</a></li>
</ul>
<div></div>
<div></div>]]></content:encoded>
    </item>
    <item>
      <title>CI / CD pipeline for VSTS market place extension for k8s</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/ci-cd-pipeline-for-vsts-market-place-extension-for-k8s</link>
      <pubDate>Mon, 04 Dec 2017 01:04:27 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2357</guid>
      <description><![CDATA[I have a project called Kubernetes extension for VSTS.  You can use it on the VSTS Market...]]></description>
      <content:encoded><![CDATA[I have a project called <a href="https://github.com/TsuyoshiUshio/KubernetesTask">Kubernetes extension</a> for VSTS.  You can use it on the VSTS Market place.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-2.54.23-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-2.54.23-PM-1024x217.png" alt="" class="alignnone size-large wp-image-2365" height="217" width="1024" /></a>

These days, official Kubernetes Task has been released. So I added advanced feature.
<ul>
 	<li>Separate download and execution of the task</li>
 	<li>Helm support</li>
 	<li>Istio support</li>
 	<li>k8s deployment (not only for ACS and AKS but others)</li>
</ul>
The implementation is very simple, however, I need full attention when I release it. I just start as my hobby project, however, now I have 320 uses. Some may use in production. I did it manually, as a DevOps guy, I wanted to automate it. However, I have some obstacles for that.
<ul>
 	<li>Integration testing with k8s cluster.  However, I developed on a Windows machine.</li>
 	<li>How can I test the extension installation for a vsts account?</li>
 	<li>Long Build Time (13 min) for CI. Release is more than that.</li>
 	<li>Over size issue of vsix file</li>
</ul>
In this blog post, I'd like to share how I solve this problems. If you have better solution, please let me know.
<h1>Strategy</h1>
I started with coming up with a strategy how to test it. I can publish the VSTS task automatically however, I'd like to test before the publish. Also, After install the extension, I need to test on a k8s cluster.  My idea is
<ol>
 	<li>Create a VSTS account</li>
 	<li>CI pipeline for build, unit test, archive artifact with zip and push to drop folder (Hosted Agent)</li>
 	<li> Release pipeline, uninstall/re-install all tasks (Hosted Agent)</li>
 	<li> Release pipeline, Integration testing (Hosted Linux Agent with AKS)</li>
 	<li>Approval process</li>
 	<li>Release pipeline, Build/Publish to the Marketplace</li>
</ol>
I'll explain whole process with some tips
<h1>1. Create a VSTS account</h1>
When I created the pipeline the first time, I create a project for this extension with a VSTS account. However, in this case, it cause a problem. The VSTS account has other projects. It uses VSTS tasks. VSTS extension/tasks deployment is for a VSTS account not for a VSTS project. Which means when I deploy a broken version, it will affect to the projects. I decided to create a new VSTS account only for this purpose.
<h1>2. CI pipeline for build, unit test, archive artifact with zip and push to drop folder (Hosted Agent)</h1>
I have a several tips for this section. I thought it must be very easy since I did it via command line with manually. It must be just make it pipeline! I was wrong. :)  Let's have a look at the pipeline.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-3.27.43-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-3.27.43-PM-741x1024.png" alt="" class="alignnone size-large wp-image-2366" height="1024" width="741" /></a>

<a href="https://github.com/TsuyoshiUshio/KubernetesTask">Source Repo: https://github.com/TsuyoshiUshio/KubernetesTask</a>

You can see the whole source code of the Kubernetes Task on the repo. Also, I include some command on the package.json file.
<pre> "scripts": {
 "pretest": "tsc -p .",
 "test": "mocha ./Tests/L0.js ./Tests/L1.js ./Tests/L2.js",
 "report": "tsc -p .&amp; mocha ./Tests/L0.js ./Tests/L1.js ./Test/L2.js --reporter mocha-junit-reporter",
 "deploy": "deploy.bat",
 "build": "tfx extension create --manifest-globs vss-extension.json"
},</pre>
This is not good practice. lol. However, when I wrote this, I'm a newbie of node and typescript. However these configuration works. I decided use this time.  then I'll refactor it in the future. I'll execute these commands. The point is, VSTS task is node application however, a lot of people using TypeScript. I love TypeScript as well.  You need to care something if you use TypeScript for CI / CD pipeline.
<h2>2.1. Preparation tasks</h2>
Before starting the unit testing, we need to install several tools.
<h3>npm install (npm)</h3>
Display name: npm install

Command: install
<h3>install typescript (npm)</h3>
Display name: install typescript

Command: custom

Command and arguments: install typescript@2.1.5 --global-style

<strong>NOTE</strong>: I try to use --global however, it didn't work. When I tried it, tsc 1.4.0 is enabled. I also try to set the PATH environment variables, however, it should be set on the task feature.
<h3>install tfx-cli command (npm)</h3>
Display name: install tfx-cli command

Command: custom

Command and arguments: install tfx-cli@v0.4.11 --global
<h2>2.2. Unit Test and Refresh node_modules</h2>
When I created the CI pipeline for the first time, one of the biggest issue was, the size of the artifact. It was very big. When I release it, I caught this error.
<div>
<pre><span>##vso[task.logissue type=error;]error: Failed Request: Bad Request(400) - The extension package size '69988355 bytes' exceeds the maximum package size '20971520 bytes'</span></pre>
</div>
<div></div>
<div>Why! I try to experiment which part matters. I clone the repo on my Mac, I realized it.</div>
<div></div>
<pre>$ du -h node_modules/
         :
 22M node_modules//typescript
         :
 39M node_modules//typings
         : 
 65M node_modules/</pre>
<div></div>
<div>We need to remove typings and typescript package for the production. However, we need to compile ts files to js files. Ideally, if I can install tsc command with --global option, I can do it but it doesn't work. tsc 1.4.0 is already installed and it becomes valid. Also, I'd like to remove development dependency like mocha and chai, I decided to remove node_modules after the test, then re-install the npm packages. It might be best practice. If you know better idea, please let me know.</div>
<div></div>
<div>FYI: If I dont' install TypeScript and development dependencies, the effect is obvious.</div>
<div></div>
<pre>$ du -h node_modules/
       :
1.1M node_modules/</pre>
<h3>npm report (npm)</h3>
Display name: npm report

Command: custom

Command and arguments: run report

NOTE: this command compile ts file , unit testing, and reporting.
<h3>Delete files (npm)</h3>
Display name: Delete files from

Contents: node_modules
<h3>npm custom (npm)</h3>
Display name: npm custom

Command: custom

Command and arguments: install --production

<strong>NOTE:</strong> Install only production dependencies.
<h3>Publish Test Results and test-results.xml (Publish Test Results)</h3>
Display name: Publish Test Results and test-results.xml

Test result format: JUnit

Test results files: test-results.xml

Search folder: $(System.DefaultWorkingDirectory)
<h3>npm run deploy(npm)</h3>
Display name: npm run deploy

Command: custom

Command and arguments: run deploy

<strong>NOTE</strong>: This extension has 6 tasks. I need to copy js file and node_modules to each task directories.
<h2>2.3. Archive it!</h2>
At the first time, the CI build took 13+ min. Because of a big sized, and a lot of files. I archive it before the upload. then build time becomes 3 min. It is massive improvement. It also take a lot of time for release pipeline. Now, it is 2.3 min even if I enabled debugging option.
<h3>Archive files (Archive Files)</h3>
Display name: Archive files

Root folder(or file) to archive: $(System.DefaultWorkingDirectory)

Prefix root folder name to archive paths: true

Archive type: zip

Archive file to create: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip

Replace existing archive: true
<h3>Publish Artifact: drop(Publish Build Artifacts)</h3>
Display name: Publish Artifact: drop

Path to publish: $(Build.ArtifactStagingDirectory)

Artifact name: drop

Artifact publish location : Visual Studio Team Services/TFS
<h2>2.4. Continuous Integration and Badge</h2>
I checkout the source from GitHub. I wanted to have a badge for CI status.  for enable it, you can refer this section.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.24.02-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.24.02-PM.png" alt="" class="alignnone size-full wp-image-2377" height="350" width="706" /></a>

Just add the URL on your README.md

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.24.18-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.24.18-PM-1024x384.png" alt="" class="alignnone size-large wp-image-2385" height="384" width="1024" /></a>

&nbsp;
<h1>3. Release pipeline, uninstall/re-install all tasks (Hosted Agent)</h1>
<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.22.25-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.22.25-PM-1024x478.png" alt="" class="alignnone size-large wp-image-2376" height="478" width="1024" /></a>

Now you are ready for Integration testing. I add one private Git repository on VSTS. It includes yaml file for testing kubernetes tasks.
<h2>3.1. Install</h2>
If you publish the extension, it will be valid for the all uses. I need to delete/install whole tasks only on this VSTS account. Simply I delete / add whole tasks.  I use Hosted agent. (windows)

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.28.12-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.28.12-PM-1024x541.png" alt="" class="alignnone size-large wp-image-2386" height="541" width="1024" /></a>
<h3>Extract files(Extract Files)</h3>
Display name: Extract files

Archive file patterns: *.zip

Destination folder: .
<h3>npm custom(npm)</h3>
Display name: npm custom

Command: custom

Working folder with package.json: s

Command and arguments: tfx-cli@v0.4.11 --global

<strong>NOTE</strong>: If you use Archive files task, it will be extracted "s" folder.

<strong>Delete apply task(Command Line)</strong>

Display name: Delete apply task

Tool: tfx

Arguments: build tasks delete -t YOUR_PERSONAL_ACCESS_TOKEN_HERE -u https://k8sexp.visualstudio.com/DefaultCollection --task-id 9bf07640-ed9b-11e6-8ac1-6b0636b1490f

<strong>NOTE</strong>: <span style="color: #ff0000">If you create an presonal access token, Please choose "All accessible accounts" for Account. The default value is only valid for the vsts account. Which means you can't right to deploy it into market place.</span>

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.36.16-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.36.16-PM-1024x245.png" alt="" class="alignnone size-large wp-image-2395" height="245" width="1024" /></a>
<h3>Upload apply task(Command Line)</h3>
Display name: Upload apply task

Tool: tfx

Arguments: build tasks upload -t YOUR_PERSONAL_ACCESS_TOKEN_HERE -u https://k8sexp.visualstudio.com/DefaultCollection --task-path apply --overwrite

: continue the same settings.
<h2>3.2.  Test</h2>
I use "Hosted Linux Preview". These tasks are only for Linux preview.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.42.32-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.42.32-PM-1024x369.png" alt="" class="alignnone size-large wp-image-2405" height="369" width="1024" /></a>

Then, you need to configure the connection string for AKS cluster, then you can any integration test you want using the tasks.
When you need any file for testing, you can include the private repo of VSTS.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.43.15-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.43.15-PM-1024x178.png" alt="" class="alignnone size-large wp-image-2407" height="178" width="1024" /></a>

&nbsp;
<h2>3.3. Deploy</h2>
<a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.47.36-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-4.47.36-PM.png" alt="" class="alignnone size-full wp-image-2417" height="410" width="766" /></a>
<h3>Extract files (Extract Files)</h3>
Display name: Extract files

Archive file patterns: *.zip

Destination folder: .
<h3>Install tfx-cli(npm)</h3>
Display name: Install tfx-cli

Command: custom

Command and arguments: install tfx-cli@v0.4.11 --global
<h3>Build vsix file(npm)</h3>
Display name: Build vsix file

Command: custom

Working folder with package.json: $(System.DefaultWorkingDirectory)/s

Command and arguments: run  build
<h3>Publish VSTS Extension: $(System.DefaultWorkingDirectory)/s/*.vsix(Publish VSTS Extension)</h3>
Display name: Publish VSTS Extension: $(System.DefaultWorkingDirectory)/s/*.vsix

VSIX path: $(System.DefaultWorkingDirectory)/s/*.vsix

Service Endpoint: YOU_NEED_CONFIGURE_YOUR_ENDPOINT

Install Tfx-cli: true

Tfx Location: $(Agent.WorkFolder)\Tools

If you've got this error, please check the PAT is the "All accessible account"
<div>
<pre><span>##vso[task.logissue type=error;]error: Received response 401 (Not Authorized). Check that your personal access token is correct and hasn't expired.</span></pre>
<h1>Conclusion</h1>
<div>Now it works. Next step is refactoring this CI/CD pipeline, also I'd like to enable Release note automation on GitHub.</div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.00.40-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.00.40-PM-1024x428.png" alt="" class="alignnone size-large wp-image-2425" height="428" width="1024" /></a></div>
</div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.00.23-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.00.23-PM.png" alt="" class="alignnone size-full wp-image-2426" height="379" width="619" /></a></div>
<div>Updated.</div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.02.23-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/Screen-Shot-2017-12-03-at-5.02.23-PM-1024x348.png" alt="" class="alignnone size-large wp-image-2427" height="348" width="1024" /></a></div>
<div></div>
<h1>Resource</h1>
<ul>
 	<li><a href="https://github.com/Microsoft/tfs-cli">https://github.com/Microsoft/tfs-cli</a></li>
 	<li><a href="https://github.com/TsuyoshiUshio/KubernetesTask">Kubernetes extension</a></li>
</ul>
<div></div>
<div></div>]]></content:encoded>
    </item>
    <item>
      <title>Migration tips from IaaS to Web App for Containers on Azure</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/migration-tips-from-iaas-to-web-app-for-containers-on-azure</link>
      <pubDate>Fri, 13 Oct 2017 02:17:36 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2205</guid>
      <description><![CDATA[Web App for Containers  is a very good service to migrate from IaaS world to the fully-managed...]]></description>
      <content:encoded><![CDATA[<a href="https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-intro">Web App for Containers </a> is a very good service to migrate from IaaS world to the fully-managed container world.  Without considering about the infrastructure, the PaaS platform  provide Scaling feature and DevOps related tips like Continuous Deployment, Blue Green Deploy and Monitoring.  This service is very good for a user who uses IaaS with OSS stack. It is very simple. If you need to handle complex situation, you might need to go orchestrator like <a href="https://azure.microsoft.com/en-us/services/container-service/">Azure Container Service</a>. However, if you don't need it, Simply you just want to use docker to pack your IaaS.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-12.56.53-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-12.56.53-AM-1024x501.png" alt="" width="769" height="376" class="alignnone wp-image-2207" /></a>

I noticed that this use case could be like a crossroad. Someone who familiar with WebApps but not for container might use this. Also, someone who is good at container but not WebApp might be interested this solution.  If you are someone like them, you might like this post.
<h1>Tips 1.  Make sure your container doesn't exit.</h1>
My colleague said that "Hey, I create a docker image from a docker image for local development environment. It works on my Mac, however, once deployed on the Web App for Containers, It doesn't seem to work. Why".  You can check if your docker image doesn't exit after docker run.  For example, if you start Nginx as a back ground process on the docker image and execute docker run, then the docker container start nginx daemon internarlly then exit it.  You might specify startup.sh script on the Dockerfile. However, if the startup.sh script should not be finished. If it finish, docker run finish as well. It might happen on your Web App for Containers. Then you can't find a good log on the Web App logs.  You can test it on your PC like this.
<pre>docker run -d -p 80:80 docker_image_name
docker ps</pre>
If your docker process can't find,  then your docker container finished on the Web App for Container.  The solution is try to stop the shell script like this. You can add this line on your startup.sh
<pre>tail -f /dev/null</pre>
Then the shell stop on the line, so the docker container keeps alive.  But why it worked on locally?  This time the case was like this. They start /bin/bash at the end of the startup.sh and they run the docker image like this.
<pre>docker -itd docker_image_name -p 80:80</pre>
-it means interactive mode. At the end of the startup.sh exec the /bin/bash. It starts bash. Which means the container keep on running until you exit from the container. However, if you deploy it to WebApp for Containers, it runs it without -itd option.  This tips is very common tips for container users. However, someone new to container might trapped.
<h1>Tips 2. How to specify the port number?</h1>
When you open the Azure Portal, you can't find where to specify the PORT. docker run command have -p option. How the Web App for Container decide the port number? The answer is, the port number is automatically detected for you. However once it doesn't work, you can specify the port number on the App Settings on the portal.
<p style="margin: 0in;font-family: segoe-ui_normal;font-size: 12.0pt;color: #222222"><a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.20.07-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.20.07-AM-1024x356.png" alt="" width="949" height="330" class="alignnone wp-image-2216" /></a></p>
<p style="margin: 0in;font-family: segoe-ui_normal;font-size: 12.0pt;color: #222222">For more detail, Please refer https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-faq</p>
<p style="margin: 0in;font-family: segoe-ui_normal;font-size: 12.0pt;color: #222222">  <a href="https://msdnshared.blob.core.windows.net/media/2017/10/Slide1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Slide1.jpg" alt="" width="564" height="317" class="alignnone wp-image-2225" /></a></p>
<p style="margin: 0in;font-family: segoe-ui_normal;font-size: 12.0pt;color: #222222">The image is like this. The port number should be the port number inside of the container. Web App for Container will generate random port number as the port number outside of the container. Also it is exposed to the server. The Load Balancer dispatch the request (http/https) to the random port number. It is also route into the nginx which reside on the container. You can see the acutualy docker run command on the portal. See Advanced Tools.  You can find the log from the Bash script on the Advanced Tools called Kudu.</p>
<p style="margin: 0in;font-family: segoe-ui_normal;font-size: 12.0pt;color: #222222"><a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.49.39-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.49.39-AM.png" alt="" width="197" height="178" class="alignnone wp-image-2236" /></a></p>

<h1>Tips 3. Chrome for Mac users</h1>
If you use Mac, I recommend to use chrome not safari. If you use safari and open the Kudu, you might can't type a letters. Chrome works fine.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.48.16-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.48.16-AM-1024x633.png" alt="" width="400" height="247" class="alignnone wp-image-2235" /></a> &lt;- not works. :)

&nbsp;
<h1>Tips 4. When it deploy container to the Web App for Containers?</h1>
We can configure the docker image to deploy howerver, when it happens. The first time your configure it, it automatically deployed to the Web App. If you update the image on the registory, when it will be upgraded?

I have two answers.

When you stop the server then start the server, the web app will get the new image form the registry. If you just restart the server, it won't fetch the new image from the registry.
However, once you specify the Continuous Deployment, if the registry has been changed, it will automatically deployed.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.53.54-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-1.53.54-AM-1024x601.png" alt="" width="567" height="333" class="alignnone wp-image-2245" /></a>

But what if you want to control the deployment timing? I'll answer on the CI/CD section.
<h1>Tips 5.  Debugging the container</h1>
At the first time, old container user like me, might feel that the Web App for Container is very hard to debug.  Because we can't use docker exec or docker logs to the Web App for Containers. Then how to debug the container?

As I said, you can use the Advanced tool (kudu).  However, you might want to see it on your local PC. Then you can use <a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest">Azure CLI</a>.  The tool written by python, you can install on your PC, you can use docker image, also, you can use it on the Azure Portal console.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.08.39-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.08.39-AM.png" alt="" width="340" height="95" class="alignnone wp-image-2255" /></a>

If you keep on watching the Web App for Containers log, you can use this command.
<pre> az webapp log tail --name your_web_app_name -g your_resource_group_name</pre>
Also, if you want to watch some logs of the middleware, you can use this technique. Just link to the stdout/stderr. Then you can see the output on the command. This is the example of the Nginx log.
<pre><span style="color: #1a1a1a"># forward request and error logs to docker log collector
 RUN </span><span style="color: #a32c1f">ln</span><span style="color: #1a1a1a"> -sf /dev/stdout /var/log/nginx/access.log \
         &amp;&amp; </span><span style="color: #a32c1f">ln</span><span style="color: #1a1a1a"> -sf /dev/stderr /var/log/nginx/error.log</span></pre>
<h1><span>Tips 6. Use SSH for debugging</span></h1>
Someone who comes from Docker world, enabling ssh.d on the container is the wrong practice. However, Web App for Container world, it is a best practice. You might surprise it. The reason why is if you add ssh.d can be a security hole. However, on the Web App for Container world, you can only ssh to the container from the Web App Server and Only one port is allow to expose. Now you can ssh from the Portal also, you can even execute sudo command on the container. It is very helpful to debug it. To enable it, you can refer this document.
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-ssh-support">SSH support for Azure Web App for Containers</a></li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.15.05-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.15.05-AM-1024x371.png" alt="" width="751" height="272" class="alignnone wp-image-2285" /></a>

&nbsp;
<h1>Tips 7. Keep Docker image small</h1>
Some people comes from IaaS world to Container, you might choose a base docker image like CentOS or Ubuntu. I don't recommend it. Because it's size is too big.

My customer's image was 1.8GB with CentOS base image. Instead, I use Alpine based image with 279MB. Also, I decompose the parts and make it simple then it becomes around 108MB. The image size matters. It consume a lot of time to build/deploy it. So I recommend to create a simple small image using container optimized image like alpine. Docker official image like nginx, php is already optimized. You can refer and learn from the Dockerfile of these images if you want to customize it. Also, docker image should be small service with single responsibility. You can't run a lot of daemons on single docker container. decompose it. It will help to simplify and easy to maintain your Dockerfile.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.21.56-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.21.56-AM-1024x865.png" alt="" width="478" height="404" class="alignnone wp-image-2256" /></a>

If you build/push your docker image locally, you might find it consume a lot of disk space. you can clean up via this command. It will remove all unused containers, volumes, and images.
<pre>$ docker system prune -a</pre>
&nbsp;
<h1>Tips 7. 403 fobbiden on Nginx</h1>
You might encounter, 403 forbidden if you just move config files from the current environment. for example,  You might see this log.
<pre>"/usr/share/nginx/html/abc/app/index.html" is forbidden (13: Permission denied), client: 172.19.0.1, server: *.xxxx.jp, request: "GET / HTTP/1</pre>
Web App for Containers 's domain is <em>your_web_app_name.azurewebsites.net</em> . If you leave the configuration on your nginx.conf, the requested server_name does not much the server_name. It causes 403.

&nbsp;
<pre>server {

     listen              80; 

    server_name         *.xxxxx.jp;</pre>
&nbsp;
<h1>Tips 8. SSL/TLS is configured</h1>
If you configure SSL on your nginx on your container, just remove it. The Web App for Containers look after it.  Serverside SSL certificate is already installed on the Web App for Containers. You don't need to buy it.

Also, even if you specify "WEBSITES_PORT = 443", you can't route SSL to your container directory. The load balancer do the SSL offloading. The load balancer pass your request as a plain http request to the container.  If you want to specify, your own serverside certificate, you can do it. If so, don't forget to configure the Custom Domain.  Also, if you want to use client certificate, you can refer <a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth">this article</a>.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Slide2.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Slide2.jpg" alt="" width="519" height="292" class="alignnone wp-image-2265" /></a>

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.44.49-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.44.49-AM-1024x495.png" alt="" width="726" height="351" class="alignnone wp-image-2275" /></a>

&nbsp;
<h1>Tips 9. Blue Green Deployment with VSTS</h1>
If you use Azure, I recommend to use <a href="https://www.visualstudio.com/team-services/">Visual Studio Team Services</a> for enabling Continuous Integration / Continuous Delivery (CI/CD).  Especially if you have a lot of manual process to build/deploy, this service helps you very well. I really love it. Visual Studio Team Service (VSTS) sounds like Visual Studio specific tool. However, it is totally great tool for open source docker guy as well. My customer who is running Ruby with Container, <a href="https://microsoft.github.io/techcasestudies/devops/2017/04/13/xenodata.html">they deployed their apps to the GCP platform by the VSTS</a>. Because it is very easy to configure and very good speed without configuring build agent. If you use Jenkins, you need to create a Build machine in somewhere. However, if you use VSTS, you don't need it. Also, VSTS include Git repository and Kanban with great Release management feature. One of the very good point is the integration with Azure. If you packed your app into container, you can create CI/CD pipeline very easily with decent control.

Once you create a Dockerfile and push into the git of the VSTS, you can configure build definition with Docker very easily.  You can create a build pipeline to enable build docker file and push to your registry in a few minutes.  All you need is just choose the subscription and registry. It was deadly easy! You can use "Hosted Linux" as an agent. VSTS automatically launch Linux VM with VSTS agent with docker.
<h2>Build Pipeline</h2>
You can choose a lot of build pipeline templates

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.58.47-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.58.47-AM-1024x538.png" alt="" width="487" height="256" class="alignnone wp-image-2295" /></a>

If you try docker, please choose Hosted Linux Preview for Agent

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.59.13-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-2.59.13-AM-1024x540.png" alt="" width="495" height="261" class="alignnone wp-image-2305" /></a>

Then choose the environment of yours.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-3.00.27-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-3.00.27-AM-1024x539.png" alt="" width="476" height="250" class="alignnone wp-image-2306" /></a>
<h2>Adding Subscription (Optional)</h2>
If you need to access other subscriptions, you can configure new endpoint.  just click "Manage" link the next to the Azure subscription. All need to know is <a href="https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest">Service Principal. </a> If you use your own subscription, you don't need this operation.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.34.11-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.34.11-AM.png" alt="" width="228" height="203" class="alignnone wp-image-2317" /></a>

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.34.25-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.34.25-AM-1024x703.png" alt="" width="411" height="282" class="alignnone wp-image-2325" /></a>

On the target subscription, you can try this command.
<pre><span class="hljs-keyword">az</span><span> </span><span class="hljs-keyword">ad</span><span> </span><span class="hljs-keyword">sp</span><span> create-for-rbac</span><span class="hljs-parameter"> --name</span><span> {appId}</span><span class="hljs-parameter"> --password</span><span> </span><span class="hljs-string">"{strong password}"</span><span> </span></pre>
Then you'll get the service principal. App(Client) ID, Password, Tenant Id, Subscription ID (You can see on your Azure Portal). Then fill this form. You can test the configuration with the "Verify connection" link.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.35.30-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-10.35.30-AM-1024x1012.png" alt="" width="443" height="438" class="alignnone wp-image-2335" /></a>
<h2>Release Pipeline</h2>
Also, I come up with how to handle the blue green deployment using Web App for Containers and VSTS.  One of the difficulty is we can't decide the timing of the deployment. However, If we have a deployment slot for blue green deployment (Web App can use Blue Green Deployment using Deployment slot), when the Web App pull the images?

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Slide31.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Slide31.jpg" alt="" width="569" height="320" class="alignnone wp-image-2355" /></a>

&nbsp;

I want to control it. However, if we configure continuous deployment, it always update the latest image. One of the simple idea is like this. On the release, you just create a pipeline Stop WebApp -&gt; Start WebApp -&gt; Manual Intervention -&gt; Swap Slots. Stop/Start Web App cause a pull new image from your registry. You don't need to enable the continuous deployment option. Then You can enable blue green deployment quite easily.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-3.12.16-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-13-at-3.12.16-AM-1024x514.png" alt="" width="741" height="372" class="alignnone wp-image-2315" /></a>
<h1>Conclusion</h1>
I just share nine tips for Web App for Containers.  I hope this post helps. :)
<h1>Resource</h1>
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-intro">Introduction to Azure Web App for Containers</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-faq">https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-faq</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest">Azure CLI 2.0</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/app-service/app-service-web-configure-tls-mutual-auth">How To Configure TLS Mutual Authentication for Web App</a></li>
 	<li><a href="https://microsoft.github.io/techcasestudies/devops/2017/04/13/xenodata.html">A DevOps hackfest helps xenodata lab migrate from GCP to Azure and enable automated deployment</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/app-service/containers/app-service-linux-ssh-support">SSH support for Azure Web App for Containers</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest">Create an Azure service principal with Azure CLI 2.0</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Enabling Typescript local debugging with Azure Functions on Mac</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/enabling-typescript-local-debugging-with-azure-functions-on-mac</link>
      <pubDate>Wed, 11 Oct 2017 09:13:53 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2166</guid>
      <description><![CDATA[I love typescript. I'd love to write typescript with Azure Functions.  However, TypeScript support...]]></description>
      <content:encoded><![CDATA[I love typescript. I'd love to write typescript with Azure Functions.  However, TypeScript support for Azure Functions is preview on Portal.

I'd like to develop Azure Functions with typescript with local debugging. Even if my Mac Book Pro.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-5.44.37-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-5.44.37-PM-1024x694.png" alt="" width="767" height="520" class="alignnone  wp-image-2175" /></a>

This was very easy. :) So I'd love to share it.
<h1>Prerequisite</h1>
Install the Azure Functions CLI (core)

Also NodeJS. I recommend 8.x for this purpose. I tried on my Mac.
<h1>Create Functions with TypeScript</h1>
<h2>Create a Function App</h2>
<pre>$ func init
Writing .gitignore
Writing host.json
Writing local.settings.json
Created launch.json

Initialized empty Git repository in /Users/ushio/Codes/AzureFunctions/some/.git/</pre>
<h2>Create Functions</h2>
<div class="code-frame">
<div class="highlight">
<pre>$ func new
Select a language: 
1. C#
2. JavaScript
Choose option: 2
JavaScript
Select a template: 
1. BlobTrigger
2. HttpTrigger
3. QueueTrigger
4. TimerTrigger
Choose option: 2
HttpTrigger
Function name: [HttpTriggerJS] 
Writing /Users/ushio/Codes/AzureFunctions/some/HttpTriggerJS/index.js
Writing /Users/ushio/Codes/AzureFunctions/some/HttpTriggerJS/sample.dat
Writing /Users/ushio/Codes/AzureFunctions/some/HttpTriggerJS/function.json
</pre>
</div>
</div>
Now, you can get a template.
<h2>Setup Typescript enviornment</h2>
This is just include TypeScript configuration.
<pre>cd HttpTriggerJS
npm init
tsc --init
cp index.js index.ts</pre>
Then Change your index.ts like this.
<pre>export async function run (context: any, req: any) {</pre>
&nbsp;
<h2>Change typeconfig.json</h2>
Then change the typeconfig.json Uncomment the sourceMap and add lib entry.
<pre><span class="p">{</span>
  <span class="nt">"compilerOptions"</span><span class="p">:</span> <span class="p">{</span>
    <span class="err">/*</span> <span class="err">Basic</span> <span class="err">Options</span> <span class="err">*/</span>                       
    <span class="nt">"target"</span><span class="p">:</span> <span class="s2">"ES2015"</span><span class="p">,</span>                          <span class="err">/*</span> <span class="err">Specify</span> <span class="err">ECMAScript</span> <span class="err">target</span> <span class="err">version:</span> <span class="err">'ES3'</span> <span class="err">(default),</span> <span class="err">'ES5',</span> <span class="err">'ES2015',</span> <span class="err">'ES2016',</span> <span class="err">'ES2017',</span> <span class="err">or</span> <span class="err">'ESNEXT'.</span> <span class="err">*/</span>
    <span class="nt">"module"</span><span class="p">:</span> <span class="s2">"commonjs"</span><span class="p">,</span> 
    "sourceMap": true,  
                   <span class="err">/*</span> <span class="err">Specify</span> <span class="err">module</span> <span class="err">code</span> <span class="err">generation:</span> <span class="err">'commonjs',</span> <span class="err">'amd',</span> <span class="err">'system',</span> <span class="err">'umd'</span> <span class="err">or</span> <span class="err">'es2015'.</span> <span class="err">*/</span>
    <span class="nt">"lib"</span><span class="p">:</span> <span class="p">[</span> <span class="s2">"es2015"</span><span class="p">],</span>   

</pre>
Now your Azure Function can use TypeScript with Local Debugging.

&nbsp;

For example, I wrote a function like this. This code is typescript code for querying Cosmos DB.  No call back hell! This is just a sample code. You can write much more simple one.

I'm not sure however, when I use "documentdb-typescript", don't need context.done().

<em>index.ts</em>

&nbsp;
<div>
<pre><span>import</span><span> </span><span>*</span><span> </span><span>as</span><span> </span><span>DB</span><span> </span><span>from</span><span> </span><span>"documentdb-typescript"</span><span>;</span>

<span>import</span><span> { </span><span>Collection</span><span> } </span><span>from</span><span> </span><span>"documentdb-typescript"</span><span>;</span>

<span>export</span><span> </span><span>async</span><span> </span><span>function</span><span> </span><span>run</span><span> (</span><span>context</span><span>:</span><span> </span><span>any</span><span>, </span><span>req</span><span>:</span><span> </span><span>any</span><span>) {</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>'JavaScript HTTP trigger function processed a request.'</span><span>);</span>

<span> </span><span>let</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>process</span><span>.</span><span>env</span><span>[</span><span>"COSMOS_DB_HOST"</span><span>];</span>

<span> </span><span>let</span><span> </span><span>key</span><span> </span><span>=</span><span> </span><span>process</span><span>.</span><span>env</span><span>[</span><span>"COSMOS_DB_KEY"</span><span>];</span>

<span> </span><span>let</span><span> </span><span>coll</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>new</span><span> </span><span>Collection</span><span>(</span><span>"car"</span><span>,</span><span>"cardb"</span><span>,</span><span>url</span><span>, </span><span>key</span><span>).</span><span>openOrCreateDatabaseAsync</span><span>();</span>

<span> </span><span>let</span><span> </span><span>state</span><span> </span><span>=</span><span> </span><span>context</span><span>.</span><span>bindingData</span><span>.</span><span>state</span><span>;</span>

<span> </span><span>if</span><span> (</span><span>state</span><span> </span><span>===</span><span> </span><span>"approved"</span><span> </span><span>||</span><span> </span><span>state</span><span> </span><span>===</span><span> </span><span>"pending"</span><span> </span><span>||</span><span> </span><span>state</span><span> </span><span>===</span><span> </span><span>"rejected"</span><span> ) {</span>

<span> </span><span>let</span><span> </span><span>allDocs</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>coll</span><span>.</span><span>queryDocuments</span><span>({</span>

<span> </span><span>query:</span><span> </span><span>"select * from car c where c.state = @state order by c.name desc"</span><span>,</span>

<span> </span><span>parameters:</span><span>[{</span><span>name:</span><span> </span><span>"@state"</span><span>, </span><span>value:</span><span> </span><span>state</span><span> }]},</span>

<span> {</span><span>enableCrossPartitionQuery:</span><span> </span><span>true</span><span>, </span><span>maxItemCount:</span><span> </span><span>10</span><span>}).</span><span>toArray</span><span>();</span>

<span> </span><span>context</span><span>.</span><span>res</span><span> </span><span>=</span><span> {</span>

<span> </span><span>body:</span><span> </span><span>allDocs</span>

<span> }</span>

<span> } </span><span>else</span><span> {</span>

<span> </span><span>context</span><span>.</span><span>res</span><span> </span><span>=</span><span> {</span>

<span> </span><span>status:</span><span> </span><span>400</span><span>,</span>

<span> </span><span>body:</span><span> </span><span>"Please pass the correct state! State is only allowed ( approved | pending | rejected )"</span>

<span> };</span>

<span> }</span>

<span> </span><span>// context.done();</span>

<span>};</span></pre>
</div>
<div></div>
<div>Once you compile this functions by</div>
<div></div>
<pre>tsc -p .</pre>
<div></div>
<div>You'll find index.map.js file. It is mapping between ts and js files.</div>
<div></div>
<div><a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-6.01.46-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-6.01.46-PM.png" alt="" width="167" height="70" class="alignnone size-full wp-image-2185" /></a></div>
&nbsp;
<h1>Debugging</h1>
Now you can debug your TypeScript functions locally! Start your functions with debug flag.
<pre class="p1"><span class="s1">$ func host start --debug VSCode</span></pre>
<p class="p1">Then start debug with your VS Code.</p>
<p class="p1">You can see the debug port on the log.</p>

<pre class="p1"><span class="s1"><span class="Apple-converted-space">      </span>Start Process: node<span class="Apple-converted-space">  </span>--inspect=5858 "/Users/ushio/.azurefunctions/bin/workers/Node/dist/src/nodejsWorker.js" --host 127.0.0.1 --port 61608 --workerId 380f28f6-f7a7-4ec4-adc6-ffa61819c1bb --requestId 0d896ea7-8657-4029-a5b4-d13e600b419a</span></pre>
<p class="p1">Then you can Start debugging to push DEBUG &gt; Attach to Azure Functions button. Also you can set a break point on index.ts file.</p>
<p class="p1"><a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-6.05.11-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-6.05.11-PM-1024x695.png" alt="" width="666" height="452" class="alignnone  wp-image-2195" /></a></p>
Send request to the functions,  You can see the deubg feature works!

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-5.44.37-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-11-at-5.44.37-PM-1024x694.png" alt="" width="947" height="642" class="alignnone  wp-image-2175" /></a>

Even if this is not the official support, I'm very happy to be able to code/debug Azure Functions with TypeScript.
<h1>Resource</h1>
<ul>
 	<li><a href="https://blogs.msdn.microsoft.com/appserviceteam/2017/09/25/develop-azure-functions-on-any-platform/">Develop Azure Functions on any platform</a></li>
</ul>
&nbsp;

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Giving minimum access privilege using Service Principal</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/giving-minimum-access-privilege-using-service-principal</link>
      <pubDate>Mon, 09 Oct 2017 08:28:19 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2085</guid>
      <description><![CDATA[Sometimes, you may want to provide the minimum privilege for some Azure resource. I'd like to...]]></description>
      <content:encoded><![CDATA[Sometimes, you may want to provide the minimum privilege for some Azure resource. I'd like to explain how to do it using Log Analytics search minimum access.

&nbsp;
<h1>Create a Service Principal</h1>
The most easiest way is using <a href="https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?toc=%2Fazure%2Fazure-resource-manager%2Ftoc.json&amp;view=azure-cli-latest">Azure CLI 2.0.</a>  This command create an Service Principal for Azure. You can choose any name and password of the Service Principal. If you use the service principal, you can access almost any resource of your subscription.

&nbsp;
<pre>$ az login

$ az ad sp create-for-rbac --name SPTestSP --password oMEDCPzT4vE0zIwY
WARNING: Retrying role assignment creation: 1/36
{
 "appId": "43d662d0-41af-41dc-bf4f-0cb0f1f93b3c",
 "displayName": "SPTestSP",
 "name": "https://SPTestSP",
 "password": "oMEDCPzT4vE0zIwY",
 "tenant": "YOUR_TENANT_ID"
}</pre>
&nbsp;

Now you can see your new Application on the Azure Portal.
See Azure Active Directory &gt; App Registrations or YOUR_LOG_ANALYTICS &gt; Access control (IAM)
You can find the new Application

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/SPAdded.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/SPAdded-1024x368.png" alt="" width="733" height="263" class="alignnone  wp-image-2105" /></a>

Also, you can do the it via Azure Portal. However it takes a lot of steps compared with az command.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/SPPortal.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/SPPortal-1024x248.png" alt="" width="662" height="160" class="alignnone  wp-image-2095" /></a>

If you don't have multiple tenant, you can access your Log Analytics with your Service Principal.

If you want to try, I provide a sample to access Log Analytics. Refer the read me.
<ul>
 	<li><a href="https://github.com/TsuyoshiUshio/LogAnalyticsSearchSample">https://github.com/TsuyoshiUshio/LogAnalyticsSearchSample</a></li>
</ul>
<h1>Remove the role</h1>
However, the default Role is <a href="https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles">Contributor</a>. It is too strong. Let's remove it.
<pre>$ az role assignment delete --assignee 43d662d0-41af-41dc-bf4f-0cb0f1f93b3c --role Contributor</pre>
Now you can see it has been removed.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Removed.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Removed-1024x521.png" alt="" width="413" height="210" class="alignnone  wp-image-2115" /></a>
<h1>Assign New Role</h1>
Go to YOUR_LOG_ANALYTICS &gt; <span>Access control (IAM)  Then push (+ ADD) button.</span>

Now you can choose a lot of roles. See <a href="https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles">List of Roles of Service Principal</a>

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/roles.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/roles.png" alt="" width="215" height="218" class="alignnone  wp-image-2125" /></a>

Configure it and save it.

I choose Log Analytics Reader. Also try Monitoring Reader.  Both works. (Since I can't find the spec of the Log Analytics, I tried both. Balloon tips said Monitoring Reader might minimum.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/LogAnalytics.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/LogAnalytics-416x1024.png" alt="" width="251" height="618" class="alignnone  wp-image-2126" /></a>

Now you can see it has been configured as Log Analytics Reader.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/AssignRole.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/AssignRole-1024x579.png" alt="" width="503" height="284" class="alignnone  wp-image-2135" /></a>

Since this is Log Analytics specific Role, I can't find it via az command.
<pre>$ az role assignment list --assignee 43d662d0-41af-41dc-bf4f-0cb0f1f93b3c
[]</pre>
<h1>Let's try</h1>
After reading the <a href="https://github.com/TsuyoshiUshio/LogAnalyticsSearchSample">Readme</a> and configure it, let's try.  Works!

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/works.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/works-1024x551.png" alt="" width="524" height="282" class="alignnone  wp-image-2145" /></a>

Then, remove the Service Principal  form the <span>YOUR_LOG_ANALYTICS &gt; </span><span>Access control (IAM) </span>

You'll get<span style="color: #ff0000"> <strong><em>403: Forbidden</em></strong></span>. :)

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Forbidden.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Forbidden-1024x642.png" alt="" width="549" height="344" class="alignnone  wp-image-2155" /></a>

For my safety I removed the Service Principal. Now I'm safe. :)

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Remove.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Remove.png" alt="" width="521" height="234" class="alignnone  wp-image-2156" /></a>
<h1>Resource</h1>
<ul>
 	<li><a href="https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?toc=%2Fazure%2Fazure-resource-manager%2Ftoc.json&amp;view=azure-cli-latest">Create an Azure service principal with Azure CLI 2.0</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-built-in-roles">List of Roles of Service Principal</a></li>
 	<li><a href="https://github.com/TsuyoshiUshio/LogAnalyticsSearchSample">https://github.com/TsuyoshiUshio/LogAnalyticsSearchSample</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Image uploading with Azure Functions node.js and Angular 4</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/image-uploading-with-azure-functions-node-js-and-angular-4</link>
      <pubDate>Sat, 07 Oct 2017 10:39:23 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=2055</guid>
      <description><![CDATA[In this blog post, I'd like to explain how to upload image to the Azure Blob storage from Angular 4...]]></description>
      <content:encoded><![CDATA[In this blog post, I'd like to explain how to upload image to the Azure Blob storage from Angular 4 SPA application and Azure Functions HttpTrigger Node. In this experiment, I use Mac Book Pro with<a href="https://github.com/Azure/azure-functions-cli/tree/core"> Azure Functions CLI with core branch</a>. Which means Azure Functions 2.0 with local debugging one.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.21.15-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.21.15-PM-1024x830.png" alt="" width="748" height="606" class="alignnone wp-image-2066" /></a>
<h1>Binary Uploading Strategy</h1>
You can choose two strategies for uploading image. One is <strong>multipart/form</strong> or <strong>base64 encoding</strong>.  In this usecase, I recommend to use <strong>base64 encoding</strong>.  If you choose the multipart/form strategy, you need to parse multipart. However, every multipart parser written for experss not for azure functions. (e.g. busboy). Even if you use azure-function-express, you <a href="https://github.com/yvele/azure-function-express/issues/8">can't do it until now</a>.  The Azure Functions req object doesn't have some methods for the multipart parsers. If you want to go  multipart/form for Azure Functions Node.js, you need to <a href="https://stackoverflow.com/questions/21745432/image-upload-to-server-in-node-js-without-using-express">write multipart parser by yourself</a>.

<span style="color: #ff0000"><strong>NOTE (2017/10/9):</strong> </span>I tried to write the multipart parser. However, eventually I didn't do it. The current version of the Azure Functions (Javascript) forcefully convert binary into string.  I wrote an issue and discuss it. I realized that it is known issue and they try to solve in the future version.
<ul>
 	<li><a href="https://github.com/Azure/azure-webjobs-sdk-script/issues/2009">Multipart/form-data processing via HttpTrigger doesn't work for Azure Functions (Javascript) #2009</a></li>
</ul>
Other solution is to use C#. I try to write multipart parser for Azure Functions Node.  Until then, I recommend the base64 encoding strategy.  Keep it simple.
<h1>Architecture</h1>
I'm using Angular 4.x. as a SPA. From this SPA, I'll send image to HttpTrigger, then using blob trigger, I'll upload the image file to a container.

&nbsp;
<pre>SPA  -&gt; Azure Functions (HttpTrigger with Blob output bindings) -&gt; Storage Account</pre>
&nbsp;

Something like this.

&nbsp;
<h1>Azure Functions Settings for SPA</h1>
If you access form SPA to Azure Functions, you might encounter this error.
<pre>Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:4200' is therefore not allowed access. The response had HTTP status code 404.</pre>
This is the <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a> problem. Javascript code from browser doesn't access the outside domain resource. For avoiding this issue on your local debugging enviornment, you need to add CORS setting on your local.settings.json. It requires server side configuration.
<pre>{
  <span class="pl-s"><span class="pl-pds">"</span>IsEncrypted<span class="pl-pds">"</span></span>: <span class="pl-c1">false</span>,
  <span class="pl-s"><span class="pl-pds">"</span>Values<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>AzureWebJobsStorage<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span><span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>AzureWebJobsDashboard<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span><span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>Host<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>LocalHttpPort<span class="pl-pds">"</span></span>: <span class="pl-c1">7071</span>,
    <span class="pl-s"><span class="pl-pds">"</span>CORS<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>*<span class="pl-pds">"</span></span>
  }
}</pre>
Now you are ready to write code!
<h1>Image Upload using Angular 4</h1>
The code is very easy.  I just do <strong> 1. base64 encoding using FileReader: readAsDataURL() method</strong>. Once I upload file on an input. Then  <strong>2. the Angular 4 invoke upload() method</strong>. Then "load" event happens, then it create an json object as a body and send it to the server.

<em>car-detail.component.ts</em>
<div>
<pre><span>@</span><span>Component</span><span>({</span>

<span> </span><span>selector:</span><span> </span><span>'app-root'</span><span>,</span>

<span> </span><span>templateUrl:</span><span> </span><span>'./car-detail.component.html'</span>

<span>})</span>

<span>export</span><span> </span><span>class</span><span> </span><span>CarDetailComponent</span><span> {</span>

<span> </span><span>title</span><span> </span><span>=</span><span> </span><span>'Car Reviews'</span><span>;</span>

<span> </span><span>image</span><span> </span><span>=</span><span> </span><span>'assets/noimage.jpg'</span><span>;</span>

<span> </span><span>car</span><span>:</span><span> </span><span>Car</span><span>;</span>


<span> </span><span>constructor</span><span>(</span><span>private</span><span> </span><span>http</span><span>:</span><span>Http</span><span>) {</span>

<span> </span><span>this</span><span>.</span><span>car</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Car</span><span>();</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>name</span><span> </span><span>=</span><span> </span><span>""</span><span>;</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>company</span><span> </span><span>=</span><span> </span><span>""</span><span>;</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>description</span><span> </span><span>=</span><span> </span><span>""</span><span>;</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>image_url</span><span> </span><span>=</span><span> </span><span>"assets/noimage.jpg"</span><span>;</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>state</span><span> </span><span>=</span><span> </span><span>"pending"</span><span>;</span>

<span> }</span>

<span> </span><span>executeUpload</span><span>(</span><span>base64encoded</span><span>:</span><span> </span><span>string</span><span>, </span><span>filename</span><span>:</span><span> </span><span>string</span><span>) {</span>

<span> </span><span>let</span><span> </span><span>headers</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Headers</span><span>();</span>

<span> </span><span>let</span><span> </span><span>options</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>RequestOptions</span><span>({</span>

<span> </span><span>headers:</span><span> </span><span>headers</span>

<span> });</span>

<span> </span><span>let</span><span> </span><span>data</span><span> </span><span>=</span><span> {</span><span>filename:</span><span> </span><span>filename</span><span>, </span><span>data:</span><span> </span><span>base64encoded</span><span> }</span>

<span> </span><span>this</span><span>.</span><span>http</span><span>.</span><span>post</span><span>(</span><span>encodeURI</span><span>(</span><span>'https://localhost:7071/api/FileUploadNode/'</span><span> </span><span>+</span><span> </span><span>filename</span><span>), </span><span>data</span><span>, </span><span>options</span><span>)</span>

<span> .</span><span>subscribe</span><span>(</span>

<span> </span><span>data</span><span> </span><span>=&gt;</span><span> </span><span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>),</span>

<span> </span><span>error</span><span> </span><span>=&gt;</span><span> </span><span>console</span><span>.</span><span>log</span><span>(</span><span>error</span><span>)</span>

<span> );</span>

<span> </span><span>this</span><span>.</span><span>car</span><span>.</span><span>image_url</span><span> </span><span>=</span><span> </span><span>encodeURI</span><span>(</span><span>"https://something.blob.core.windows.net/outcontainer/"</span><span> </span><span>+</span><span> </span><span>filename</span><span>); </span>

<span> </span>
<span> </span><span>this</span><span>.</span><span>image</span><span> </span><span>=</span><span> </span><span>base64encoded</span><span>; // 3. </span>

<span> </span><span>console</span><span>.</span><span>log</span><span>(</span><span>"File encoded"</span><span>);</span>

<span> }</span>

<span> </span><span>upload</span><span>(</span><span>list</span><span>:</span><span> </span><span>any</span><span>) {</span>

<span> </span><span>if</span><span> (</span><span>list</span><span>.</span><span>length</span><span> </span><span>&lt;=</span><span> </span><span>0</span><span>) { </span><span>return</span><span>; }</span>

<span> </span><span>let</span><span> </span><span>f</span><span> </span><span>=</span><span> </span><span>list</span><span>[</span><span>0</span><span>];</span>

<span> </span><span>let</span><span> </span><span>reader</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>FileReader</span><span>();</span>

<span> </span><span>let</span><span> </span><span>self</span><span> </span><span>=</span><span> </span><span>this</span><span>;</span>

<span> </span><span>reader</span><span>.</span><span>addEventListener</span><span>(</span><span>"load"</span><span>, </span><span>function</span><span>() {  // 2.</span>

<span> </span><span>let</span><span> </span><span>base64encoded</span><span> </span><span>=</span><span> </span><span>reader</span><span>.</span><span>result</span><span>;</span>

<span> </span><span>self</span><span>.</span><span>executeUpload</span><span>(</span><span>base64encoded</span><span>, </span><span>f</span><span>.</span><span>name</span><span>);</span>

<span> }, </span><span>false</span><span>);</span>

<span> </span><span>if</span><span> (</span><span>f</span><span>) {</span>

<span> </span><span>reader</span><span>.</span><span>readAsDataURL</span><span>(</span><span>f</span><span>); // 1.</span>

<span> }</span>

<span> }</span>

<span>}</span></pre>
</div>
&nbsp;

After sending image data to the server, we need to update the image on the screen. Although I have a bindings to Car instance, I didn't directly map the image to the image. Instead I use image property then <strong>3. I pass the base64 image data to the image property</strong>. We can pass the URL of the blob storage, however, it is asynchronous operations, we need to wait until the process has been done.

<em>car-detail.component.html</em>

&nbsp;
<div>
<pre><span> </span><span>&lt;</span><span>md-card-header</span><span>&gt;</span>

<span> </span><span>&lt;</span><span>div</span><span> </span><span>md-card-avatar</span><span> </span><span>class</span><span>=</span><span>"example-header-image"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span>

<span> </span><span>&lt;</span><span>md-card-title</span><span>&gt;</span><span>{{car.name}}</span><span>&lt;/</span><span>md-card-title</span><span>&gt;</span>

<span> </span><span>&lt;</span><span>md-card-subtitle</span><span>&gt;</span><span>{{car.company}}</span><span>&lt;/</span><span>md-card-subtitle</span><span>&gt;</span>

<span> </span><span>&lt;/</span><span>md-card-header</span><span>&gt;</span>

<span> </span><span>&lt;</span><span>img</span><span> </span><span>md-card-image</span><span> </span><span>src</span><span>=</span><span>"{{image}}"</span><span> </span><span>alt</span><span>=</span><span>"Some car image"</span><span>&gt;</span>

<span> </span><span>&lt;</span><span>md-card-content</span><span>&gt;</span></pre>
</div>
&nbsp;
<h1>Decode base64 image with Azure Functions</h1>
Now you can get an image encoded in base64 via HttpTrigger of Azure Functions. Let's write a code for decode.  To encode the image base64 image is like this according to <a href="https://tools.ietf.org/html/rfc2397">the RFC2397</a> . Just decode these.

example of base64 image. It includes some headers.
<pre style="margin: 0in;font-family: Menlo;font-size: 8.25pt"><span style="color: black;background: white" lang="en-US">[10/7/17 4:58:58 AM] </span><span style="color: #24d5d4;background: white" lang="ja-JP">  data: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABagAAAG0CAYAAADXf8CiAAAMFWlDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnltSCAktEAEpoTdBepUaqiAgHWyEJEAoAROCih1dVHDtIoIVXRVRdC2ALDZEsbAI2OsDFRVlXVzFhpo3KaDra9</span></pre>
And once you configure the output blob bindings, you all you need to do is

&nbsp;
<pre><span>context</span><span>.</span><span>bindings</span><span>.</span><span>outputBlob</span><span> </span><span>=</span><span> </span><span>response</span><span>.</span><span>data</span><span>;</span></pre>
<div></div>
<div>Then an image is uploaded to your Storage Account. In this case, blob output binding's name is outputBlob.</div>
<div></div>
<div><em>index.js</em></div>
<div></div>
<div>
<pre><span>function</span><span> </span><span>decodeBase64Image</span><span>(</span><span>context</span><span>, </span><span>data</span><span>) {</span>

<span> </span><span>var</span><span> </span><span>matches</span><span> </span><span>=</span><span> </span><span>data</span><span>.</span><span>match</span><span>(</span><span>/</span><span>^</span><span>data:([A-Za-z-+\/]</span><span>+</span><span>);base64,(.</span><span>+</span><span>)</span><span>$</span><span>/</span><span>);</span>

<span> </span><span>var</span><span> </span><span>response</span><span> </span><span>=</span><span> {}</span>

<span> </span><span>if</span><span> (</span><span>matches</span><span>.</span><span>length</span><span> </span><span>!==</span><span> </span><span>3</span><span>) {</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>"Error case"</span><span>);</span>

<span> </span><span>return</span><span>;</span>

<span> }</span>

<span> </span><span>response</span><span>.</span><span>type</span><span> </span><span>=</span><span> </span><span>matches</span><span>[</span><span>1</span><span>];</span>

<span> </span><span>response</span><span>.</span><span>data</span><span> </span><span>=</span><span> </span><span>Buffer</span><span>.</span><span>from</span><span>(</span><span>matches</span><span>[</span><span>2</span><span>], </span><span>'base64'</span><span>);</span>

<span> </span><span>return</span><span> </span><span>response</span><span>;</span>

<span>}</span>

<span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> </span><span>function</span><span> (</span><span>context</span><span>, </span><span>req</span><span>) {</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>'JavaScript HTTP trigger function processed a request.'</span><span>);</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>req</span><span>.</span><span>body</span><span>);</span>

<span> </span><span>let</span><span> </span><span>response</span><span> </span><span>=</span><span> </span><span>decodeBase64Image</span><span>(</span><span>context</span><span>, </span><span>req</span><span>.</span><span>body</span><span>.</span><span>data</span><span>);</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>'filename: '</span><span> </span><span>+</span><span> </span><span>req</span><span>.</span><span>name</span><span>);</span>

<span> </span><span>context</span><span>.</span><span>log</span><span>(</span><span>'filetype: '</span><span> </span><span>+</span><span> </span><span>response</span><span>.</span><span>type</span><span>);</span>

<span> </span><span>context</span><span>.</span><span>bindings</span><span>.</span><span>outputBlob</span><span> </span><span>=</span><span> </span><span>response</span><span>.</span><span>data</span><span>;</span>

<span> </span><span>context</span><span>.</span><span>res</span><span> </span><span>=</span><span> {</span>

<span> </span><span>// status: 200, /* Defaults to 200 */</span>

<span> </span><span>body:</span><span> </span><span>"Uploaded "</span><span> </span>

<span> };</span>

<span> </span><span>context</span><span>.</span><span>done</span><span>();</span>

<span>};</span></pre>
</div>
&nbsp;

However, we have some problem. The uploaded image has a random number name. I'd like to specify the filename.

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.15.36-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.15.36-PM-1024x47.png" alt="" width="1024" height="47" class="alignnone size-large wp-image-2065" /></a>

&nbsp;
<h1>Specify the name binding for images</h1>
We can <a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings">configure binding data runtime</a>. However it is only for C#.  We need to come up with other strategy. We can't configure the filename from our code. Instead, we can use the feature of the Azure Functions binding feature. You can see the <strong>route</strong> property. Once we accept the FileUpload/xxxxx url, Azure Functions pass the xxxxx to {filename}. On the output bindings, you can use {filename} as well.

Let's see the <em>function.json </em>
<div>
<pre><span>{</span>

<span> </span><span>"bindings"</span><span>: [</span>

<span> {</span>

<span> </span><span>"authLevel"</span><span>: </span><span>"function"</span><span>,</span>

<span> </span><span>"type"</span><span>: </span><span>"httpTrigger"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"in"</span><span>,</span>

<span> </span><span>"name"</span><span>: </span><span>"req"</span><span>,</span>

<span> </span><span>"route"</span><span>: </span><span>"FileUploadNode/{filename}"</span><span>,</span>

<span> </span><span>"methods"</span><span>: [</span>

<span> </span><span>"post"</span>

<span> ]</span>

<span> },</span>

<span> {</span>

<span> </span><span>"type"</span><span>: </span><span>"http"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"out"</span><span>,</span>

<span> </span><span>"name"</span><span>: </span><span>"res"</span>

<span> },</span>

<span> {</span>

<span> </span><span>"type"</span><span>: </span><span>"blob"</span><span>,</span>

<span> </span><span>"name"</span><span>: </span><span>"outputBlob"</span><span>,</span>

<span> </span><span>"path"</span><span>: </span><span>"outcontainer/{filename}"</span><span>,</span>

<span> </span><span>"connection"</span><span>: </span><span>"carreviewstr_STORAGE"</span><span>,</span>

<span> </span><span>"direction"</span><span>: </span><span>"out"</span>

<span> }</span>

<span> ],</span>

<span> </span><span>"disabled"</span><span>: </span><span>false</span>

<span>}</span></pre>
</div>
Now, you can upload image from your Angular 4 apps to Azure Functions (Node.js).  I'll upload whole sample after finish the coding.

Enjoy coding with Azure Functions!

&nbsp;

<a href="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.31.24-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/10/Screen-Shot-2017-10-07-at-7.31.24-PM-1024x513.png" alt="" width="679" height="340" class="alignnone wp-image-2076" /></a>

&nbsp;

&nbsp;
<h1>Resource</h1>
<ul>
 	<li><a href="https://github.com/Azure/azure-functions-cli/issues/133">Allow specifying CORS settings in local.settings.json</a></li>
 	<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL">FileReader: readAsDataURL</a></li>
 	<li><a href="https://tools.ietf.org/html/rfc2397">RFC2397: The "data" URL scheme</a></li>
 	<li><a href="https://stackoverflow.com/questions/10037563/node-js-base64-image-decoding-and-writing-to-file">Node.js Base64 Image decoding and writing to file</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings">https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings</a></li>
 	<li><a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node">https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node</a></li>
 	<li><a href="https://stevenfollis.com/2016/09/24/background-image-processing-with-azure-functions-and-nodejs/">https://stevenfollis.com/2016/09/24/background-image-processing-with-azure-functions-and-nodejs/</a></li>
 	<li><a href="https://github.com/Azure/azure-functions-cli/tree/core">https://github.com/Azure/azure-functions-cli/tree/core</a></li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>OpenFaaS on Azure (Swarm)</title>
      <link>https://docs.microsoft.com/archive/blogs/livedevopsinjapan/openfaas-on-azure-swarm</link>
      <pubDate>Thu, 21 Sep 2017 07:28:03 GMT</pubDate>
      <dc:creator><![CDATA[Tsuyoshi Ushio]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/livedevopsinjapan/?p=1986</guid>
      <description><![CDATA[I explain about how to deploy OpenFaaS on Kubernetes on Azure. However, OpenFaaS supports Swarm...]]></description>
      <content:encoded><![CDATA[<a href="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-20-at-11.55.07-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-20-at-11.55.07-PM-1024x457.png" alt="" width="496" height="221" class="alignnone wp-image-1996" /></a>

I explain about how to deploy OpenFaaS on Kubernetes on Azure. However, OpenFaaS supports Swarm as well. What is the most easy way to deploy it? Since the OpenFaaS requires docker ce for 17.05+, we can't use Azure Container Service. Instead, we can use Docker for Azure. It is the most easiest way to deploy 17.06+ swarm mode cluster on Azure, currently.

Let's deploy it.
<h1>Deploy Docker for Azure</h1>
Go to this site. You can deploy the  cluster directly. Just click "Deploy Docker Community Edition for Azure (Stable)"

<a href="https://docs.docker.com/docker-for-azure/#quickstart">Deploy your app on Docker for Azure</a>

Then you can see this page. You can edit the template if you like.

<a href="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-21-at-12.04.38-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-21-at-12.04.38-AM-1024x695.png" alt="" width="517" height="351" class="alignnone wp-image-2006" /></a>
<h1>Connect to the Docker for Azure</h1>
After the deployment, you can find the <span>externalSSHLoadBalancer which have an IP address to access the master nodes.</span>

If you have three master nodes, then the SSH port will be 50000, 50001, and 50002.  You can check it out on the externalSSHLoadBalancer &gt; Inbound NAT Rules

<a href="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-21-at-12.13.35-AM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-21-at-12.13.35-AM-1024x472.png" alt="" width="573" height="264" class="alignnone wp-image-2016" /></a>

You can  tunnel it to deploy OpenFaaS. If the loadbalancer's IP is 13.93.211.68, then the command is like this. NOTE: the default user name is docker. not azureuser!
<pre class="p1"><span class="s1">ssh -p 50000 -fNL localhost:2374:/var/run/docker.sock docker@13.93.211.68
export DOCKER_HOST=:2374</span></pre>
<h1 class="p1"><span class="s1"> Deploy OpenFaaS</span></h1>
<p class="p1">Just clone the OpenFaaS and deploy it.</p>

<pre class="p1">git clone git@github.com:alexellis/faas.git
cd faas
./deploy-stack.sh</pre>
<p class="p1">Finish. Then you can check it out. If the all nodes status is OK and replicas are not 0, then it works.</p>

<pre class="p1"><span class="s1">$ docker node ls</span>

<span class="s1">ID<span class="Apple-converted-space">                            </span>HOSTNAME<span class="Apple-converted-space">              </span>STATUS<span class="Apple-converted-space">              </span>AVAILABILITY<span class="Apple-converted-space">        </span>MANAGER STATUS</span>

<span class="s1">19jwb8riabdtgbrgbhcaohv7v <span class="Apple-converted-space">    </span>swarm-manager000002 <span class="Apple-converted-space">  </span>Ready <span class="Apple-converted-space">              </span>Active<span class="Apple-converted-space">              </span>Leader</span>

<span class="s1">5r4cghmtsiyt96cfmzbeavhb5 * <span class="Apple-converted-space">  </span>swarm-manager000000 <span class="Apple-converted-space">  </span>Ready <span class="Apple-converted-space">              </span>Active<span class="Apple-converted-space">              </span>Reachable</span>

<span class="s1">guc9klap92wy9w393d4s29vir <span class="Apple-converted-space">    </span>swarm-manager000001 <span class="Apple-converted-space">  </span>Ready <span class="Apple-converted-space">              </span>Active<span class="Apple-converted-space">              </span>Reachable</span>

<span class="s1">ubwo378qzjq4pl45rrixusfa9 <span class="Apple-converted-space">    </span>swarm-worker000000<span class="Apple-converted-space">    </span>Ready <span class="Apple-converted-space">              </span>Active <span class="Apple-converted-space">             </span></span>

<span class="s1">xm12qzvwqyuspzcy3fs3o2a5f <span class="Apple-converted-space">    </span>swarm-worker000001<span class="Apple-converted-space">    </span>Ready <span class="Apple-converted-space">              </span>Active <span class="Apple-converted-space">             </span></span>

<span class="s1">$ docker service ls</span>

<span class="s1">ID<span class="Apple-converted-space">                  </span>NAME<span class="Apple-converted-space">                </span>MODE<span class="Apple-converted-space">                </span>REPLICAS<span class="Apple-converted-space">            </span>IMAGE <span class="Apple-converted-space">                                  </span>PORTS</span>

<span class="s1">0z3nhuc3322r<span class="Apple-converted-space">        </span>func_decodebase64 <span class="Apple-converted-space">  </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/alpine:health<span class="Apple-converted-space">                 </span></span>

<span class="s1">5k222fmec6pb<span class="Apple-converted-space">        </span>func_nodeinfo <span class="Apple-converted-space">      </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/nodeinfo:latest<span class="Apple-converted-space">               </span></span>

<span class="s1">6dscv6uctk8p<span class="Apple-converted-space">        </span>func_hubstats <span class="Apple-converted-space">      </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/hubstats:latest<span class="Apple-converted-space">               </span></span>

<span class="s1">ki6r1w1f5cdm<span class="Apple-converted-space">        </span>func_wordcount<span class="Apple-converted-space">      </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/alpine:health<span class="Apple-converted-space">                 </span></span>

<span class="s1">mji9f788qktk<span class="Apple-converted-space">        </span>func_gateway<span class="Apple-converted-space">        </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/gateway:0.6.3 <span class="Apple-converted-space">                </span>*:8080-&gt;8080/tcp</span>

<span class="s1">mktgocot0uxq<span class="Apple-converted-space">        </span>func_echoit <span class="Apple-converted-space">        </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/alpine:health<span class="Apple-converted-space">                 </span></span>

<span class="s1">nz764gxdg99k<span class="Apple-converted-space">        </span>func_prometheus <span class="Apple-converted-space">    </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/prometheus:latest <span class="Apple-converted-space">            </span>*:9090-&gt;9090/tcp</span>

<span class="s1">u8s2kw7755q2<span class="Apple-converted-space">        </span>func_webhookstash <span class="Apple-converted-space">  </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/webhookstash:latest<span class="Apple-converted-space">           </span></span>

<span class="s1">ubbtcade7skw<span class="Apple-converted-space">        </span>func_markdown <span class="Apple-converted-space">      </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>alexellis2/faas-markdownrender:latest<span class="Apple-converted-space">   </span></span>

<span class="s1">xulsluhy3zvv<span class="Apple-converted-space">        </span>func_alertmanager <span class="Apple-converted-space">  </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/alertmanager:latest <span class="Apple-converted-space">          </span>*:9093-&gt;9093/tcp</span>

<span class="s1">yw7s4ut1xt99<span class="Apple-converted-space">        </span>func_base64 <span class="Apple-converted-space">        </span>replicated<span class="Apple-converted-space">          </span>1/1 <span class="Apple-converted-space">                </span>functions/alpine:health<span class="Apple-converted-space">       


</span></span></pre>
<h1 class="p1">Open the OpenFaaS potal</h1>
<p class="p1">As you can see, All you need to do is find the <span>externalLoadBalancer on the Resource Group, then access the URL with port 8080.  You can refer <a href="https://blogs.technet.microsoft.com/livedevopsinjapan/2017/09/19/open-faas-on-acs-kubernetes/">OpenFaaS on ACS (Kubernetes)</a> for seeing the faas-cli setting. </span></p>
<p class="p1"><span>
<a href="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-20-at-11.55.07-PM.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/09/Screen-Shot-2017-09-20-at-11.55.07-PM-1024x457.png" alt="" width="1024" height="457" class="alignnone size-large wp-image-1996" /></a>
Then you can see the OpenFaaS dashboard. Enjoy coding. </span></p>
<p class="p1"></p>]]></content:encoded>
    </item>
  </channel>
</rss>