Carnation Anapa Winery: industrial crushing and destemming

Over the passed weekend I, my family, and my parents stayed at Knight Hill Winery in Zillah, WA and got a chance to participate in two incredible activities:

First, on Saturday, we’ve picked a row of Roussanne at Carthage Vineyard. It took for 4 of us (me, my dad, my wife, and the owner) about 3.5 hours and produced one full bucket and a little more in another bucket, totalling more than 1400 lbs.

Then, on Sunday, we’ve crushed it using real industrial-grade production line: tipped the buckets over using a forklift, dumped the grapes over a conveyor line, that dropped them into a industrial crusher and destemmer, then pumped over the juice into a 250-gallon tank.

Posted in Winemaking | Tagged | Leave a comment

How I started using MediatR and then how I stopped, part 1

This is a series of posts:

Introduction

Today I own the Service Fabric infrastructure piece in my team, to run applications and services written by otherw. But before I wrote a Service Fabric application to deploy other Service Fabric applications, it’s called accordingly – Deployment Service. It’s up and running in public and two national cloud environments, works perfectly fine (except huge backlog that that was put on hold and then effectively cut, of course). Initially it consisted of three “classic” layers:

  • Controller (ASP.NET Core)
  • Service (business logic)
  • Repository (CosmosDB)

I’m using Simple Injector as the Dependency Injection container of my choice with active usage of the Decorator pattern.

Having an interface like this for one of the “services” that plays the central role in the application:

public interface IDeploymentService
{
    Task<DeploymentPayload&gt; GetOrCreateDeployment(StartDeploymentRequest request);

    Task<DeploymentPayload&gt; GetDeployment(Guid deploymentId);

    Task CancelDeployment(Guid deploymentId);
}

I ended up with the following hierarchy of classes that implement and/or “decorate” it:

  • IDeploymentServices
  • DeploymentService
  • MultiTenantDeploymentServiceDecorator
  • LoggingDeploymentServiceDecorator

DeploymentService was implemented in a way that its methods called each other and it was working fine. Sooner or later almost every application receives a feature request which often leads to a lot of rethinking and restructuring, it’s called multi-tenancy. I implemented it relatively easily by introducing just yet another decorator, conventionally called MultiTenantDeploymentServiceDecorator.

Now, when a call reaches the bottom of the stack, i.e.:

  1. IDeploymentService.GetOrCreateDeployment(request);
  2. LoggingDeploymentServiceDecorator.GetOrCreateDeployment(request);
  3. MultiTenantDeploymentServiceDecorator.GetOrCreateDeployment(request);
  4. DeploymentService.GetOrCreateDeployment(request);

at DeploymentService then calls to other methods will be to DeploymentService itself as well. What bypasses the multi-tenancy decorator and brakes the functionality:

public sealed class DecoratorService : IDeploymentService
{
    public async Task<DeploymentPayload&gt; GetOrCreateDeployment(StartDeploymentRequest request)
    {
        // this call
        var deployment = await GetDeployment(request.DeploymentId); 
    }

    public async Task<DeploymentPayload&gt; GetDeployment(Guid deploymentId)
    {
        // will jump here 
    }
}

public sealed class MultiTenantDeploymentServiceDecorator : IDeploymentService
{
    public async Task<DeploymentPayload&gt; GetDeployment(Guid deploymentId)
    {
        //  and not here
    }
}

This issue forced me to drop current architecture and redo it in the right way: Command Query Responsibility Segregation (CQRS).

Handlers, commands and queries

After refactoring each service’s method into its own class accepting (handling) its own type of command or query, I ended up with the following classes:

public sealed class StartDeploymentHandler : IRequestHandler<StartDeploymentCommand,  DeploymentPayload&gt;
{
}

public sealed class GetDeploymentHandler : IRequestHandler<GetDeploymentQuery,  DeploymentPayload&gt;
{
}

public sealed class CancelDeploymentHandler : IRequestHandler<CancelDeploymentCommand&gt;
{
}

With single logging decorator (neat!):

public sealed class LoggingHandler<T, TResult&gt; : IRequestHandler<T,  TResult&gt;
{
}

And multi-tenancy decorator wherever it’s applicable:

public sealed class MultiTenantGetDeploymentHandler : IRequestHandler<GetDeploymentQuery,  DeploymentPayload&gt;
{
}

MediatR

Instead of reinventing the wheel, I’m using the interfaces from small, slick and well-designed, open source library called MediatR which implements the Mediator pattern.

