Reading Notes #259

three-amigos-mainCloud


Programming




Reading Notes #258

AzureAdvisorSuggestion of the week

  • Announcing the public preview of Azure Advisor (Shankar Sivadasan) - This is definitely the most asked question from clients: how can I optimize my solutions. I was very positively surprised by the quality and precision of the suggestions of the advisor service. It's a must.

Cloud


Programming



Lessons learn while trying to deploy a Docker container in Azure

(Ce billet en aussi disponible en français.)


Since I saw Donovan Brown do his demo during the Connect(); // 2016 Keynote, I really want to have a taste of that left click to turn a project to Docker containers. So last Sunday I wake up early and armed with a big bowl of cafe latte start prepping my VM to try it. But as you could imagine, it didn't work on the first attempt, and that what I want to share to you.

DonovanBrown

Let's get started


I build a new VirtualBox virtual machine (VM) using an ISO of Windows 10, then install all the updates to get the anniversary edition. I afterward went to visualstudio.com to get the Visual Studio 2017 RC and install it with a few components: web, azure, etc. And next when looking for Docker for windows. Same here super easy just need to download and install the MSO from docker.com and voila... or not. Like specified in the Docker documentation the installer noticed that Hyper-V was not present in my environment and suggested installing it and reboot the machine. Until then, everything was going fine, but when Docker try to start, after the reboot, I got an error message:

Error creating machine: Error in driver during machine creation: This computer doesn't have VT-X/AMD-v enabled. Enabling it in the BIOS is mandatory

However, the setting was set, as you can see in the screenshot.

VT-xSetting

After a short investigation, I found that VirtualBox was not supporting nested virtualization, yet. Well, let's try another virtualization platform then.

First Success


I created a new VM under VMware Player this time and repeated all the steps as before. After the reboot, the little white whale in the system didn't prompt any error... Was it working? Let's try to create a Nginx Hello-world container to check. And the answer was YES!

2016-11-22_19-00-45

Docker and Azure


Now let's get serious. It's time to do the left click on the project and add Docker Project Support. Then press F5 to try it locally.

ERROR: for mystuff Cannot create container for service mystuff: C: drive is not shared. Please share it in Docker for Windows Settings Encountered errors while bringing up the project..

I got too excited, and I had skipped some reading... It's written black on white in the documentation that you need to share some drive to make it work.

ShareDrice

After that it when smoothly and in few minutes, I got my website to run in a Docker container accessible via localhost:32768. Great! Now to get it available on Azure, I need to create a registry where all the images will be saved. To do that simply left click again on the project, and select Publish. The guided dialog will popup and help you to create and deploy your things. An interesting point is before clicking the "Create" button you will have the option to export your template as a json file, very useful. But for now click Create, then Publish.

DockerPublishing

After a moment you should have a new browser window that will popup with your App now deployed in Azure.

DockerOnline

Wow! That was really a great experience. It's definitely a very simple process to get started. I really appreciate the Docker for Windows and Kitematic user interface. Of course, all the command-line are still available, but now I also have another option for the day where I feel more for clicking instead of typing.

DockerTools

Let's build it and ship it, from any platform to the cloud!



Reading Notes #257

2016-11-20_21-14-57Suggestion of the week

  • Microsoft Connect(); 2016 Recap (Joseph Hill) - Three full day of great content. However, if you are like me, you didn't that much free time. Fortunately, all the presentations are available in video on demand. You need a summary because even if the keynote was really good... it is still 2h30, this post is the place to start.

Cloud


Programming


Miscellaneous



Reading Notes #256

IMG_20161107_104028Cloud

Programming

Miscellaneous



What did you say you are, an MVP?


A few years ago, I decided to put myself in a situation where I’d be in contact with more people. Of course, I got a lot of technical questions, but also, and more often than you may think, people ask me about my MVP title. What’s an MVP? What do you need to do to become one? What do you do when you are an MVP? What do you get as an MVP? You can always come see me and ask me; it would be a pleasure to speak with you. However, for those who want to stay in the shadows, or are not sure how to ask, I decided to write a blog post about it.


What is MVP?

MVP_Logo_Preferred_Cyan300_RGB_300ppiIn short, MVPs are Microsoft Most Valuable Professionals (MVPs). For more than twenty years, Microsoft has given that award to technology experts who passionately share their knowledge with the community. There are close to 4,000 MVPs around the globe specializing in approximately seventeen different categories. MVPs share their passion by writing blog posts, articles, and books, answering questions in forums, and giving presentations in community groups and events.

How I Became an MVP

Firstly, I didn’t do anything to become an MVP. I became an MVP because of what I was doing. And that’s how I think it should be approached.

