Python Coding: FizzBuzz challenge

FizzBuzz is a very common task, asked in Dev/DevOps interviews. You are given a range of numbers and need to write algorithm using the following rules: if the number is divisible by 3, print “Fizz”; if the number is divisible by 5, output “Buzz”; if the number is divisible by both 3 and 5, the result should be “FizzBuzz”.

The main goal of the task is to check how you understand loops, conditionals and simple math using one of programming or scripting languages. I solved the task using PowerShell years ago: check this gist.

As I started to learn Python, I decided to share FizzBuzz implementation in this language to show how simple and “elegant” the solution can be.

I used matplotlib and colorama to make a pie chart and add color text output respectively. Defined a function fizz_buzz with 2 arguments, and then used try/catch/finally statements to catch exceptions errors. Inside of the try, the for loop and if conditionals are described to meet all task’s rules. As a result, the function outputs numbers and categories based on rules, and makes a pie chart to show how many fizz, buzz, fizzbuzz found in percentage.

import matplotlib.pyplot as plt
import colorama
from colorama import Fore, Back, Style
colorama.init()

def fizz_buzz(x,y):
    """Python version of popular Fizz Buzz task"""
    fb = 0 ; b = 0; f = 0; rest = 0 # start values
    fb_type = ['fizzbuzz','fizz','buzz','rest'] # plot labels
    fb_colors = ['r','y','c','g'] # plot colors
    fb_explode = [0.2, 0.1, 0.1, 0.1] # plot fraction of the radius
    try:
        for n in range(x,y):
            if ((n % 3 == 0) and (n % 5 == 0)):
                fb += 1
                print(Fore.RED + f"Found FizzBuzz: {n}")
            elif n % 3 ==0:
                f += 1
                print(Fore.WHITE + f"Found Fizz: {n}")
            elif n % 5 ==0:
                b += 1
                print(Fore.GREEN + f"Found Buzz: {n}")
            else: 
                rest += 1
                print(Style.BRIGHT + f"The rest is {n}")
            print(Style.RESET_ALL)
        fb_array = [fb, f, b, rest]
        plt.pie(fb_array, colors = fb_colors, explode = fb_explode, shadow = True, radius = 1.1, autopct = '%1.1f%%') # form a pie
        plt.legend(fb_type,loc='upper right') # show legend
        plt.show() # show a pie
    except:
        print(Style.BRIGHT + Fore.RED + "You provided wrong x and y")
        print(Style.RESET_ALL)
    finally:
        print(Style.BRIGHT + Fore.GREEN + "Author: github.com/rlevchenko")
        print(Style.RESET_ALL)

Result

Available at Gist

Azure DevOps: Update service connection expired secret

If you’re reading this post, you’re trying to find a way to edit an existing service connection with a new service principal secret/key.

It’s a weird that UI and devops cli don’t allow us to quickly change service connection details if it was created automatically by Azure DevOps (“creationMode”: “Automatic”; will talk about it a bit later).

So, how to change a secret? Answer: Azure DevOps REST API.
Note: if you have correct permissions, try out the steps at the bottom of the post. The steps below are for those who don’t have Owner permissions.

  • Create a new Personal Access Token (full access and all scope, expiration 1 day)
  • Go to Project Settings – Service Connections, choose your connection and click on Manage Service Principal. Add a new secret and note it’s value.
  • Choose a tool to work with REST API. It could be either PowerShell or Postman, for instance. I will show both.
  • [Postman] Install Postman and create a new HTTP Request
Postman – File – New – HTTP Request
  • [Postman] Go to Authorization and paste PAT token to the password field
PAT token should be used as password for any REST API requests
  • [Postman] Using the following GET request, get a service endpoint details in JSON format. Organization Name, Project Name and Endpoint Name are parts of the URI (can be taken from service connections list in the azure devops ui) :

    https://dev.azure.com/<orgName>/<ProjectName>/_apis/serviceendpoint/endpoints?endpointNames=<Endpoint Name> &api-version=6.0-preview.4
  • [Postman] Copy everything from the response under the value as shown below
{
            "data": {
                "subscriptionId": "",
                "subscriptionName": "",
                "environment": "AzureCloud",
                "scopeLevel": "Subscription",
                "creationMode": "Automatic",
                "azureSpnRoleAssignmentId": ""
            },
            ...............
                }
            ]
}
  • [Postman] Using a PUT request update the service connection. Make sure you set Body – Raw to JSON , and then Paste JSON copied in the previous step to the Body
Body – RAW should be set to JSON
  • Here is a tricky part. Prior to sending PUT request, change creationMode from “Automatic” to “Manual”. Also, in my case, I had to delete the following parameters spnObjectId and appObjectId (data section). Plus, I added serviceprincipalkey with a value set to a new secret (authorization section)
    A short excerpt is provided below:
{
    "data": {
        "subscriptionId": "",
        "subscriptionName": "",
        "environment": "AzureCloud",
        "scopeLevel": "Subscription",
        "creationMode": "Manual",  # changed
        "azureSpnRoleAssignmentId": "",
        "azureSpnPermissions": ""
         spnObjectId # deleted
         appObjectId # deleted
    },
    "description": "",
    "authorization": {
        "parameters": {
            "tenantid": "",
            "serviceprincipalid": "",
            "authenticationType": "spnKey",
            "serviceprincipalkey": "secret here" # added
        },
        "scheme": "ServicePrincipal"
}
}
  • [Postman] URI used for a PUT request: https://dev.azure.com/OrganizationName/_apis/serviceendpoint/endpoints/EndpointId?api-version=6.0-preview.4
  • [Postman] Go back to Azure DevOps and make sure that service connections has been updated and ready to use.

  • [PowerShell] Use the following example
$token ="PAT Token"
$orgName = "Organization Name"
$projectName = "Project Name"
$endpointName = "your endpoint"
$endpointId = "your endpoint ID, use GET request or UI"
$header = @{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($token)")) }

# Get Endpoint details

Invoke-RestMethod -Method GET -URI "https://dev.azure.com/$($orgName)/$($projectName)/_apis/serviceendpoint/endpoints?endpointNames=$($endpointName)&api-version=6.0-preview.4" -Headers $header -ContentType "application\json"

# Update Endpoint
$json = @{ json here } | ConvertTo-Json -Depth <your depth>
Invoke-RestMethod -Method PUT -URI "https://dev.azure.com/$($OrgName)/_apis/serviceendpoint/endpoints/$($endpointId)?api-version=6.0-preview.4" -Body -Headers $header -ContentType "application\json" -Body $json


That’s it. Now you know how to change a service connection with a new secret without removing a connection and customizing all pipelines in a project.

P.S. If you have Owners permissions on the app registration/service principal used by the connection, try to edit the connection by adding a description, and then click on Save. Azure DevOps should create a new secret and update the connection automatically.

%d bloggers like this: