Monday, 20 December 2021

IBM Key Protect - Computer says "No"

Whilst tinkering with IBM Key Protect, the computer was most definitely saying "No" 

ic kp keys --instance-id $guid

Retrieving keys...

FAILED

kp.Error: correlation_id='8638482c-706f-4959-9d39-cb583f4e7692', msg='Unauthorized: The user does not have access to the specified resource'

Thankfully, the internet had the answer ( the internet is my friend ) : -


The error is actually described in the introduction to ibm_kms_key, but easily overread. The set region for the provider currently has to match the region of the KMS instance.

The referenced Terraform provider documentation - ibm_kms_key - adds some context: -

The region parameter in the provider.tf file must be set. If region parameter is not specified, us-south is used as default

I double-checked where my Key Protect instance was located: -

ic resource service-instances --output JSON | jq -r '.[] | select(.name | endswith("kms"))' | jq -r .region_id

eu-gb

and directed the CLI tool to target that region: -

ic kp region-set eu-gb

OK

and retried my command: -

ic kp keys --instance-id $guid

Retrieving keys...
OK
Key ID                                 Key Name   
595e2c8e-f99c-45c0-82c3-997dd646dcf3   terraform-state-key-davehay-1638264407   

Good to go!

JQ and output control and searching ... I must remember this

As per many many previous posts, I'm continuing to learn - and love - jq.

One thing that's especially useful is the ability to be able to corral multiple facets together using the pipe ( | ) symbol, especially when searching/listing.

I did, however, fall into a trap this AM.

So I'm querying my IBM Cloud account for a Key Protect instance: -

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name} | select(.name | endswith("kms"))'

which resulted in: -

jq: error (at <stdin>:77): endswith() requires string inputs

So what did I do wrong ?

To break it down, this is what I'm doing: -

List my IBM Cloud Service Instances

ic resource service-instances

Print the output in JavaScript Object Notation (JSON)

ic resource service-instances --output JSON

Parse the output via jq

ic resource service-instances --output JSON | jq

Strip out double-quotes where possible ( i.e. raw text )

ic resource service-instances --output JSON | jq -r

Inspect the array that comprises the output

ic resource service-instances --output JSON | jq -r

Only print the name field, aka .name, *AND* format it as Name

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name}

Use the name field for a select ( search )

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name} | select(.name

Look at the end of the name field, for the characters "kms" - short for Key Management System

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name} | select(.name | endswith("kms"))'

and that's where the borkage occur...

Can you see what I did wrong ?

I asked jq to format the output of the .name field as Name, and then tried to search the output for .name ....

In this case, jq is reformatting the output JSON from .name to .Name ...

Here's an example with the search removed: -

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name}'

{
  "Name": "davehay-1638264407-kms"
}
{
  "Name": "davehay-1638264407-state"
}

Once I changed my search: -

ic resource service-instances --output JSON | jq -r '.[] | {Name: .name} | select(.Name | endswith("kms"))'

{
  "Name": "davehay-1638264407-kms"
}

I'm good to go ....

Sunday, 19 December 2021

Don't be blue - debugging Bluetooth in macOS Monterey

Having noticed that Apple quietly removed Reset the Bluetooth module option: -

in macOS 12 Monterey, I was pleased to "discover" that there is the "nuclear" option of kill the Bluetooth stack, via: -

sudo pkill bluetoothd

before rebooting.

For the record, I have NOT yet tried this, but I trust the source of this tip, namely 9to5mac.com : -


But, of course, YMMV

There's also this: -


from Apple themselves

Wednesday, 15 December 2021

More fun with JQ - formatting

Following on from prior posts, a bit more tinkering with JQ, this time formatting the output.

So here's my starting point, a JSON document: -

simpsons.json 

[

    {

        "givenName": "Maggie",

        "familyName": "Simpson"

    },

    {

        "givenName": "Lisa",

        "familyName": "Simpson"

    },

    {

        "givenName": "Marge",

        "familyName": "Simpson"

    },

    {

        "givenName": "Homer",

        "familyName": "Simpson"

    },

    {

        "givenName": "Bart",

        "familyName": "Simpson"

    }

]