So now my ASP.NET Core controller looks like this:

[ApiController]
public sealed class DeploymentController : ControllerBase
{
    private readonly IMediator _mediator;

    public DeploymentController(IMediator mediator) =&gt;  
        _mediator = mediator;

    [HttpPut]
    public async Task<IActionResult&gt; StartDeployment(StartDeploymentRequest request, CancellationToken cancellationToken)
    {
        var command = new StartDeploymentCommand(request);
        var deployment = _mediator.Send(command, cancellationToken);
    }
}

Here’s how its unit test looks like now:

[TestClass]
public class DeploymentControllerTest
{
    [TestMethod]
    public async Task StartDeployment_Should_Return_StatusCode_Accepted_And_State_Queued_When_Deployment_Is_Accepted_And_Queued()
    {
        // Arrange
        var deploymentId = Guid.NewGuid();
        var request = new StartDeploymentRequest
        {
            DeploymentId = deploymentId
        };
        var deploymentPayload = new DeploymentPayload
        {
            DeploymentId = deploymentId
        };

        var mediator = new Mock<IMediator&gt;();
        mediator.Setup(m =&gt; m.Send(It.Is<GetDeploymentQuery&gt;(q =&gt; q.DeploymentId == request.DeploymentId)))
                .ReturnsAsync((DeploymentPayload)null);
        mediator.Setup(m =&gt; m.Send(It.Is<CreateDeploymentCommand&gt;(c =&gt; c.Request == request)))
                .ReturnsAsync(deploymentPayload);

        var controller = new DeploymentController(mediator.Object);

        // Act
        var result = await controller.StartDeployment(request, CancellationToken.None);

        // Assert
    }
}

And it illustrates perfectly the issue with Mediator in general and MediatR in particular: the code that uses it violates, or stops following, even if with good intentions, the SOLID principles. Namely, it’s not possible anymore to tell what are the dependencies of DeploymentController as it stops telling that explicitly. At least not in the design time. I personally find it now an anti-pattern due to the very same reasons to why Service Locator/Inversion of Control is.

Back to injecting handlers

So instead DeploymentController’s constructor now looks like this:

[ApiController]
public sealed class DeploymentController : ControllerBase
{
    public DeploymentController(
        IRequestHandler<StartDeploymentRequest, DeploymentPayload&gt; startDeploymentHandler,
        IRequestHandler<GetDeploymentQuery, DeploymentPayload&gt; getDeploymentHandler,
        IRequestHandler<CancelDeploymentCommand&gt; cancelDeploymentHandler)
    {
    }
}
Posted in Programming | Tagged , | Leave a comment

How to deploy Traffic Manager to a Sovereign cloud using ARM template

On other day I tried to deploy Azure Traffic Manager profile to a sovereign aka national aka government cloud but got an error:

Code: BadRequest
Message: A policy with the requested domain name could not be created because the name example.trafficmanager.net does not end with the expected value .trafficmanager.cn.

That’s it, the error message describes the issue perfectly (what is not always the case for ARM): I used in sovereign cloud for China the domain name for Public. Here’s a way to use the right one:

{
   "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
   "contentVersion": "1.0.0.0",
   "parameters": {
     "resourceName": {
       "type": "string"
     },
     "cloudInstance": {
       "type": "string"
     }
   },
   "variables": {
     "tmApiVersion": "[providers('Microsoft.Network', 'trafficManagerProfiles').apiVersions[0]]",
     "endpointDomainLookup": {
       "Public": "trafficmanager.net",
       "USGov": "usgovtrafficmanager.net",
       "China": "trafficmanager.cn",
       "Germany": "azuretrafficmanager.de"
     },
     "endpointDomain": "[variables('endpointDomainLookup')[parameters('cloudInstance')]]"
   },
   "resources": [
     {
       "type": "Microsoft.Network/trafficManagerProfiles",
       "name": "[parameters('resourceName')]",
       "apiVersion": "[variables('tmApiVersion')]",
       "location": "global"
       "properties": {
         "profileStatus": "Enabled",
         "trafficRoutingMethod": "Priority",
         "dnsConfig": {
           "relativeName": "[parameters('resourceName')]",
           "fqdn": "[concat(parameters('resourceName'), '.', variables('endpointDomain'))]",
           "ttl": 30
         },
         "monitorConfig": {
           "protocol": "HTTPS",
           "port": 443,
           "path": "/ping",
           "intervalInSeconds": 30,
           "toleratedNumberOfFailures": 3,
           "timeoutInSeconds": 10
         }
       }
     },
     {
       "type": "Microsoft.Network/trafficManagerProfiles/externalEndpoints",
       "name": "[concat(parameters('resourceName'), '/', parameters('endpoint1Name'))]",
       "apiVersion": "[variables('tmApiVersion')]",
       "properties": {
         "endpointStatus": "Enabled",
         "target": "[parameters('endpoint1Address')]",
         "weight": 1,
         "priority": 10,
         "endpointLocation": "[parameters('endpoint1Locatiom')]"
       },
       "dependsOn": [ "[parameters('resourceName')]" ]
     },
     {
       "type": "Microsoft.Network/trafficManagerProfiles/externalEndpoints",
       "name": "[concat(parameters('resourceName'), '/Endpoint', parameters('endpoint2Name'))]",
       "apiVersion": "[variables('tmApiVersion')]",
       "properties": {
         "endpointStatus": "Enabled",
         "target": "[parameters('endpoint2Address')]",
         "weight": 1,
         "priority": 20,
         "endpointLocation": "[parameters('endpoint2Location')]"
       },
       "dependsOn": [ "[parameters('resourceName')]" ]
     }
   ]
 }