I’ve always read a lot about new technologies and enjoy working on home “pet projects”. I find that the optimal way to learn is by doing whenever possible. Having real struggles with “features” are the best brain push-up you can get. Because things are changing quickly, and because I was playing with a large variety of technologies, I was keeping notes on my work. First, my notes were on a disk; then I put them online. From time to time, when someone would ask me a question at work, I would search through my notes. Although my online notes were public, the URL was purposely not a friendly one. Before long, co-workers started to ask me if they could have the URL to my notes and I knew it was time to take the first real step into the light.

I still remember clearly that talk I had with Dom, an "Eagle" (tech prime) at the office. I was shy but he told me to give it a try; some people were already liking what I was sharing, and after all, I was doing the work for myself anyways so why not share it with others? Since getting out of your comfort zone is a good way to learn, I decided to start my blog. And just to add a level of difficulty, I decided to do it in English since at the time I only knew French.

I started my blog, FrankysNotes.com, and changed all my funny avatars to my photo. Since starting my blog, I publish my reading notes every Monday. And exactly like the saying goes, “build it, and they will come.” The weeks passed and the number of weekly views on my blog grew from dozens to hundreds. Encouraged, I decided to publish the notes from one of my home projects. Immediately the number of views jumped. I was trying to write more, but it was a very long process since I was definitely not fluent in English. However, every time I published a post, I was really proud. Not only had I successfully finished a project and learned something new, I had also written a post that would help others learn too. At the same time, I joined the Canadian Windows Azure Community Experts group and participated in events.

Sharing my passion through presentations, blog posts, and meetups was enough for me to be welcomed into the big MVP family.

CanadianMVPFamilly

What I’ve Been Up to Since Becoming an MVP

Having been recognized as an MVP didn’t change me. I’m still very nervous before a presentation or publishing a blog post. I continue to code late at night on personal projects. More than ever, I’m excited when after a long battle with a bug, I finally find the way to make everything work.
What is different is that I now have more opportunities. All those friends reaching out to me (and other times it’s me reaching out to them) to ask a quick question or invite me to join them at an event. It’s up to me to embrace those challenges, get out of my comfort zone and continue to share my passion and my journey through the technology I like so much. I’ve started a second blog, in French this time, called CloudenFrancais.com. I’ve also joined the MSDEVMTL (Cloud) community group in Montreal, Quebec, Canada as a co-admin and started a new community in Ottawa, Ontario, Canada called OttCloudTech.

Thank you for reading my blog posts and asking questions. Next time you have the chance, reach out to me, it would be terrific to finally meet you.
See you soon.


References

ReadingNotes #256


Cloud



Programming



Miscellaneous



Reading Notes #255

microsoft_studioCloud


Programming


integration


Miscellaneous




Reading Notes #254

IMG_20161019_192029Cloud


Programming


Databases


Miscellaneous



Reading Notes #253

2016-10-17_09-17-05Suggestion of the week


Cloud


Programming


Databases



Reading Notes #252

ReadingNotesAppCloud

  • Azure Subscription Migration to CSP (Kirill Kotlyarenko) - Excellent post that explains the differences between the different types and how to migrate ... with a minimum of pain.
  • New lower Azure pricing (Takeshi Numoto) - Really good news more VMs types and lower prices.
  • Storing and using secrets in Azure (Bertrand Le Roy) - This p is great tutorial that explains all h steps to configure use the Azure Vault, when our secrets need more then sits in a config file.

Programming


Databases

  • Avoid ORDER BY in SQL Server views (Aaron Bertrand) - Sometimes we need workarounds to bend some services to our wishes, but we must keep in mind the real best practices.



How I use Azure Logic App, API App and Function App in my life

Why should we do things over and over? I know I don't want to lose my time doing so. Every time I see myself doing something I already did, I look for optimization. Sometimes, it's just little things like trying a different path to get from the train station to the office, and the other time, it's like drinking the rainbow juice directly from the source.

In this post, I will share with you how I optimized a three hours process into a two... minutes automated customizable solution using Azure Logic App and API App.

Quick Context

For the past two hundred fifty something weeks every Monday I share my reading notes. Those are articles that I read during the previous week with a little comment; my 2 cents about it. I read all those books, articles and posts on my e-book reader; In this case a Kindle whitepaper. I use an online service call Readability that can easily clean (remove everything except the text and useful images) the article and send it to my e-book reader. All the articles are kept as a bookmark list.

SendToKindle

When I have time I read what's on my list. Each time I'm done, I add a note ended by tags between square brackets, those will be use later for research and filter.

OnlyNotewithTags

Every Sunday, I extract the notes, then search in Readability to find back the URL and build with all this my post for the next morning. A few years ago, I did a first optimization using a Ruby script and I blogged about it here. While it's been working very well all those years, I wanted to change it so I do not have to install Ruby and the Gems on every machine I use.

Optimization Goals