and here's my going through it and formatting the output: -

cat simpsons.json | jq -r '.[] | {"Given Name": .givenName, "Family Name": .familyName}'

{

  "Given Name": "Maggie",

  "Family Name": "Simpson"

}

{

  "Given Name": "Lisa",

  "Family Name": "Simpson"

}

{

  "Given Name": "Marge",

  "Family Name": "Simpson"

}

{

  "Given Name": "Homer",

  "Family Name": "Simpson"

}

{

  "Given Name": "Bart",

  "Family Name": "Simpson"

}

and here's an example, searching for given names beginning with "M" and then formatting the output: -

cat simpsons.json | jq -r '.[] | select(.givenName | startswith("M")) | {"Given Name": .givenName, "Family Name": .familyName}'

{

  "Given Name": "Maggie",

  "Family Name": "Simpson"

}

{

  "Given Name": "Marge",

  "Family Name": "Simpson"

}

Note that, in both examples, I wrap the to-be-displayed "labels" in double-quotes because they have space characters therein.

Otherwise, JQ is sick: -

cat simpsons.json | jq -r '.[] | select(.givenName | startswith("M")) | {Given Name: .givenName, Family Name: .familyName}'

jq: error: syntax error, unexpected IDENT, expecting '}' (Unix shell quoting issues?) at <top-level>, line 1:
.[] | select(.givenName | startswith("M")) | {Given Name: .givenName, Family Name: .familyName}                                                    
jq: error: May need parentheses around object key expression at <top-level>, line 1:
.[] | select(.givenName | startswith("M")) | {Given Name: .givenName, Family Name: .familyName}                                              
jq: error: syntax error, unexpected IDENT, expecting '}' (Unix shell quoting issues?) at <top-level>, line 1:
.[] | select(.givenName | startswith("M")) | {Given Name: .givenName, Family Name: .familyName}                                                                             
jq: error: May need parentheses around object key expression at <top-level>, line 1:
.[] | select(.givenName | startswith("M")) | {Given Name: .givenName, Family Name: .familyName}                                              
jq: 4 compile errors

Tuesday, 7 December 2021

Fun with Python and PyEnv on macOS

Via the Advent of Code 2021 I've been doing more with Python on macOS, and was struggling with versions, given that Apple kindly include Python 2 embedded in the OS, whereas I needed Python 3.10.0 for the work that I was doing.

This was of use: -

How to Install Python 3 on Mac – Brew Install Update Tutorial

and introduced me to PyEnv via Homebrew: -

brew install pyenv

One thing that didn't work was the way that PyEnv sets up $PATH in terms of different Python versions.

Looking at this: -

cat ~/.pyenv/version

I could see: -

3.10.0

but I couldn't initially work out how to add this to my PATH.

PyEnv uses the concept of a shim, as defined in: -

pyenv works by inserting a directory of shims at the front of your PATH:

$(pyenv root)/shims:/usr/local/bin:/usr/bin:/bin

Through a process called rehashing, pyenv maintains shims in that directory to match every Python command across every installed version of Python—python, pip, and so on.

Shims are lightweight executables that simply pass your command along to pyenv. So with pyenv installed, when you run, say, pip, your operating system will do the following:

    Search your PATH for an executable file named pip
    Find the pyenv shim named pip at the beginning of your PATH
    Run the shim named pip, which in turn passes the command along to pyenv


The first article describes how to setup $PATH: -

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile

This didn't work for me for one simple reason - I don't have $PYENV_ROOT/bin : -

ls $PYENV_ROOT/bin

ls: /Users/hayd/.pyenv/bin: No such file or directory

However, I do have $PYENV_ROOT/shims: -

ls $PYENV_ROOT/shims

