Force majeure and the Township Solid Waste District

We attended a “Candidates Night” event last night where the two individuals on the ballot for a Trustee position spoke and took questions. Where most local elections don’t have much in the way of issues, this particular election may be a proxy vote for the single-hauler solid waste district because the incumbent was involved in the entire process and voted to establish a Solid Waste District that allows only one trash hauler. And indicated that she didn’t see anything wrong with the way the decision was approached.

There were two justifications provided for this decision — both financial. Individuals who have rubbish service will pay less for their service because the Township is essentially facilitating a bulk-purchase agreement. The company is going to drive the same number of miles but 100% of the houses will be their customer. The other stated motivation is reducing road repair costs. Not because the Trustees provided any evidence that rubbish trucks cause a significant amount of damage to roads (although I’ve been told it’s common sense that big trucks cause a lot of damage … there are four, I think, companies that collect rubbish in the area. Commercial rubbish collection is out of scope, so those companies are still going to be driving on some of the roads. What percentage of road damage is done by three rubbish trucks a week compared to vehicle traffic, delivery trucks, snow plows, freeze/thaw cycles? And that’s assuming the single hauler doesn’t need to increase the number of trucks/trips to collect all residential waste — which I doubt is true. We’re more likely to net remove one or two large trucks a week from the roads.). But when I asked what metrics would be provided to show that this cost savings would be realized, the incumbent candidate replied “I don’t think residents want to fund an expensive study about what roads needed repairs and how much it costs”. Which is a senseless non-answer — they’ve got a projected service department budget for next year. And hopefully the year after that. They’ve got historic actual numbers for decades. Take next year’s actual and compare it to the budget. How’s that compare to, say, the difference between last year’s actual and forecasted budgets?

But the oddest part of the night was when a resident asked about people whose existing contracts are a problem — either their current rubbish service will stop collecting trash a month before this single-hauler contract begins, their annual contract is up a month or three before the single-hauler contract begins and they’re not going to be able to renew, or their contract extends beyond the single-hauler start date. The first two scenarios are answered easily enough — the company that’s been chosen as the rubbish collector has agreed to start collecting “early” at rack-rate. So you “get” to buy service from the company you didn’t want at the price you didn’t want. The incumbent indicated that people whose contracts extend beyond the single-hauler start date won’t have to pay early termination penalties because of force majeure. Now maybe she’s actually seen residential contracts from each of the rubbish collectors that operate in this Township. We haven’t had rubbish service for years because we compost & recycle. The remaining trash (generally Styrofoam), we can drop off once a year at the county dump for like 1.50$. But in the contract we did have, force majeure was specifically protection for the trash hauler — they are not in breach for failing to collect rubbish in the middle of a hurricane, during a strike, etc. Courts tend to interpret force majeure clauses narrowly. If the hauler wants to push the issue … I doubt there’s a clause about government action freeing the resident from fulfilling their contractual duties. You’d be making an argument under common law contract doctrine.

But there’s no need to put yourself in a defensive position. The hauler will elect either to cease operation in the Township or incur penalties for continued residential rubbish collection. As a customer, you aren’t the one seeking to breach the contract. The hauler’s failure to act on their contractual duties may fall under a specific item within a force majeure clause. Or they may consider their duty voided under “frustration of purpose”. Call it “impracticability” because of the fines. It’s not like a resident needs to fight to compel their old hauler to continue their contractually-obligated duties that the hauler needs to defend their withdraw as a specifically permitted action. A resident needs the hauler to be the one who withdraws from the contract.

Testing Procedural Code with PHPUnit

You can use PHPUnit to test procedural code — in this case, I’m testing the output of a website. I have some Selenium tests for UI components but wanted to use the shell executor for functional testing. In the test code, you can populate the _SERVER and _POST (or _GET) arrays and simulate the web environment.

<?php
    namespace phpUnitTests\CircuitSearch;
    class CircuitExportTest extends \PHPUnit_Framework_TestCase{
        private function _execute(array $paramsPost = array(), array $paramsServer = array() ) {
            $_POST = $paramsPost;
            $_SERVER = $paramsServer;
            ob_start();
            include "../../myWebSitePage.php";
            return ob_get_clean();
        }
        public function testUsageLogging(){
            $argsPost = array('strInput'=>'SearchValue', 'strReportFormat'=>'JSON');
            $argsServer = array("DOCUMENT_ROOT" => '/path/to/website/code/html/', "HOSTNAME" => getHostByName(),
                                "SERVER_ADDR" => getHostByName(php_uname('n')), "PWD" => '/path/to/website/code/html/subcomponent/path');
            $this->assertEquals('{}', $this->_execute($argsPost, $argsServer));
        }
    }