Posted in Uncategorized | Leave a comment

How to combine Key Vault access policy for AAD application and user-assigned managed identity in single ARM template

On other day I was exploring how to grant access for a user-assigned managed identity to a key vault. But here’s a more advanced scenario: let’s say legacy code uses an AAD application to access the key vault and modern code uses an identity.

How to grant access to either one or another based on some condition? Turns out it’s quite easy:

{
   "accessPolicies":[
     {
       "tenantId":"[variables('tenantId')]",
       "objectId":"[if(empty(parameters('objectId')), reference(concat('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('identityName')), variables('idApiVersion')).principalId, parameters('objectId'))]",
       "permissions":{
         "keys":[
           "Get",
           "List"
         ],
         "secrets":[
           "Get",
           "List"
         ],
         "certificates":[
           "Get",
           "List"
         ]
       }
     }
   ]
 }

In this case if objectId is empty (its default value) then it means the identity shall be used.

Posted in Programming | Tagged , | Leave a comment

How to create user-assigned managed identity, Key Vault, assign access policy using ARM template

There is already a plenty of materials about managed identities in Azure. But how to create a user-assigned managed identity and grant it the access to a key vault using an ARM template? I tried to find any references but to no avail.

First you’ll need a user-assigned managed identity:

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "identityName": {
      "type": "string"
    }
  },
  "variables": {
    "idApiVersion": "[providers('Microsoft.ManagedIdentity', 'userAssignedIdentities').apiVersions[0]]",
    "location": "[resourceGroup().location]"
  },
  "resources": [
    {
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
      "apiVersion": "[variables('idApiVersion')]",
      "name": "[parameters('identityName')]",
      "location": "[variables('location')]"
    }
  ]
}

Then a key vault:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "kvName": {
      "type": "string"
    }
    "identityName": {
      "type": "string"
    }
  },
  "variables": {
    "kvApiVersion": "[providers('Microsoft.KeyVault', 'vaults').apiVersions[0]]",
    "location": "[resourceGroup().location]",
    "tenantId": "[subscription().tenantId]"
  },
  "resources": [
    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "[variables('kvApiVersion')]",
      "name": "[parameters('kvName')]",
      "location": "[variables('location')]",
      "properties": {
        "sku": {
          "family": "A",
          "name": "standard"
        },
        "tenantId": "[variables('tenantId')]",
        "enableSoftDelete": true,
        "enabledForDeployment": true,
        "enabledForTemplateDeployment": true,
        "enabledForDiskEncryption": false,
        "accessPolicies": [
          {
            "tenantId": "[variables('tenantId')]",
            "objectId": "[reference(concat('Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('identityName')), variables('idApiVersion')).principalId]",
            "permissions": {
              "keys": [
                "Get",
                "List"
              ],
              "secrets": [
                "Get",
                "List"
              ],
              "certificates": [
                "Get",
                "List"
              ]
            }
          }
        ]
      }
    }
  ]
}

Voila! The identity has full read-only access to all secrets in the vault.