2to3 easy_install-3.7 pip pydoc python-config python3.10-gdb.py python3.7m-config
2to3-3.10 idle pip3 pydoc3 python3 python3.7 pyvenv
2to3-3.7 idle3 pip3.10 pydoc3.10 python3-config python3.7-config pyvenv-3.7
autopep8 idle3.10 pip3.7 pydoc3.7 python3.10 python3.7-gdb.py
easy_install idle3.7 pycodestyle python python3.10-config python3.7m

Therefore, I setup ~/.bash_profile accordingly : -

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/shims:$PATH"
if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi

And now I have Python 3.10 

python3 --version

Python 3.10.0

For the record, this helped massively: -

 As Vadorequest said, if pyenv is installed using homebrew, you have to add $PYENV_ROOT/shims to the path as $PYENV_ROOT/bin does not exist. I think that is unique to homebrew installs of pyenv. 


Thursday, 2 December 2021

Automated creation of a Red Hat OpenShift cluster on IBM Cloud using the existing CLIs and plugins

Talking of plugins, this is my post pluggin' someone else's blog: -

Automated creation of a Red Hat OpenShift cluster on IBM Cloud using the existing CLIs and plugins

This blog post is about automating the creation of a Red Hat OpenShift cluster on IBM Cloud in a Virtual Private Cloud. I used bash scripting with the IBM Cloud CLI and and the associated IBM Cloud CLI plugins vpc-infrastructure and kubernetes-service. I also use jq to handle json output.

Thomas Suedbroecker is an IBM colleague, and this definitely worth a read.....

Wednesday, 1 December 2021

A reminder - querying Kubernetes nodes by their labels

I have a requirement to inspect a particular label of the nine nodes that comprise my Kubernetes ( actually Red Hat OpenShift Container Platform ) cluster.

The label in question is ibm-cloud.kubernetes.io/worker-id as the OCP cluster is hosted on IBM Cloud.

Here's up with what I ended: -

kubectl get nodes --output wide --label-columns ibm-cloud.kubernetes.io/worker-id | grep -v NAME | awk '{print $12}'

and here's the JSON / jq variant: -

kubectl get nodes --output JSON --label-columns ibm-cloud.kubernetes.io/worker-id | jq '.items[].metadata.labels.ibm-cloud.kubernetes.io/worker-id'

which borks with: -

jq: error: cloud/0 is not defined at <top-level>, line 1:

.items[].metadata.labels.ibm-cloud.kubernetes.io/worker-id                             

jq: error: worker/0 is not defined at <top-level>, line 1:

.items[].metadata.labels.ibm-cloud.kubernetes.io/worker-id                                                 

jq: error: id/0 is not defined at <top-level>, line 1:

.items[].metadata.labels.ibm-cloud.kubernetes.io/worker-id                                                        

jq: 3 compile errors

Ewww, hang on

This helps: -


TL;DR: the answer is: -

If the key contains special characters or starts with a digit, you need to surround it with double quotes like this: ."foo$", or else .["foo$"]

So, here's an amended version: -

kubectl get nodes --output JSON --label-columns ibm-cloud.kubernetes.io/worker-id | jq '.items[].metadata.labels."ibm-cloud.kubernetes.io/worker-id"'

which does the trick.

I love the internet ....

Tuesday, 30 November 2021

Every day is a school day - Bash and macOS and aliases etc.

 So I've been using Bash on various Unices for the longest time - I think I started with BSD back in the late 90s, and then switched to various distributions of Linux, via AIX, and now mainly working with macOS ( which is kinda BSD / Darwin ) and Ubuntu.

Anyway, that's the scene setting out of the way ...

I've got a whole load of aliases set up in my Mac's shell, via ~/.bash_profile - examples include: -

alias hist='history | cut -c 8-'

alias ic='/usr/local/bin/ibmcloud'

alias coverage='go test ./... -coverprofile coverage.out && go tool cover -html=coverage.out'

etc.

