mardi 19 novembre 2024

removing unwanted *typo* systemd instance'd template units

 Systemd has this great feature : 


file: foo@.service 

contains the definition, as usual, with "%i"

=> will replace anything in the service file 

for example:


systemctl start foo@bar.service

systemctl start foo@resto.service


=> will start  service foo@bar  and foo@resto


but if resto does not make a valid service, it fails and can't be easily removed from the list of apparently formerly existing services.

(cf. for example https://bbs.archlinux.org/viewtopic.php?id=286912&p=1 )


As you can see with the command : 

 systemctl list-units --type=service | grep 'foo'

  UNIT                                                                                      LOAD   ACTIVE SUB     DESCRIPTION

  foo@alpha.service                                                               loaded active running Foo for protocol alpha

● foo@lish.service                                                              masked failed failed  foo@lish.service



=> Solution (on ubuntu, but no reason it does not work elsewhere) 

 systemctl mask foo@resto.service #this creates a symlink / replaces the symlink with one pointing to /dev/null, and marks the service as failed => no restart will happen again

 systemctl reset-failed # cleans failed services




vendredi 15 novembre 2024

workshop - Intro to Creative Coding & Generative Art, by Ahmad Moussa (links)

 https://slides.com/ahmadmoussa-3/creative-coding-generative-art

by https://x.com/gorillasu


https://timeline.lerandom.art Generative Art Timeline


https://editor.p5js.org 


https://x.com/gorillasu/status/1857444190910664749 example with p5js


https://openprocessing.org/sketch/2320206


example on fxHash https://www.fxhash.xyz/marketplace/generative/15063

colors palette : https://ronikaufman.github.io/color_pals/

colors manipulation js library : https://gka.github.io/chroma.js/

+ https://encycolorpedia.com/2b3c00


https://iquilezles.org/articles/distfunctions/ shapes and math



doc on fxHash : https://docs.fxhash.xyz/


Tricks : 

- when playing with RGB, start from the median value 127.5 and move around +/- 127.5

- RGB + 2 chars => 2 chars of transparency

- cos/sin/tan [0..1] with frameCount native variable of p5js : use pi to divide values and have the last frame coincide with the first frame of the loop.




--- first example

let a = 1;

var b;

const windowWidth = 800;

const windowHeitgh = 800;


function setup() {

  // attach a canvas element to the dom

  createCanvas(windowWidth, windowHeitgh);

  

}


// runs continously for each frame of the video, unless noLoop() inside

function draw() {

  // "#efface"

  // "#decede"

  background("#decede");

  ellipse(100, 150, 100)


  fill ("#efface")

  rect (300, 200, 200)

  noStroke()

  stroke("blue")

  

}



-- animated


let a = 1;

var b;

const windowWidth = 400;

const windowHeitgh = windowWidth;


function setup() {

  // attach a canvas element to the dom

  createCanvas(windowWidth, windowHeitgh);

  

}


// runs continously for each frame of the video, unless noLoop() inside

function draw() {

  // "#efface"

  // "#decede"

  background("#decede");

  noStroke()

  let t = frameCount 

  // for (let y = 0; y < 400; y=y+1){

  //   ellipse (200, y, 5)

  // }

  

  // console.log(frameCount/50)


  for (let y = 0; y < 400; y=y+1){

    fill(127.5 + sin (-frameCount/50 + y/20) * 127.5, 

         127.5 + sin (-frameCount/50 + y/20) * 127.5, 

         127.5 + sin (-frameCount/50 + y/20) * 127.5)

    

    ellipse (200 + sin (-frameCount/50 + y/20) * 20, 

             y,

             20 + cos (frameCount/30 + y/10) * 10)

  }  

  

}

--- moving, and colors changing (by me, inspired by GorillaSun)

let a = 1;

var b;

const windowWidth = 400;

const windowHeitgh = windowWidth;


let variation = 0

let variation2 = 2


function setup() {

  // attach a canvas element to the dom

  createCanvas(windowWidth, windowHeitgh);

  frameRate(50) // frame / s

  

  randomSeed(0) // so that random always does the same

  variation = random(0, 80)

  variation2 = random(100, 80)

}


let loopLength = 75



// runs continously for each frame of the video, unless noLoop() inside

function draw() {

  // "#efface"

  // "#decede"

  background("#decede");

  

  // trick to 

  let t = ( frameCount % loopLength ) / loopLength  * 2 * PI;

  

  // console.log(sin(PI))

  

  // noStroke()


  

  // for (let y = 0; y < 400; y=y+1){

  //   ellipse (200, y, 5)

  // }

  

  // console.log(frameCount/50)


  for (let y = 0; y < 400; y=y+1){

    stroke (127.5 + sin (-t + y/variation) * 127.5, 

            127.5 + sin (-t + y/20) * 127.5, 

            127.5 + sin (-t + y/variation2) * 127.5)

    

    // fill(127.5 + sin (-t/50 + y/20) * 127.5, 

    //      127.5 + sin (-t/50 + y/20), 

    //      127.5 + sin (-t/50 + y/20) * 127.5)

    noFill()

    

    square (200 + sin (-t/50 + y/variation) * 20, 

            200 + tan (-t/50 + y/variation) * variation*variation/3,

             20 + cos (t/30 + y/variation) * variation)

  }  

  

}


function keyPressed(){

  console.log(keyCode)

  if (keyCode == 56){

  saveGif('annimation', 4)

  }

}




--- other links and code from the presentation




other code from the presentation :

Sinus Wave by Ahmad Moussa || Gorilla Sun  https://openprocessing.org/sketch/1784279

function setup() {
createCanvas(400, 400);

}

function draw() {
background(0);
noStroke();
let t = millis()/500

for(let y = 20; y < 380; y++){
  fill(
    127.5 + 127.5 * sin(t + y/40),
    127.5 - 127.5 * cos(t + y/40),
    127.5 + 127.5 * cos(t + y/40)
  )
  ellipse(
    200 + sin(t + y/80 +
              sin(t + y/400) +
              cos(t + y/100)*2
             ) * 30, 
    y + sin(t + y/80 +
              sin(t + y/400))*15,
    20 + sin(t + y/10) * 15)
}
}

variation square by Ahmad Moussa || Gorilla Sun 
function setup() {
createCanvas(400, 400);
}

function draw() {
background(0);
noStroke();
let t = millis()/500

for(let y = 20; y < 380; y++){
  fill(
    127.5 + 127.5 * sin(t + y/40),
    127.5 + 127.5 * cos(t + y/40),
    127.5 - 127.5 * sin(t + y/80)
  )
  ellipse(
    200 + sin(t + y/80 +
              sin(t + y/400) +
              cos(t + y/50)*2
             ) * 30, 
    y + sin(t + y/80 +
              sin(t + y/400))*15,
    20 + sin(t + y/30) * 15)
}
}




LINKS

Zach Lieberman, Talk: Poetic Computation + atlas of blobs




https://openprocessing.org/sketch/2320206 simple circles packing by Ahmad Moussa || Gorilla Sun 

(with : <script src="https://openprocessing.org/openprocessing_sketch.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.4/lib/p5.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.4/lib/addons/p5.sound.min.js"></script> )


let circles = []
let numAttempts = 20000

let canvas_width = 800
let canvas_height = 800
let padding = 50

function setup() {
  createCanvas(canvas_width, canvas_height);
  pixelDensity(4)
  
  background(0)
  stroke(255)
  
  for(let n = 0; n < numAttempts; n++){
    
    let randX = random(padding, canvas_width-padding)
    let randY = random(padding, canvas_height-padding)
    let randR = random(5, 120)
    
    let placeable = true
    for(let circle of circles){
      let d = dist(
        randX, randY, circle.x, circle.y
      )
      
      if(d < randR + circle.r + 5){
        placeable = false
      }
    }
    
    if(
      (randX + randR > canvas_width-padding) ||
      (randX - randR < padding) ||
      (randY + randR > canvas_height-padding) ||
      (randY - randR < padding)
    ){
        placeable = false
    }
    
    if(placeable){
      circles.push(
        {
          x: randX, y: randY, r: randR
        }
      )
    }
  }
  
  strokeWeight(2)
noFill()
  for(let circle of circles){
    ellipse(
      circle.x,
      circle.y ,
      circle.r*2
    )
  }
  
  noLoop()
}




 Particle System with Grid Lookup
by Ahmad Moussa || Gorilla Sun 
<script src="https://cdn.jsdelivr.net/npm/p5@1.6.0/lib/p5.min.js"></script> 
p5.disableFriendlyErrors = true;
let N_PARTICLES = 50;
let particles = [];
let grid;

function setup() {
  createCanvas(windowWidth, windowHeight);

  grid = new Grid(windowWidth, windowHeight, 22);

  for (let n = 0; n < N_PARTICLES; n++) {
    let particle = new Particle(new createVector(random(windowWidth), random(windowHeight)))
    particles.push(particle);
    grid.addParticle(particle);
  }
}

function draw() {
  background(220);

  if (mouseIsPressed) {
    for(let n = 0; n < 5; n++){
let particle = new Particle(new createVector(mouseX+random(-1,1), mouseY+random(-1,1)))
    particles.push(particle);
    grid.addParticle(particle);
}
  }

  textSize(30)
  textAlign(LEFT, TOP)
  let numCollisionChecks = 0
  let startneigh = performance.now();
  for (let p of particles) {
    let neighbors = grid.getNeighbors(p)
    numCollisionChecks += p.checkCollision(neighbors)
p.updateState();
  }
  let endneigh = performance.now();
  let coll = `${numCollisionChecks} collisions computed in ${ endneigh - startneigh} ms`

  let startup = Date.now();
  for (let p of particles) {
p.checkEdges();
    grid.removeParticle(p)
    grid.addParticle(p)
  }
  let endup = Date.now();
  let up = 'Grid updated in ' + round(endup - startup, 2) + ' ms'

noFill()
  let startd = Date.now();
  for (let p of particles) {
    p.display();
  }
  let endd = Date.now();
  let dr = 'Draw in ' + round(endd - startd, 2) + ' ms'


  fill(0)
  text('Particles: ' + particles.length, 10, 10)
  text(coll, 10, 50);
  text(up, 10, 90);
  text(dr, 10, 130);
}

class Particle {
  constructor(pos) {
    this.pos = pos;
    this.velocity = createVector(random(-1.25, 1.25), random(-1.25, 1.25));
    this.acceleration = createVector(0, 0);

    this.mass = random(3, 10)
    this.radius = this.mass;
    this.maxSpeed = 10;
  }

  updateState(newPos) {
    this.velocity.add(this.acceleration);
    this.velocity.limit(this.maxSpeed); // Limit the particle's speed
    this.pos.add(this.velocity);
  }

  checkEdges() {
    if (this.pos.x - this.radius < 0) {
      this.pos.x = this.radius; // Prevent from leaving the canvas from the left side
      this.velocity.x *= -1;
    } else if (this.pos.x + this.radius > width) {
      this.pos.x = width - this.radius; // Prevent from leaving the canvas from the right side
      this.velocity.x *= -1;
    }

    if (this.pos.y - this.radius < 0) {
      this.pos.y = this.radius; // Prevent from leaving the canvas from the top
      this.velocity.y *= -1;
    } else if (this.pos.y + this.radius > height) {
      this.pos.y = height - this.radius; // Prevent from leaving the canvas from the bottom
      this.velocity.y *= -1;
    }
  }

  checkCollision(otherParticles) {
let counter = 0
    for (let other of otherParticles) {
      if (this != other) {
        let distance = this.pos.dist(other.pos);
        let minDistance = this.radius + other.radius + 1;

        if (distance <= minDistance) {
          // Calculate collision response
          let normal = p5.Vector.sub(other.pos, this.pos).normalize();
          let relativeVelocity = p5.Vector.sub(other.velocity, this.velocity);
          let impulse = p5.Vector.mult(normal, 2 * p5.Vector.dot(relativeVelocity, normal) / 2);

          // Apply repulsion force to prevent sticking
          let repulsion = p5.Vector.mult(normal, minDistance - distance + 2).mult(1);

          // Update velocities
          this.velocity.add(p5.Vector.div(impulse, this.mass));
          other.velocity.sub(p5.Vector.div(impulse, other.mass));

          // Apply repulsion force
          this.pos.sub(p5.Vector.div(repulsion, this.mass));
          other.pos.add(p5.Vector.div(repulsion, other.mass));
        }
counter++
      }
    }
return counter
  }

  display() {
    ellipse(this.pos.x, this.pos.y, this.radius * 2);
  }
}

/*
  The lookup grid
*/
class Grid {
  constructor(i, t, s) {
    (this.cellSize = s),
    (this.numCols = Math.ceil(i / s)),
    (this.numRows = Math.ceil(t / s)),
    (this.cells = []);
    for (let e = 0; e < this.numCols; e++) {
      this.cells[e] = [];
      for (let l = 0; l < this.numRows; l++) {
        this.cells[e][l] = [];
      }
    }
  }

  addParticle(i) {
    let t = Math.floor(i.pos.x / this.cellSize);
    let s = Math.floor(i.pos.y / this.cellSize);

    this.cells[t][s].push(i)
    i.gridCell = {
      col: t,
      row: s
    }
  }

  removeParticle(i) {
    let {
      col: t,
      row: s
    } = i.gridCell
    let e = this.cells[t][s];
    let l = e.indexOf(i);
    e.splice(l, 1);
  }

  determineCell(i) {
    let t = Math.floor(i.pos.x / this.cellSize);
    let s = Math.floor(i.pos.y / this.cellSize);
    return {
      col: t,
      row: s
    }
  }

  getNeighbors(particle) {
    let top_left = [
      floor((particle.pos.x - particle.radius) / this.cellSize),
      floor((particle.pos.y - particle.radius) / this.cellSize),
    ]

    let bottom_right = [
      floor((particle.pos.x + particle.radius) / this.cellSize),
      floor((particle.pos.y + particle.radius) / this.cellSize),
    ]

    let neighbors = []
    for (let i = top_left[0]; i <= bottom_right[0]; i++) {
      for (let j = top_left[1]; j <= bottom_right[1]; j++) {
        if (i < 0 || j < 0 || i >= this.numCols || j >= this.numRows) continue
        let c = this.cells[i][j]
        for (let p of c) {
          // don't add the particle itself
          if (p != particle) neighbors.push(p)
        }
      }
    }

    return neighbors
  }
}

jeudi 3 octobre 2024

json_exporter prometheus debug

 JSON url to convert : http://json_url/foobar.json

json_exporter running locally : localhost:7979 or json_exporter:7979 



Status of the json_exporter, does NOT contain the metrics from the targets, only related to the process itself (useful to know if it's up or not for example).

 localhost:7979/metrics


Check the result of a JSON URL to be converted / aka. what prometheus should scrape

curl http://json_url/foobar.json => JSON (original)

curl localhost:7979/probe?target=https://json_url/foobar.json => openmetrics converted by json_exporter



Other useful commands :


* edit, restart, wait, check json_exporter output

sudo vi /etc/json_exporter/config.yml && sudo systemctl restart json_exporter && sleep 5 && curl http://localhost:7979/probe?target=http://json_url/foobar.json


* edit, check and restart prometheus : 

sudo vi /etc/prometheus/prometheus.yml && sudo promtool check config /etc/prometheus/prometheus.yml && sudo systemctl restart prometheus.service



lundi 9 septembre 2024

Google Spreadsheet conditional formatting for week days check (display weekends with a different color)

Goal: 

I have a column of dates that I want to format so that weekends are in a different color. 

Solution :  

conditional formatting and the formula =OR(WEEKDAY(A1)=7;WEEKDAY(A1)=1) 








lundi 19 août 2024

GCP+ansible+gitlab-ci : OS-login for ansible with dynamic google compute inventory and gitlab-ci

"How to configure OS Login in GCP for Ansible" + ansible dynamic inventory for GCP compute + update on accepted cryptographic algo for SSH key + gitlab-ci example

Context: 

2024 update on https://alex.dzyoba.com/blog/gcp-ansible-service-account/ => thanks ! this still works, but the ssk-keygen by default doesn't provide keys that are accepted by gcp os-login.

+ updated precisions that took me too much time to infer, understood after reading : https://cloud.google.com/compute/docs/connect/create-ssh-keys => the SSH keys need to be in ssh-rsa !

+ ansible dynamic inventory configuration (as of 2024-aug)

+ automation example with gitlab-ci (as of 2024-aug)


Note: For the sake of completeness, ease of reproduction by the reader and leveraging the CC-BY-SA copyright, I include the sections of the great blog post cited as [1] and add my contributions when and where I needed too. 

Service account

 (cf. [1] - no change so far) OS Login allows SSH access for IAM users - there is no need to provision Linux users on an instance.

So Ansible should have access to the instances via IAM user. This is accomplished via IAM service account.

You can create service account via Console (web UI), via Terraform template or (as in [this] case) via gcloud:

$ gcloud iam service-accounts create ansible-sa \
     --display-name "Service account for Ansible"

Configure OS Login

 (cf. [1,5,6] - no change so far)
 Now, the trickiest part – configuring OS Login for service account.

 

0. Enable OS Login for all VMs in the project

Before you do anything else make sure to enable it for your project:

$ gcloud compute project-info add-metadata \
    --metadata enable-oslogin=TRUE

1. Add roles

Fresh service account don't have any IAM roles, so ansible-sa doesn’t have permission to do anything. To allow OS Login we have to add these 4 roles to the Ansible service account:
  • Compute Instance Admin (beta)
  • Compute Instance Admin (v1) => login as root (for "become: true" with ansible)
  • Compute OS Admin Login =>  login as a regular user
  • Service Account User

Here is how to do it via gcloud:

for role in \
    'roles/compute.instanceAdmin' \
    'roles/compute.instanceAdmin.v1' \
    'roles/compute.osAdminLogin' \
    'roles/iam.serviceAccountUser'
do \
    gcloud projects add-iam-policy-binding \
        my-gcp-project-241123 \
        --member='serviceAccount:ansible-sa@my-gcp-project-241123.iam.gserviceaccount.com' \
        --role="${role}"
done


2. Create key for service account and save it 

Service account is useless without key, create one with gcloud,  and save it, we will use it for the dynamic inventory connection further down the path.
This will create GCP key, not the SSH key.
$ gcloud iam service-accounts keys create \
    .gcp/gcp-key-ansible-sa.json \
    --iam-account=ansible-sa@my-gcp-project.iam.gserviceaccount.com 


3. Create SSH key for service account 

(cf. [1]  modified ! with command from [2])

This  [was supposed] the easiest part. $ ssh-keygen -f ssh-key-ansible-sa

 By default ssh-keygen provided an ssh-ed25519 ssh key, leading to a  Permission denied (publickey) when trying to connect with Ansible and OS-login (but no issue when connecting directly from the command-line). Specify `-t rsa` when creating your SSH keys.

$ ssh-keygen -t rsa -f ssh-key-ansible-sa -b 2048


4. Add SSH key for OS login to service account

(cf. [1] - no change) Now, to allow service account to access instances via SSH it has to have SSH public key added to it. To do this, first, we have to activate service account in gcloud:
$ gcloud auth activate-service-account \
    --key-file=.gcp/gcp-key-ansible-sa.json

This command uses GCP key we’ve created on step 2.

Now we add SSH key to the service account:

$ gcloud compute os-login ssh-keys add \
    --key-file=ssh-key-ansible-sa.pub

5. Switch back from service account

(cf. [1] - no change)  

$ gcloud config set account your@gmail.com

 

Connecting to the instance with OS login 

(cf. [1] - with change to the command to bypass the ssh-agent)

Now, we have everything configured on the GCP side, we can check that it’s working.

Note, that you don’t need to add SSH key to compute metadata, authentication works via OS login. But this means that you need to know a special user name for the service account.

Find out the service account id.

$ gcloud iam service-accounts describe \
    ansible-sa@my-gcp-project.iam.gserviceaccount.com \
    --format='value(uniqueId)'
106627723496398399336


This id is used to form user name in OS login – it’s sa_<unique_id>.  

Here is how to use it to check SSH access is working, 

 Specify the RSA private key, and to bypass the ssh-agent, specify to only test the identity provided in the command (IdentitiesOnly=yes), not all the keys you may have loaded in your running ssh-agent.

$ ssh -o "IdentitiesOnly=yes" -i ssh-key-ansible-sa sa_106627723496398399336@10.0.0.44
...

Configuring Ansible

Ansible GCP static inventory

 (cf. [1] - no change for static inventory, more on dynamic inventory just after)

And for the final part – make Ansible work with it.

There is a special variable ansible_user that sets user name for SSH when Ansible connects to the host.

In my case, I have a group gcp where all GCP instances are added, and so I can set ansible_user in group_vars like this:

# File inventory/dev/group_vars/gcp
ansible_user: sa_106627723496398399336


(thanks a lot to [1]'s author Alex Dzyoba, those previous steps helped me a lot in going this far ! now, let's add dynamic inventory and how I run it from gitlab-ci...)


Ansible GCP dynamic inventory

The compose section of the dynamic GCP inventory ansible plugin (google.cloud.gcp_compute, cf. [3]) expects a jinga2 template, to pass a variable directly, you need to double escape it:

 ansible_user: "'sa_106627723496398399336'"

#example of inventory.gcp.yml
---
plugin: google.cloud.gcp_compute

projects:
 - your-gcp-project

auth_kind: serviceaccount
# must match `ansible_user` below, json file must be available
service_account_file: ./.gcp/gcp-key-ansible-sa.json

filters:
 - status = RUNNING

keyed_groups:
  - key: labels
    prefix: label
  - key: zone
    prefix: zone
  - key: project
    prefix: project
  - key: labels['compoment']
    prefix: component

compose:
 ansible_host:           networkInterfaces[0].accessConfigs[0].natIP
 ansible_user:           "'sa_106627723496398399336'"

Configuring Ansible (ansible.cfg ssh_args)

Make sure to instruct ansible to use the correct private key when connecting to the servers
ssh_args = -i ssh-key-ansible-sa 

#file ansible.cfg :
[defaults]
;debug = true
roles_path = ./vendor-roles:./roles
collections_path = ./vendor-collections:./collections
stdout_callback = yaml
deprecation_warnings = True
host_key_checking = False
forks = 10
callbacks_enabled = timer, profile_tasks, profile_roles
;remote_user = sa_106627723496398399336
remote_tmp = /tmp [ssh_connection] pipelining = True scp_if_ssh = True ssh_args = -i ssh-key-ansible-sa

Gitlab-ci example

Identify an image that has ansible installed (and maintained), I used registry.gitlab.com/gitlab-org/gitlab-environment-toolkit:latest but if you find other /lighter one, let me know ! 


Gitlab-ci secret files [4] doc is set from the gitlab project's configuration, in the CI settings  and doc can be found here https://docs.gitlab.com/ee/ci/secure_files/index.html 

  • Using gitlab-ci feature secret files [4], store the ssh RSA secret key (for ssh)
  • Using gitlab-ci feature secret files [4], store the GCP json file for GCP authentication (for dynamic inventory).
  • We gather the files in the prepare_ssh_ansible job


If you have multiple jobs using Ansible, factorize (here  in the prepare_ssh_ansible job), and extends, here in the ssh-access, ansible-ping, ansible-inventory)

Example playbook, in this case, is located in ~/ansible/playbook/ssh.yml; replace with your own playbook).