Here is the list of things I wanted for this new brew of the Reading notes post generator:
  • No install required
  • not device or service couple.
  • generate json verrsion for future purpuse
  • cheap

Optimization Plan

Azure Logic App is the perfect candidate for this optimization because it doesn't require any local installation. Since it a flow between connectors any of them can be changed to please the user. In fact, that was the primary factor that made me picked Azure Logic App. For example, i the current solution, I'm using OneDrive as an initial drop zone. If you your environment you would prefer using DropBox instead of OneDrive, you just need to switch connectors, and nothing else will be affected. Another great advantage is that Azure Logic App is part of the App service ecosystem so all those components are compatible.

Here is the full process plan, at the high level.

ReadingNoteLogicApp_blog

  1. Drop the My Clippings.txt file in an OneDrive folder.
  2. Make a copy of the file In Azure Blob Storage, using the Blob Storage built-in connector.
  3. Parse the My Clippings.txt file to extract all the clippings (notes) since last extraction, using my custom My Clippings API App.
  4. For each note,
    1. Get the URL where that post is coming from, using my custom Readability Api App.
    2. Extract the tags and category (first tag is used as a category), using my custom Azure Function.
    3. Serialize the note with all the information in json.
    4. Save to Azure Blob Storage the json file in a temporary container.
  5. Generate a summary of all json files using my last custom ReadingNotes API App. It also saved a json and Markdon files of the summary.
Note: The summary could be published directly, but I decided to keep that last step manual, so I can check for typos and Grammar.

Let's see more in details

Many great tutorials are already available about how to create Azure Logic App or Azure API App, so in this post, I won't explain how to create them, but mostly share with you some interesting snippets or gotchas I encounter during my journey.

In the next screen capture, you can see all the steps contained in my two Logic App. I decided to slip the process because many tasks needed to be done for every note. The main loop (on the left) fetches the notes collection and generates the output. For every note, it will call the Child Logic App (on the right).


logicapp-Overview

The ReadingNotes Builder contains:
  1. Initial Trigger when a file is created in an OneDrive folder.
  2. Create a copy of the file in an Azure Blob storage.
  3. Delete the file in OneDrive.
  4. Get the configuration file from Azure blob storage.
  5. Call the API App responsible for parsing the file and extract the recent clippings.
  6. Call the child Logic App for every clipping returned in the previous steps (foreach loop).
    • A. Trigger of the Child Logic App.
    • B. Call the API App responsible for searching in the online bookmark collection and return the URL of the article/ post.
    • C. Call Azure Function App responsible for extracting tags from the note.
    • D. Call Azure Function App responsible for converting the object in json.
    • E. Saves the json object in a file in Azure blob storage.
    • F. Gets the updated configuration file.
    • G. Call Azure Function App responsible for keeping the latest note date.
    • H. Update the configuration with the latest date.
    • I. Return an HTTP 200 code, so the parent Logic App knows the work is done.
  7. Call the API App responsible for building the final markdown file.
  8. Save the markdown file to an Azure blob storage that was returned at the previous step.
  9. Update the config final.

As an initial trigger, I decided to use OneDrive because it's available from any devices, from anywhere. I just need to drop the MyClippings.txt file in the folder, and the Logic App will start. Here, how I configured it in the editor:


logicappMain-InitialTrigger

MyClippings API App


Kindle's notes and highlights are saved in a local file named My Clippings.txt. To be able to manipulate my notes, I needed a parser. Ed Ryan created the excellent [KindleClippings][KindleClippings], an open-source project available on github. In the actual project, I only wrapped that .Net Parser in an Azure API App. Wrapping the API in an API App will help me later to manage security, metrics, and it will simplify the connection in all other Azure solutions app.

I won't go into the detail on how to create an Azure API App, a lot of great documentation is available online. However, you will need at least the Azure .Net SDK 2.8.1 to create an API App project.

CreateAPIApp_step1


Swagger API metadata and UI are a must so don't forget to un-comment that section in the SwaggerConfig file.


CreateAPIApp_step2


I needed an array of notes taken after a specific date. All the heavy work is done in [KindleClippings][KindleClippings] library. The ArrayKindleClippingsAfter method gets the content of the My Clippings.txt file (previously saved in Azure blob storage), and pass it to the KindleClippings.Parse method. Then using Linq, only return the notes taken after the last ReadingNotes publication date. All the code for this My Clippings API App is available on github, but here the method:


public Clipping[] ArrayKindleClippingsAfter(string containername, string filename, string StartDate)
{
    var blobStream = StorageHelper.GetStreamFromStorage(containername, filename);
    var clippings = KindleClippings.MyClippingsParser.Parse(blobStream);
    var result = (from c in clippings
                    where c.DateAdded >= DateTime.Parse(StartDate)
                    && c.ClippingType == ClippingTypeEnum.Note
                    select c as KindleClippings.Clipping).ToArray<Clipping>();
    return result;
}