Due to the limitations of ARM, function reference() cannot be placed inside variables. It’s a runtime function so must be placed inside resources. What in the case of key vault’s access policies limits the options for composition (real programming using ARM) and unnecessarily complicates the template. For example, it’s hard to have an if with two variables. Otherwise, it’s quite simple and straightforward.

Posted in Programming | Tagged , | 1 Comment

How to disable Night mode for Search bar on Android

  1. Turn on Developer options
  2. Go to Developer options, switch Night mode to Always off
Posted in Uncategorized | Leave a comment

How to find out the latest ARM api version for given resource type

If you’d like to find this out, for instance, for Service Fabric applications, then use this query:

((Get-AzureRmResourceProvider -ProviderNamespace Microsoft.ServiceFabric).ResourceTypes | where { $_.ResourceTypeName -eq "clusters/applications" }).ApiVersions

which would yield this result:

2017-07-01-preview
2016-09-01
2016-03-01

what means that you now can go to the GitHub repo with all ARM schemas and find the one you need.

Happy deployments!

Posted in Programming | Tagged , , | Leave a comment

Git aliases to combine fetch in the background and checkout/merge/rebase

I decided to write down few useful Git aliases I’m using every day.

git config --global alias.fetch-master "!git fetch -p && git fetch origin master:master"

git config --global alias.fetch-checkout "!git fetch-master && git rev-parse --abbrev-ref HEAD > .git/BRANCH && git checkout master && git branch -D `cat .git/BRANCH` && rm .git/BRANCH"

git config --global alias.fetch-merge "!git fetch-master && git merge master"

git config --global alias.fetch-rebase "!git fetch-master && git rebase master"

Or how it looks in .gitconfig:

[alias]
  fetch-master = !git fetch -p && git fetch origin master:master
  fetch-checkout = !git fetch-master && git rev-parse --abbrev-ref HEAD > .git/BRANCH && git checkout master && git branch -D `cat .git/BRANCH` && rm .git/BRANCH
  fetch-merge = !git fetch-master && git merge master
  fetch-rebase = !git fetch-master && git rebase master
Posted in Programming | Tagged | Leave a comment

Carnation Anapa Winery, part 3, day 51: Corking

I decided to do not cork shortly before going on vacation and instead wait little more. Now I came back from vacation, measure specific gravity the last time and finally cork.

  • Petite Sirah: 0.992 (0.990 + 1/5)
  • Mourvèdre: 0.992 (0.990 + 1/5)
  • Grenache: 0.990

I bought the last box of green bottles at Mt Si Homebrew Supply and rented handy floor “Itallian” corker for $20/day. A new one they sell for $120 so it looks like a good deal since I need it for only one day in a year.

CAW GPS #1.1, 10.11.2018

  • Grenache: 34%
  • PetiteSirah: 33%
  • Mourvèdre: 33%

CAW GPS #1.2, 10.11.2018

  • Grenache: 45%
  • Petitee Sirah: 38%
  • Mourvèdre: 17%

CAW GPS #1.3, 10.11.2018

  • Grenache: 33%
  • PetiteeSirah: 34%
  • Mourvèdre: 33%

CAW GPS #1.4, 10.11.2018

  • Grenache: 29%
  • PetiteSirah: 26%
  • Mourvèdre: 45%

CAW GPS #1.5, 11.11.2018

  • Grenache: 26%
  • PetiteSirah: 45%
  • Mourvèdre: 29%

CAW M100%, 11.11.2018

  • Mourvèdre: 100%

CAW PS100%, 11.11.2018

  • Petite Sirah: 100%

CAW G100%, 11.11.2018

  • Grenache: 100%

CAW GPS #1.6, 11.11.2018

  • Grenache: 33%
  • PetiteSirah: 34%
  • Mourvèdre: 33%

CAW GPS #1.7, 11.11.2018

  • Grenache: 23%
  • PetiteSirah: 32%
  • Mourvèdre: 45%

That’s it, folks! 10 bottles total. Now let’s wait for few months before starting tasting what I’ve got.

Posted in Winemaking | Tagged | Leave a comment

Carnation Anapa Winery, part 2, day 30: Re-measuring specific gravity

Before going on vacation for 2.5 weeks and leaving the carboys on their own, I’m re-measuring specific gravity to understand where we’re at and when it would be good time to bottle-and-cork:

  • Petite Sirah: 0.994 (0.990 + 2/5)

  • Mourvèdre: 0.992 (0.990 + 1/5)

  • Grenache: 0.986 (0.990 – 2/5)

Posted in Winemaking | Tagged | Leave a comment