# file: .gitlab-ci.yml
variables:
ANSIBLE_DYN_INVENTORY : "inventory.gcp.yml"
ANSIBLE_CHECK : "--check -vvv"
SECURE_FILES_DOWNLOAD_PATH: './secured_files/'

prepare_ssh_ansible:
# image: librespace/ansible:9.6.0
image: registry.gitlab.com/gitlab-org/gitlab-environment-toolkit:latest
before_script:
# install missing packages
- apt update --allow-releaseinfo-change -y -qq && apt install -y ansible curl bash jq

# gitlab-ci secured_files (cf [4]) for GCP service account credentials
- curl --silent "https://gitlab.com/gitlab-org/incubation-engineering/mobile-devops/download-secure-files/-/raw/main/installer" | bash
- mkdir ./ansible/.gcp/
- cp ${SECURE_FILES_DOWNLOAD_PATH}/gcp-key-ansible-sa.json ./ansible/.gcp/gcp-key-ansible-sa.json
- cp ${SECURE_FILES_DOWNLOAD_PATH}/ssh-key-ansible-sa ./ansible/ssh-key-ansible-sa && chmod 400 ./ansible/ssh-key-ansible-sa

# cf https://docs.ansible.com/ansible/9/scenario_guides/guide_gce.html#providing-credentials-as-environment-variables
- export GCP_AUTH_KIND="serviceaccount"
- export GCP_SERVICE_ACCOUNT_FILE="./ansible/.gcp/gcp-key-ansible-sa.json"
- export GCP_SCOPES="https://www.googleapis.com/auth/compute"