So I've been writing a Bash script to query my IBM Cloud account and list out the various resources that I've created, including OpenShift Container Platform (OCP) clusters, Virtual Private Clouds (VPC), subnets, security groups etc.

And I wanted this script to use my alias for the ibmcloud command-line interface (CLI) tool, namely ic ...

As an example: -

#!/usr/bin/env bash
ic version

but, when I ran this, I saw: -

./foo.sh: line 3: ic: command not found

I changed my script to dump out my aliases: -

#!/usr/bin/env bash
echo "My aliases are : "
alias
ic version

which returned: -

My aliases are :

./foo.sh: line 6: ic: command not found

Thankfully, Google came to my aid ...

So today I learned ...

1. There's a difference between .bash_profile and .bashrc

.bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.

Source: What is the difference between .bash_profile and .bashrc?

So, really, I should be putting my aliases in .bashrc rather than .bash_profile ...

Or duplicating them #yuck

2. I can choose to source .bash_profile from .bashrc meaning that non-interactive shells will pick it up

3. If I add: -

#!/usr/bin/env bash -I

and: -

shopt -s expand_aliases

to my Bash script, I can get the best of all worlds.

Therefore, my test script now looks like this: -

#!/usr/bin/env bash -i

alias

shopt -s expand_aliases

echo "My aliases are : "
alias

ic version

and (a) returns all of my aliases and (b) works 

So I have added: -

if [ -f ~/.bash_profile ]; then
    source ~/.bash_profile
 fi

to ~/.bashrc and also changed my scripts to include: - 

#!/usr/bin/env bash -i

and: -

shopt -s expand_aliases

Thursday, 25 November 2021

And even more sed fun - inserting a file into a file ...

Following on from an earlier post: -

More fun with sed

I can also choose to insert a whole block of text: -

cat insert.txt

  backend "s3" {
    bucket                      = "$bucket"
    endpoint                    = "$endpoint"
    force_path_style            = true
    skip_region_validation      = true
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    key                         = "$object"
    region                      = "$REGION"
  }

into an existing Terraform file: -

cat version.tf

terraform {
  required_providers {
    aws = {
      version = ">= 2.7.0"
      source = "hashicorp/aws"
    }
  }
}

as follows: -

sed -i '/terraform {/ r insert.txt' version.tf

which gives us the following: -

cat version.tf
 
terraform {
  backend "s3" {
    bucket                      = "$bucket"
    endpoint                    = "$endpoint"
    force_path_style            = true
    skip_region_validation      = true
    skip_credentials_validation = true
    skip_metadata_api_check     = true
    key                         = "$object"
    region                      = "$REGION"
  }

  required_providers {
    aws = {
      version = ">= 2.7.0"
      source = "hashicorp/aws"
    }
  }
}

Nice!

More fun with sed

Problem to be solved - I was looking for a way to insert a line into a file ( it's actually related to Terraform but, for the purpose of illustration, it's just a text file ), using sed.

Here's a sample text file: -

cat simpsons.txt 

Bart
Homer
Lisa
Maggie
Marge

and I want to add a new cast member called, imaginatively, "Dave" into the list, between "Bart" and "Homer".

Here's how I can do it in sed : -

sed -i'' '/^Bart/a Dave' simpsons.txt

cat simpsons.txt

Bart
Dave
Homer
Lisa
Maggie
Marge

Of course, with a basic list of text, I could've just as easily appended "Dave" to the list, and sort it: -

echo "Dave" >> simpsons.txt && sort simpsons.txt --output simpsons.txt

cat simpsons.txt

Bart
Dave
Homer
Lisa
Maggie
Marge

but that doesn't work too well with a structured file.

Let's use a Terraform file for illustration: -

cat version.tf
 
terraform {
  required_providers {
    aws = {
      version = ">= 2.7.0"
      source = "hashicorp/aws"
    }
  }
}

where I want to insert backend "s3" immediately after terraform but indented with two spaces: -

sed -i'' '/^terraform/a \ \ backend "s3" {}' version.tf