?>

Running the test, my web output is compared to the static string in assertEquals. In this case, I am searching for a non-existent item, nothing is returned, and I expect to get empty braces. I could use AssertsRegExp or or AssertsStringContainsString to verify the specifics of a real result set.

Docker for Windows: Using Built-in k8s

I just started using k8s built into Docker for Windows, but I couldn’t connect because the target machine actively refused the connection.

C:\Users\lisa>kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.6", GitCommit:"96fac5cd13a5dc064f7d9f4f23030a6aeface6cc", GitTreeState:"clean", BuildDate:"2019-08-19T11:13:49Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"windows/amd64"}
Unable to connect to the server: dial tcp [::1]:8080: connectex: No connection could be made because the target machine actively refused it.

No idea — it’s all internal traffic, but I resorted to turning off my firewall anyway just to see what would happen. Nothing. Turns out I need a KUBECONFIG environment variable pointing to the config file

C:\Users\lisa>set | grep KUB
KUBECONFIG=C:\Users\lisa.RUSHWORTH.000\.kube\config

Applied the yaml file and started the proxy

C:\Users\lisa>kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
secret/kubernetes-dashboard-certs created
serviceaccount/kubernetes-dashboard created
role.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard-minimal created
deployment.apps/kubernetes-dashboard created
service/kubernetes-dashboard created

C:\Users\lisa>kubectl proxy
Starting to serve on 127.0.0.1:8001

Working! Get the token from

kubectl -n kube-system describe secret default

And access the dashboard.

 

A reminder for myself — the totally not obvious package name for the kubeadm binary on the CHANGELOG link list is Node. Go figure!

Python f-strings

I’m accustomed to using variables directly in strings — most of my scripting experience was with Bash, Perl, and PHP. It’s something I have to think about when I would write Java or C++ code, and it’s one of the few things that struck me as a step backward in Python. This is basically the advantage that kwargs have over args, except changing a string common where changing a function definition is pretty rare.

I’ve taken to using the arg identifier numbers in the print statement.

>>> first=”Lisa”
>>> last=”Rushworth”
>>> print(“Hi {0}, you are {0} {1}.”.format(first, last))
Hi Lisa, you are Lisa Rushworth.

This allows me to append a new variable to the format argument list and use it anywhere in the string
>>> salutation=”Hello”
>>> print(“{2} {0}, you are {0} {1}.”.format(first, last, salutation))
Hello Lisa, you are Lisa Rushworth.

Python 3 introduced f-strings, which go beyond the functionality I was missing. You *can* use variable names within the string:

>>> print(f”{salutation} {first}, you are {first} {last}”)
Hello Lisa, you are Lisa Rushworth

You can have multi-line strings — notice that newlines aren’t being magically added. If you *want* newlines, add \n!

>>> strString = (
… f”{salutation} {first}, ”
… f”You are {first} {last} ”
… f”And I have more ”
… f”data down here”
… )
>>> print(strString)
Hello Lisa, You are Lisa Rushworth And I have more data down here

But you can also perform operations:
>>> print(f”{2 ** 3}”)
8

And use the f-string in classes
>>> class MyThing:
… def __init__(self, thing1, thing2, thing3):
… self.thing1 = thing1
… self.thing2 = thing2
… self.age = thing3

… def __str__(self):
… return f”{self.thing1} has 2 {self.thing2} and 3 {self.age}.”

>>>
>>> thingSample = MyThing(“Something1”, “Something2”, “Something3″)
>>> print(f”{thingSample}”)
Something1 has 2 Something2 and 3 Something3.

What if you need to have a literal curly brace?
>>> print(f”Hi {first}, this output needs a {{curly brace}}”)
Hi Lisa, this output needs a {curly brace}

VS Code Keyboard Shortcut: Commenting

We’ve been watching Microsoft’s Python programming course series — only the first couple so far, so it’s a lot of “yeah, knew that”. *But* there’s the occasional cool tip. You can comment line(s) of code with a keyboard shortcut:

Ctrl k,c comment current line (or selection)
Ctrl k,u uncomment current line (or selection)

 

Highlight the section of code that you want to comment out.

Hit ctrl-k and then ctrl-c … voila, a whole section of commented code. Denoting a comment is language specific, so this does not do anything if VS Code has not yet identified the language for your file.

To remove comments, use ctrl-k then ctrl-u. This works with code that already includes comments – you’ll get an additional comment in front of the commented line, and that additional comment will be removed leaving a commented line.

yEd: Item Alignment

I’ve been using yEd as a free not-quite-Visio, and happened across a feature that I love — as you move items around, little marks pop up when things are lined up and with multiple alignments? When they’re equidistant.