- export ANSIBLE_HOME=./ansible
- cd ./ansible/
- export ANSIBLE_CONFIG=./ansible.cfg
- ansible-galaxy install -r requirements.yaml --roles-path ./vendor-roles
- ansible-galaxy collection install -r requirements.yaml -p ./vendor-collections/
- ansible --version

ansible-inventory:
extends:
.prepare_ssh_ansible
script:
- ansible-inventory -i ${ANSIBLE_DYN_INVENTORY} --graph

ansible-ping:
extends:
.prepare_ssh_ansible
script:
- ansible all -i ${ANSIBLE_DYN_INVENTORY} -m ping -vvv

ssh-access:
extends:
.prepare_ssh_ansible
script:
- ansible-playbook -i ${ANSIBLE_DYN_INVENTORY} playbooks/ssh.yml


References :

[1] https://alex.dzyoba.com/blog/gcp-ansible-service-account/

[2] https://cloud.google.com/compute/docs/connect/create-ssh-keys 

[3] https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_compute_inventory.html 

[4] https://docs.gitlab.com/ee/ci/secure_files/index.html

[5] https://cloud.google.com/compute/docs/oslogin

[6] https://cloud.google.com/compute/docs/oslogin/set-up-oslogin


mercredi 22 mai 2024

list of awesome jq tools