which results in a nicely updated file: -

cat version.tf 

terraform {
  backend "s3" {}
  required_providers {
    aws = {
      version = ">= 2.7.0"
      source = "hashicorp/aws"
    }
  }
}

I <3 sed

Monday, 22 November 2021

Today I Learned - use nettop on macOS to see what's eating your network stack

One of my IBM colleagues drew my attention to nettop 

NAME

     nettop – Display updated information about the network


SYNOPSIS

     nettop [-ncd] [-m <mode>] [-t <type>] [-s <seconds>] [-p <process-name|pid>] [-n] [-l <samples>] [-L <samples>] [-P]

            [-j|k|J <column-name[,column-name]...>]


DESCRIPTION

     The nettop program displays a list of sockets or routes. The counts for network structures are updated periodically.

I've already started using this to see what Slack, Firefox etc. are doing, in terms of chatting away ....

Awesome!

Monday, 15 November 2021

Continuing to love jq - more on selections

I'm using jq more and more now, and continue to love it the more I get to know it ...

This time around, I'm looking at selecting data based upon text patterns.

Here's an example: -

cat simpsons.json | jq .

[
  {
    "givenName": "Maggie",
    "familyName": "Simpson"
  },
  {
    "givenName": "Lisa",
    "familyName": "Simpson"
  },
  {
    "givenName": "Marge",
    "familyName": "Simpson"
  },
  {
    "givenName": "Homer",
    "familyName": "Simpson"
  },
  {
    "givenName": "Bart",
    "familyName": "Simpson"
  }
]
Say I want to find all the family members whose first name ( aka givenName ) begins with "Ma" and ends with "e" ?

JQ has the tools for that, as part of the select() tool, namely startswith and endswith.

Here's it in action: -

cat simpsons.json | jq -r '.[].givenName | select(startswith("Ma") and endswith("e"))' 

Maggie
Marge

If I want to narrow that down to only include first names that end with "ie", then here goes: -

cat simpsons.json | jq -r '.[].givenName | select(startswith("Ma") and endswith("ie"))' 

Maggie

Now obviously this is a very trivial example, but I've been using this to great effect with the IBM Cloud CLI tool, whilst tinkering with OpenShift Container Platform (OCP) clusters, Cloud Object Storage buckets and secrets.

Of course I could use grep and awk but why.... jq can do it all 🤪

Which is nice....

Friday, 12 November 2021

Keeping my skills from getting rusty - by tinkering with Rust

A friend was looking for a way to define a function in Rust outside of the module upon which he was working, using the tried n' approved method of creating a "library" of re-usable functions.

I'd not done this before, so was happy to jump in and have a play.

This is with what I ended up: -

Create a new project

cargo new greetings

     Created binary (application) `greetings` package

Enter the project root

cd greetings/

See what we have

ls -al

total 16

drwxr-xr-x  6 hayd  staff  192 12 Nov 15:56 .

drwxr-xr-x  4 hayd  staff  128 12 Nov 15:56 ..

drwxr-xr-x  9 hayd  staff  288 12 Nov 15:56 .git

-rw-r--r--  1 hayd  staff    8 12 Nov 15:56 .gitignore

-rw-r--r--  1 hayd  staff  178 12 Nov 15:56 Cargo.toml

drwxr-xr-x  3 hayd  staff   96 12 Nov 15:56 src

Create a library directory etc.

mkdir -p lib/src

Create the library module

vi lib/src/lib.rs

pub fn greeting(name: &str) {
    println!("Hello {}, how you doing ?", name);
}

Create the main module

vi src/main.rs

use greeting_lib::greeting;

fn main() {
    let name = std::env::args().nth(1).expect("no name given");

    greeting(&name);
}

Update the Cargo manifest

vi Cargo.toml

[package]
name = "greetings"
version = "0.1.0"
edition = "2021"

[lib]
name = "greeting_lib"
path = "lib/src/lib.rs"