Once the Azure API App is deployed in Azure it could be easily called from the Azure Logic App.


AddCustomAPIApp


A great thing to notice here is that because Azure Logic App is aware of the required parameters and remembers all the information from the previous steps (show in different color), it will be a very simple to configure the call.


logicappMain-GetTheClippings

Azure Logic App calling another Azure Logic App


Now that we have an array of note, we will be able to loop through each of them to execute other steps. When I wrote the App, the only possibility way to execute multiple steps in a loop, was to call another Azure Logic App. The child Logic App will by trigger by an HTTP POST and will return an HTTP Code 200 when it's done. A json schema is required to define the input parameters. A great tool to get that done easily is http://jsonschema.net.


logicappSub-InitialTrigger

Readability API App

Readability is an online bookmark service that I'm using for many years now. It offers many API to parse or search article and bookmarks. I found and great .Net wrapper on github called CSharp.Readability that was written by Scott Smith. I could have called directly the Readability from Logic App. However, I needed a little more so I decided to use Scott's version as my base for this API App.
From the clipping collection returned at the previous step, I only have the title and need to retrieve the URL. To do this, I added a recursive method call SearchArticle.

private BookmarkDetails SearchArticle(string Title, DateTime PublishDate, int Pass)
{
    var retryFactor = 2 * Pass;
    var fromDate = PublishDate.AddDays(-1 * retryFactor);
    var toDate = PublishDate.AddDays(retryFactor);
    var bookmarks = RealAPI.BookmarkOperations.GetAllBookmarksAsync(1, 50, "-date_added", "", fromDate, toDate).Result;
    var result = from b in bookmarks.Bookmarks
                    where b.Article.Title == Title
                    select b as BookmarkDetails;
    if (result.Count() > 0)
    {
        return result.First<BookmarkDetails>();
    }
    if (Pass <= 3)
    {
        return SearchArticle(Title, PublishDate, Pass + 1);
    }
    return null;
}

Azure Function: Extract tags

While most of the work was done in different API, I needed little different tools. Many possibilities but I decided to take advantage of the new Azure Function App. They just sit there waiting to be use! The ReadingNotes Builder uses three Azure Function App, let me share one of them: ExtractTags. An interesting part with function is that you can configure them to get triggered by some event or to act as Webhook.

CreateFunctionApp

To create a Function App as Webhook you can use one of the templates when you create the new Function. Or from the code editor in the Azure Portal, you can click on the Integrate tab and configure it.


SetWebHookonFunctionApp


Once it's done you are ready to write the code. Once again, this code is very simple. It started by validating the input. I'm expecting a Json with a node called note, then extract the tags from it and return both parts.


public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
    string tags;
    string cleanNote;
    string jsonContent = await req.Content.ReadAsStringAsync();
    dynamic data = JsonConvert.DeserializeObject(jsonContent);
    if (data.note == null ) {
        return req.CreateResponse(HttpStatusCode.BadRequest, new {
            error = "Please pass note properties in the input object"
        });
    }
    string note = $"{data.note}";
    int posTag = note.LastIndexOf('[')+1;
    if(posTag > 0){
        tags = note.Substring(posTag, note.Length - posTag-1);
        cleanNote = note.Substring(0,posTag-1);
    }
    else{
        tags = "";
        cleanNote = note;
    }
    return req.CreateResponse(HttpStatusCode.OK, new {
        tags = $"{tags}",
        cleanNote = $"{cleanNote}"
    });
}


Now, to call it from the Azure Logic App, You will need first to Show Azure Function in the same region to see your Function App. And simply add the input; in this case like expected a json with a node called note.


logicappSub-FunctionCall

What's next

Voila! This is a simple but real application. While I shared only a part of the code in this post, all of it is available on github. I also did a presentation at DevTeach and other details are present in those slides. Using Azure Logic App to build this application was really interesting, and easy. Now that some pieces are in place (up there), I will be able to grow my environment by adding more functionalities, an interface, more security, but that's for another post...



References

Reading Notes #251

CAW8uq8UwAA_ffsCloud


Programming


Miscellaneous



Reading Notes #250

250Notes

 

Suggestion of the week


Cloud


Programming



Reading Notes #249

logicappSuggestion of the week


Cloud


Programming


Databases


Miscellaneous




Reading Notes #248

imageProgramming


Databases


Miscellaneous


Reading Notes #247

23Cloud


Programming


Miscellaneous

Reading Notes #246

IMG_20160826_115405Cloud


Programming


Databases


Miscellaneous


Reading Notes #245

Cloud


Miscellaneous


Reading Notes #244

cakeWin10Cloud


Programming


Miscellaneous