from https://github.com/fiatjaf/awesome-jq?tab=readme-ov-file#tools


example:

https://github.com/jcsalterego/jqq/  interactive json path explorer `jqq <expr> file>

DNS debugging

 Doing some digging about why a specific DNS wasn't propagating properly everywhere, I found out that it was related to a wrong DNSSEC declaration.



a bit more details about DNSSEC 

https://blog.ovhcloud.com/an-introduction-to-dnssec/


DNS DNSKEY and DS records "The DNSKEY and DS records are used by DNSSEC resolvers to verify the authenticity of DNS records."

https://www.cloudflare.com/learning/dns/dns-records/dnskey-ds-records/



some debuging steps

https://serverfault.com/questions/1018543/dns-not-resolving-in-all-locations-after-a-week 


dimanche 7 avril 2024

RFC 1178. Choosing a Name for Your Computer (c ACM 1989)

 RFC 1178

Informational



Network Working Group                                          D. Libes

Request for Comments: 1178                Integrated Systems Group/NIST

FYI: 5                                                      August 1990



                   Choosing a Name for Your Computer


Status of this Memo


   This FYI RFC is a republication of a Communications of the ACM

   article on guidelines on what to do and what not to do when naming

   your computer [1].  This memo provides information for the Internet

   community.  It does not specify any standard.


   Distribution of this memo is unlimited.