Build the project

cargo build

   Compiling greetings v0.1.0 (/Users/hayd/functions.rust/greetings)
    Finished dev [unoptimized + debuginfo] target(s) in 0.56s

Test

cargo run Roy

    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/greetings Roy`
Hello Roy, how you doing ?

cargo run Ted

    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/greetings Ted`
Hello Ted, how you doing ?

cargo run Keely

    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/greetings Keely`
Hello Keely, how you doing ?

cargo run Rebecca

    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/greetings Rebecca`
Hello Rebecca, how you doing ?

Build a binary

cargo install --path .

  Installing greetings v0.1.0 (/Users/hayd/functions.rust/greetings)
   Compiling greetings v0.1.0 (/Users/hayd/functions.rust/greetings)
    Finished release [optimized] target(s) in 0.55s
  Installing /Users/hayd/.cargo/bin/greetings
   Installed package `greetings v0.1.0 (/Users/hayd/functions.rust/greetings)` (executable `greetings`)

Validate the built binary

ls -al target/release/greetings

-rwxr-xr-x  2 hayd  staff  464416 12 Nov 16:08 target/release/greetings

Test the binary

./target/release/greetings Beard

Hello Beard, how you doing ?

And that's all she ( I mean, I ) wrote 🤣

Friday, 5 November 2021

There's a hole in my bucket - IBM Cloud Object Storage

Whilst trying to create a Storage Bucket within my IBM Cloud Object Storage (COS) instance: -

ic cos bucket-create --bucket abcd321s

I saw this: -

FAILED

InvalidLocationConstraint: Invalid provisioning code.  Container storage location not deployed

status code: 400, request id: ff7e511d-87d4-4a65-b20c-8a35e268ce73, host id: 

I suspected my configuration, specifically the Service Endpoint for COS: -

ic cos config endpoint-url --list

Key                  Value   
ServiceEndpointURL   s3.us-south.cloud-object-storage.appdomain.cloud   

Looking at Endpoints and storage locations and given that I'm targeting the EU-DE region, I took a guess that having us-south wasn't ever gonna work.

Therefore, I cleared the current setting: -

ic cos config endpoint-url --clear

and validated the clearing: -

ic cos config endpoint-url --list

Key                  Value   
ServiceEndpointURL      

and set it to eu-de: -

ic cos config endpoint-url --url s3.eu-de.cloud-object-storage.appdomain.cloud

OK
Successfully updated service endpoint URL.

and validating the setting: -

ic cos config endpoint-url --list

Key                  Value   
ServiceEndpointURL   s3.eu-de.cloud-object-storage.appdomain.cloud   

and then retried the bucket creation: -

ic cos bucket-create --bucket abcd321s

OK
Details about bucket abcd321s:
Region: eu-de
Class: Standard

Yay!

Thursday, 4 November 2021

SSH keys - removing passphrase

This is somewhat related to an old-but-good post: -

Using SSH without passwords OR pass phrases

A colleague had generated an SSH key pair using a command such as: -

ssh-keygen

which, by default, asks for, and applies, a passphrase to the generated private key.

This can sometimes get in the way of automated pipelines e.g. Git, Terraform etc. where there're repeated calls to the private key.

*IF* there's absolutely no good reason to use a passphrase - and there are for a lot of folks - the phrase can be removed thusly: -

ssh-keygen -p -P blahblah -N "" -f ~/.ssh/id_rsa

where "blahblah" is the old ( and unwanted passphrase ) and "" ( null ) is the new passphrase.

Easy when you know, how ?

Tuesday, 2 November 2021

Brewing up with Tekton

Having recently upgraded to macOS 12 Monterey, I also wanted to upgrade my Homebrew installation, which I did thusly: -

brew update

Updated 1 tap (homebrew/core).

No changes to formulae.

brew upgrade

Warning: Calling bottle :unneeded is deprecated! There is no replacement.