And once you have something lined up and equidistant, you can hold the shift key and drag the item to move it along one axis. In this case, I wanted the middle circle to be, well, in the middle. But I didn’t want it on the same horizontal line, so I was able to drag it up without losing the vertical spacing.

yEd Color Gradient

I don’t want to buy Visio — for one thing, I’m using it for work, and I don’t want to buy anything for work. But I don’t use Visio frequently enough to warrant paying for a license. I tried a few open source iterations with no success (OpenOffice Draw gave me the exact feeling I remember when trying to use the spreadsheet product — halfway there, but missing a LOT of features that are important to me). I happened across a free-but-not-open-source program called yEd. It’s got a basic shape gallery, I can draw lines between shapes, I can add labels to my lines and shapes. Perfect!

Their sample diagram, though, had a cool gradient effect. Not something I’m apt to use on a serious diagram … but I wanted to know how to achieve the same look. A lot of clicking later:

Select two nodes where the gradient starts. Select “Tools” => “Colorize Graph”. On the “General” tab, set “Highlight Feature” to “Graph Distance”. On the “Graph Distance” tab, ensure “Rainbow Interpolation” is unchecked. Pick your starting color, ending color, and a max distance (I used 250). Apply and you’ll have a vertical gradient across your document.

Certificate Generation Script

I finally put together a script that gathers some basic information (hostname & SAN’s) and creates a certificate signed against my CA. I’ve got a base myssl.cnf file that ends with

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]

The script appends all of the alternate names to the myssl.cnf file.

#!/bin/bash

RED_DARK='\033[38;5;196m'
GREEN_DARK='\033[38;5;35m'
BLUE_DARK='\033[38;5;57m'
NC='\033[0m' # Reset

function getInput {
        echo -e "${BLUE_DARK}Please input the short hostname you wish to use (e.g. server123):${NC}"
        read HOST

        echo -e "${BLUE_DARK}Please input the domain name you wish to use with this hostname (e.g. rushworth.us):${NC}"
        read DOMAIN

        echo -e "${GREEN_DARK}Please enter any SAN values for this certificate, separated by spaces (must be fully qualified):${NC}"
        read SANS

        FQHOST="${HOST}.${DOMAIN}"

        echo -e "Short hostname: $HOST"
        echo -e "Fully qualified hostname: $FQHOST"
        echo -e "SAN: $SANS"

        echo -e "${RED_DARK}Is this correct? (Y/N):${NC}"
        read boolCorrect

        if [ $boolCorrect == 'Y' ] || [ $boolCorrect == 'y' ]
        then
                mkdir $HOST
                echo $HOST
                cp myssl.cnf "./$HOST/myssl.cnf"

                cd "./$HOST"

                echo "The following SANs will be used on this certificate: "
                echo "DNS.1 = ${FQHOST}"
                echo "DNS.1 = ${FQHOST}" >> ./myssl.cnf
                echo "DNS.2 = ${HOST}"
                echo "DNS.2 = ${HOST}" >> ./myssl.cnf

                if [ -n "$SANS" ]
                then
                        SANARRAY=( $SANS )
                        iSANCounter=2
                        for SANITEM in "${SANARRAY[@]}" ; do
                                let iSANCounter=iSANCounter+1
                                echo "DNS.${iSANCounter} = ${SANITEM}"
                                echo "DNS.${iSANCounter} = ${SANITEM}" >> ./myssl.cnf
                        done
                fi
                export strCertKeyPassword=Wh1t2v2rP144w9rd
                export strPFXPassword=123abc456
                openssl genrsa -passout env:strCertKeyPassword -aes256 -out $FQHOST.passwd.key 2048
                openssl req -new -key $FQHOST.passwd.key -passin env:strCertKeyPassword -config ./myssl.cnf -reqexts req_ext -out $FQHOST.csr -subj "/C=US/ST=Ohio/L=Cleveland/O=Rushworth/OU=Home/CN=$FQHOST"
                openssl x509 -req -in $FQHOST.csr -passin env:strCertKeyPassword -extensions req_ext -extfile ./myssl.cnf -out $FQHOST.cer -days 365 -CA /ca/ca.cer -CAkey /ca/ca.key -sha256
                openssl rsa -in $FQHOST.passwd.key -out $FQHOST.key -passin pass:$strCertKeyPassword -passin env:strCertKeyPassword
                openssl pkcs12 -export -out $FQHOST.pfx -inkey $FQHOST.key -in $FQHOST.cer -passout env:strPFXPassword

        else
                getInput
        fi
}

getInput

There’s an encrypted private key and a non-encrypted private key. Because I have some Windows servers — Exchange and Active Directory — I create a PFX file too.