Abstract


   In order to easily distinguish between multiple computers, we give

   them names.  Experience has taught us that it is as easy to choose

   bad names as it is to choose good ones.  This essay presents

   guidelines for deciding what makes a name good or bad.


   Keywords: domain name system, naming conventions, computer

   administration, computer network management


Introduction


   As soon as you deal with more than one computer, you need to

   distinguish between them.  For example, to tell your system

   administrator that your computer is busted, you might say, "Hey Ken.

   Goon is down!"


   Computers also have to be able to distinguish between themselves.

   Thus, when sending mail to a colleague at another computer, you might

   use the command "mail libes@goon".


   In both cases, "goon" refers to a particular computer.  How the name

   is actually dereferenced by a human or computer need not concern us

   here.  This essay is only concerned with choosing a "good" name.  (It

   is assumed that the reader has a basic understanding of the domain

   name system as described by [2].)


   By picking a "good" name for your computer, you can avoid a number of

   problems that people stumble over again and again.


   Here are some guidelines on what NOT to do.





Libes                                                           [Page 1]


RFC 1178                   Name Your Computer                August 1990



      Don't overload other terms already in common use.


         Using a word that has strong semantic implications in the

         current context will cause confusion.  This is especially true

         in conversation where punctuation is not obvious and grammar is

         often incorrect.


         For example, a distributed database had been built on top of

         several computers.  Each one had a different name.  One machine

         was named "up", as it was the only one that accepted updates.

         Conversations would sound like this: "Is up down?"  and "Boot

         the machine up." followed by "Which machine?"


         While it didn't take long to catch on and get used to this

         zaniness, it was annoying when occasionally your mind would

         stumble, and you would have to stop and think about each word

         in a sentence.  It is as if, all of a sudden, English has

         become a foreign language.


      Don't choose a name after a project unique to that machine.


         A manufacturing project had named a machine "shop" since it was

         going to be used to control a number of machines on a shop

         floor.  A while later, a new machine was acquired to help with

         some of the processing.  Needless to say, it couldn't be called

         "shop" as well.  Indeed, both machines ended up performing more

         specific tasks, allowing more precision in naming.  A year

         later, five new machines were installed and the original one

         was moved to an unrelated project.  It is simply impossible to

         choose generic names that remain appropriate for very long.


         Of course, they could have called the second one "shop2" and so

         on.  But then one is really only distinguishing machines by

         their number.  You might as well just call them "1", "2", and

         "3".  The only time this kind of naming scheme is appropriate

         is when you have a lot of machines and there are no reasons for

         any human to distinguish between them.  For example, a master

         computer might be controlling an array of one hundred

         computers.  In this case, it makes sense to refer to them with

         the array indices.


         While computers aren't quite analogous to people, their names

         are.  Nobody expects to learn much about a person by their

         name.  Just because a person is named "Don" doesn't mean he is

         the ruler of the world (despite what the "Choosing a Name for

         your Baby" books say).  In reality, names are just arbitrary

         tags.  You cannot tell what a person does for a living, what

         their hobbies are, and so on.




Libes                                                           [Page 2]


RFC 1178                   Name Your Computer                August 1990



      Don't use your own name.


         Even if a computer is sitting on your desktop, it is a mistake

         to name it after yourself.  This is another case of

         overloading, in which statements become ambiguous.  Does "give

         the disk drive to don" refer to a person or computer?


         Even using your initials (or some other moniker) is

         unsatisfactory.  What happens if I get a different machine

         after a year?  Someone else gets stuck with "don" and I end up

         living with "jim".  The machines can be renamed, but that is

         excess work and besides, a program that used a special

         peripheral or database on "don" would start failing when it

         wasn't found on the "new don".


         It is especially tempting to name your first computer after

         yourself, but think about it.  Do you name any of your other

         possessions after yourself?  No.  Your dog has its own name, as

         do your children.  If you are one of those who feel so inclined

         to name your car and other objects, you certainly don't reuse

         your own name.  Otherwise you would have a great deal of

         trouble distinguishing between them in speech.


         For the same reason, it follows that naming your computer the

         same thing as your car or another possession is a mistake.


      Don't use long names.


         This is hard to quantify, but experience has shown that names

         longer than eight characters simply annoy people.


         Most systems will allow prespecified abbreviations, but why not

         choose a name that you don't have to abbreviate to begin with?

         This removes any chance of confusion.


      Avoid alternate spellings.


         Once we called a machine "czek".  In discussion, people

         continually thought we were talking about a machine called

         "check".  Indeed, "czek" isn't even a word (although "Czech"

         is).


         Purposely incorrect (but cute) spellings also tend to annoy a

         large subset of people.  Also, people who have learned English

         as a second language often question their own knowledge upon

         seeing a word that they know but spelled differently.  ("I

         guess I've always been spelling "funxion" incorrectly.  How

         embarrassing!")




Libes                                                           [Page 3]


RFC 1178                   Name Your Computer                August 1990



         By now you may be saying to yourself, "This is all very

         silly...people who have to know how to spell a name will learn

         it and that's that." While it is true that some people will

         learn the spelling, it will eventually cause problems

         somewhere.


         For example, one day a machine named "pythagoris" (sic) went

         awry and began sending a tremendous number of messages to the

         site administrator's computer.  The administrator, who wasn't a

         very good speller to begin with, had never seen this machine

         before (someone else had set it up and named it), but he had to

         deal with it since it was clogging up the network as well as

         bogging down his own machine which was logging all the errors.

         Needless to say, he had to look it up every time he needed to

         spell "pythagoris".  (He suspected there was an abbreviation,

         but he would have had to log into yet another computer (the

         local nameserver) to find out and the network was too jammed to

         waste time doing that.)


      Avoid domain names.


         For technical reasons, domain names should be avoided.  In

         particular, name resolution of non-absolute hostnames is

         problematic.  Resolvers will check names against domains before

         checking them against hostnames.  But we have seen instances of

         mailers that refuse to treat single token names as domains.

         For example, assume that you mail to "libes@rutgers" from

         yale.edu.  Depending upon the implementation, the mail may go

         to rutgers.edu or rutgers.yale.edu (assuming both exist).


      Avoid domain-like names.


         Domain names are either organizational (e.g., cia.gov) or

         geographical (e.g., dallas.tx.us).  Using anything like these

         tends to imply some connection.  For example, the name "tahiti"

         sounds like it means you are located there.  This is confusing

         if it is really somewhere else (e.g., "tahiti.cia.gov is

         located in Langley, Virginia?  I thought it was the CIA's

         Tahiti office!").  If it really is located there, the name

         implies that it is the only computer there.  If this isn't

         wrong now, it inevitably will be.


         There are some organizational and geographical names that work

         fine.  These are exactly the ones that do not function well as

         domain names.  For example, amorphous names such as rivers,

         mythological places and other impossibilities are very

         suitable.  ("earth" is not yet a domain name.)





Libes                                                           [Page 4]


RFC 1178                   Name Your Computer                August 1990



      Don't use antagonistic or otherwise embarrassing names.


         Words like "moron" or "twit" are good names if no one else is

         going to see them.  But if you ever give someone a demo on your

         machine, you may find that they are distracted by seeing a

         nasty word on your screen.  (Maybe their spouse called them

         that this morning.)  Why bother taking the chance that they

         will be turned off by something completely irrelevant to your

         demo.


      Don't use digits at the beginning of the name.


         Many programs accept a numerical internet address as well as a

         name.  Unfortunately, some programs do not correctly

         distinguish between the two and may be fooled, for example, by

         a string beginning with a decimal digit.


         Names consisting entirely of hexadecimal digits, such as

         "beef", are also problematic, since they can be interpreted

         entirely as hexadecimal numbers as well as alphabetic strings.


      Don't use non-alphanumeric characters in a name.


         Your own computer may handle punctuation or control characters

         in a name, but most others do not.  If you ever expect to

         connect your computer to a heterogeneous network, you can count

         on a variety of interpretations of non-alphanumeric characters

         in names.  Network conventions on this are surprisingly

         nonstandard.


      Don't expect case to be preserved.


         Upper and lowercase characters look the same to a great deal of

         internet software, often under the assumption that it is doing

         you a favor.  It may seem appropriate to capitalize a name the

         same way you might do it in English, but convention dictates

         that computer names appear all lowercase.  (And it saves

         holding down the shift key.)


   Now that we've heard what not to do, here are some suggestions on

   names that work well.


      Use words/names that are rarely used.


         While a word like "typical" or "up" (see above) isn't computer

         jargon, it is just too likely to arise in discussion and throw

         off one's concentration while determining the correct referent.

         Instead, use words like "lurch" or "squire" which are unlikely




Libes                                                           [Page 5]


RFC 1178                   Name Your Computer                August 1990



         to cause any confusion.


         You might feel it is safe to use the name "jose" just because

         no one is named that in your group, but you will have a problem

         if you should happen to hire Jose.  A name like "sphinx" will

         be less likely to conflict with new hires.


      Use theme names.


         Naming groups of machines in a common way is very popular, and

         enhances communality while displaying depth of knowledge as

         well as imagination.  A simple example is to use colors, such

         as "red" and "blue".  Personality can be injected by choices

         such as "aqua" and "crimson".


         Certain sets are finite, such as the seven dwarfs.  When you

         order your first seven computers, keep in mind that you will

         probably get more next year.  Colors will never run out.


         Some more suggestions are: mythical places (e.g., Midgard,

         Styx, Paradise), mythical people (e.g., Procne, Tereus, Zeus),

         killers (e.g., Cain, Burr, Boleyn), babies (e.g., colt, puppy,

         tadpole, elver), collectives (e.g., passel, plague, bevy,

         covey), elements (e.g., helium, argon, zinc), flowers (e.g.,

         tulip, peony, lilac, arbutus).  Get the idea?


      Use real words.


         Random strings are inappropriate for the same reason that they

         are so useful for passwords.  They are hard to remember.  Use

         real words.


      Don't worry about reusing someone else's hostname.


         Extremely well-known hostnames such as "sri-nic" and "uunet"

         should be avoided since they are understood in conversation as

         absolute addresses even without a domain.  In all other cases,

         the local domain is assumed to qualify single-part hostnames.

         This is similar to the way phone numbers are qualified by an

         area code when dialed from another area.


         In other words, if you have choosen a reasonable name, you do

         not have to worry that it has already been used in another

         domain.  The number of hosts in a bottom-level domain is small,

         so it shouldn't be hard to pick a name unique only to that

         domain.






Libes                                                           [Page 6]


RFC 1178                   Name Your Computer                August 1990



      There is always room for an exception.


         I don't think any explanation is needed here.  However, let me

         add that if you later decide to change a name (to something

         sensible like you should have chosen in the first place), you

         are going to be amazed at the amount of pain awaiting you.  No

         matter how easy the manuals suggest it is to change a name, you

         will find that lots of obscure software has rapidly accumulated

         which refers to that computer using that now-ugly name.  It all

         has to be found and changed.  People mailing to you from other

         sites have to be told.  And you will have to remember that

         names on old backup media labels correspond to different names.


         I could go on but it would be easier just to forget this

         guideline exists.


Conclusion


   Most people don't have the opportunity to name more than one or two

   computers, while site administrators name large numbers of them.  By

   choosing a name wisely, both user and administrator will have an

   easier time of remembering, discussing and typing the names of their

   computers.


   I have tried to formalize useful guidelines for naming computers,

   along with plenty of examples to make my points obvious.  Having been

   both a user and site administrator, many of these anecdotes come from

   real experiences which I have no desire to relive.  Hopefully, you

   will avoid all of the pitfalls I have discussed by choosing your

   computer's name wisely.


Credits


   Thanks to the following people for suggesting some of these

   guidelines and participating in numerous discussions on computer

   naming: Ed Barkmeyer, Peter Brown, Chuck Hedrick, Ken Manheimer, and

   Scott Paisley.


   This essay first appeared in the Communications of the ACM, November,

   1989, along with a Gary Larson cartoon reprinted with permission of

   United Press Syndicate.  The text is not subject to copyright, since

   it is work of the National Institute of Standards and Technology.

   However, the author, CACM, and NIST request that this credit appear

   with the article whenever it is reprinted.








Libes                                                           [Page 7]


RFC 1178                   Name Your Computer                August 1990



References


   [1]  Libes, D., "Choosing a Name for Your Computer", Communications

   of the ACM, Vol. 32, No. 11, Pg. 1289, November 1989.


   [2]  Mockapetris, P., "Domain Names - Concepts and Facilities",

   RFC 1034, USC/Information Sciences Institute, November 1987.


Security Considerations


   Security issues are not discussed in this memo.


Author's Address


   Don Libes

   Integrated Systems Group

   National Institute of Standards and Technology

   Gaithersburg, MD 20899


   Phone: (301) 975-3535


   EMail:  libes@cme.nist.gov






























Libes                                                           [Page 8]

RFC 1178

Informational





Document type

RFC Informational

August 1990

Select version

RFC 1178

Author

Don Libes

RFC stream

Legacy stream

Other formats