Please report this issue to the tektoncd/tools tap (not Homebrew/brew or Homebrew/core):

  /usr/local/Homebrew/Library/Taps/tektoncd/homebrew-tools/Formula/tektoncd-cli.rb:6

Reading this: -

Install tektoncd cli with brews

let me to this: -

brew untap tektoncd/tools

Warning: Calling bottle :unneeded is deprecated! There is no replacement.

Please report this issue to the tektoncd/tools tap (not Homebrew/brew or Homebrew/core):

  /usr/local/Homebrew/Library/Taps/tektoncd/homebrew-tools/Formula/tektoncd-cli.rb:6

Error: Refusing to untap tektoncd/tools because it contains the following installed formulae or casks:

tektoncd-cli

Given that I'm not currently using Tekton ( sad ), I took the "nuclear" option of removing tektoncd-cli 

brew remove tektoncd-cli

Warning: Calling bottle :unneeded is deprecated! There is no replacement.
Please report this issue to the tektoncd/tools tap (not Homebrew/brew or Homebrew/core):
  /usr/local/Homebrew/Library/Taps/tektoncd/homebrew-tools/Formula/tektoncd-cli.rb:6

Uninstalling /usr/local/Cellar/tektoncd-cli/0.21.0... (8 files, 59.7MB)

and then re-ran brew untap tektoncd/tools

Untapping tektoncd/tools...
Untapped 1 formula (203 files, 109.9KB).

and then re-ran brew upgrade

Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
Updated 16 formulae.


Monday, 1 November 2021

Back in JQ, retrieving multiple fields

I'm using the IBM Cloud CLI tool ( aka ic ) to retrieve a list of API keys from my account.

This can be retrieved as a JSON document, and then passed through jq as per the following: -

ic iam api-keys --output JSON | jq

However, I really only wanted to retrieve two fields - .id and .description

And, of course, jq can do that ...

ic iam api-keys --output JSON | jq ".[] | .id, .description"

Now I'm not going to paste the output here because ... security.

However, I continue to ❤️ jq

macOS Time Machine to Synology DiskStation - have I solved it ?

 So I've been battling with Time Machine on my Mac this past few days, trying/failing to get it to backup to my Synology DiskStation Network Attached Storage (NAS).

I have an older model DS414, with ~2 TB of disk, configured as RAID, and have written about my fun with this device before including getting a nice fast Ethernet connection at 1000baseT.  

I've used this box for TM backups for a long while ....

So, for I'm not sure what reasons, this week, things started going a bit awry with backups failing to complete with: -


I have a shell script - ~/tm_logs.sh - as per this which showed: -

2021-10-30 07:47:49  Backup failed (7: BACKUP_FAILED_TARGETVOL_DISK_SPACE - Not enough available disk space on the target volume.)

which makes no sense, given how much storage I appear to have available to me: -

df -kmh /volume1/

Filesystem      Size  Used Avail Use% Mounted on

/dev/vg1000/lv  3.6T  2.0T  1.7T  55% /volume1

After much faffing about, I decided to REDO FROM START, and deleted the existing backup ( such as it was ), the shared folder AND the user ( on the NAS, by which the Mac authenticates to the Synology over SMB ).

This provided some useful inspiration: -

How do I back up files from my Mac to Synology NAS using Time Machine?

These are some of my settings: -

User & Group



File Services






Shared Folder


DSM Version


Other than that, at a friend's suggestion, I did set: -

debug.lowpri_throttle_enabled: 1

on macOS - whether/not that made any difference, I'm not sure, but I personally doubt it.

At a guess, it was a problem with the user account, perhaps a quota setting ....

Either way, so far, so good, which is nice

Thursday, 28 October 2021

RedHat OpenShift Container Platform - commanding the line ..

As per previous posts, I'm working with RedHat OpenShift Container Platform (OCP) a lot at present, and was looking for the most recent command-line tool, namely oc, for my Mac.

RedHat have the downloads for macOS, Windows and Linux here: -

Command-line interface (CLI) tools

so I pulled the appropriate tarball 



which resulted in: -

-rw-r--r--@   1 hayd  staff    41481963 28 Oct 15:35 openshift-client-mac.tar.gz

Having unpacked this: -

ls -al ~/Downloads/openshift-client-mac

total 384664
drwx------@ 5 hayd  staff       160 28 Oct 15:51 .
drwx------@ 7 hayd  staff       224 28 Oct 15:51 ..
-rw-r--r--@ 1 hayd  staff       954  1 Oct 01:41 README.md
-rwxr-xr-x@ 2 hayd  staff  98469344  1 Oct 01:41 kubectl
-rwxr-xr-x@ 2 hayd  staff  98469344  1 Oct 01:41 oc


I checked the version of oc - having had 4.7 previously: -

~/Downloads/openshift-client-mac/oc version

Client Version: 4.9.0

However, I also noted that the bundle includes kubectl 

When I checked the version of that: -

~/Downloads/openshift-client-mac/kubectl version

Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v0.21.0-beta.1", GitCommit:"96e95cef877ba04872b88e4e2597eabb0174d182", GitTreeState:"clean", BuildDate:"2021-10-01T00:41:12Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"darwin/amd64"}

which is out of sync with the version that I'm already using: -

kubectl version

Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.2", GitCommit:"8b5a19147530eaac9476b0ab82980b4088bbc1b2", GitTreeState:"clean", BuildDate:"2021-09-15T21:31:32Z", GoVersion:"go1.16.8", Compiler:"gc", Platform:"darwin/amd64"}

I'm not 100% sure why, and will ask around, but... in the meantime, I'll stick with what I have ...

IBM Cloud - The computer says "No"

Whilst trying to delete an IBM Cloud Object Storage (COS) instance from the command-line: -

ic resource service-instance-delete e8c79678-2ef8-4c7c-8a89-24ff2e85e691 --force

I saw: -

Deleting service instance e8c79678-2ef8-4c7c-8a89-24ff2e85e691 in resource group default under account DAVID HAY's Account as david_hay@uk.ibm.com...
FAILED
Cannot delete instance or alias, resource keys must first be deleted.


and couldn't quite work out to what it was referring.

Thankfully, the help text for that command had the answer: -

ic resource service-instance-delete --help

FAILED
Incorrect Usage.

NAME:
  service-instance-delete - Delete service instance

USAGE:
  /usr/local/bin/ibmcloud resource service-instance-delete ( NAME | ID ) [-g RESOURCE_GROUP] [-f, --force] [--recursive] [-q, --quiet]
  
OPTIONS:
  -g value     Resource group name
  -f, --force  Force deletion without confirmation
  --recursive  Delete all belonging resources
  -q, --quiet  Suppress verbose output



ic resource service-instance-delete e8c79678-2ef8-4c7c-8a89-24ff2e85e691 --force --recursive

Deleting service instance e8c79678-2ef8-4c7c-8a89-24ff2e85e691 in resource group default under account DAVID HAY's Account as david_hay@uk.ibm.com...
OK
Service instance cos_for_roks with ID crn:v1:bluemix:public:cloud-object-storage:global:a/f5e2ac71094077500e0d4b1ef85fdaec:e8c79678-2ef8-4c7c-8a89-24ff2e85e691:: is deleted successfully


Apple Watch - stop talking to me

For some peculiar reason, the Workout app on my Apple Watch started talking to me this morning …

Whilst that's not necessarily a problem, hearing a disembodied voice coming through my AirPods at 0600ish, whilst out on my morning walk was somewhat disconcerting

Thankfully a quick Google came to the rescue: -

which led me to the Apple Watch app on my iPhone : -


Why this started today, given that I updated to watchOS 8 a week or two back …. 🤷‍♀️

TIL - read-only variables in Linux

 A co-worker was seeing an exception: -  line 8: TMOUT: readonly variable when trying to SCP a file from a remote Linux box. I did some digg...