# Question
Title: Ansible playbook error: "Connection timed out during banner exchange"
I am trying to connect to my bastion host and then tunnel that ssh connection to connect to a jenkins host but keep running into the connection timed out error.

The error message in full is:

```
fatal: [<bastion-public-ip>]: UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Connection timed out during banner exchange",
    "unreachable": true
}

```

my inventory file:

```
[bastion]
#ip for bastion host
<bastion-public-ip>

[bastion:vars]
ansible_ssh_user=ubuntu
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ansible_ssh_common_args='-o ProxyCommand="ssh -W %h:%p -q ubuntu@10.0.1.49"'
ansible_ssh_private_key_file=~/.ssh/bastion.pem

[jenkins]
#ip of EC2 instance
10.0.1.49

[jenkins:vars]
ansible_user=ubuntu
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ubuntu@10.0.1.49'
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
ansible_ssh_private_key_file=~/j-key.pem

```

And my playbook file is:

```
- hosts: bastion
  become: true

- hosts: jenkins
  # run as the root user on the remote machine
  become: true
  # list of tasks to run on the remote machine
  tasks:
  - name: 'update system'
    apt: name=aptitude state=latest update_cache=yes force_apt_get=yes

  - name: 'install docker'
    script: docker.sh

  - name: 'install docker-compose'
    script: docker-compose.sh

  - name: 'install Jenkins'
    script: jenkins.sh

```

My ansible version is: ansible 2.9.13

EDIT: Wanted to add the rules for the security group my bastion server is in

Port 22 is open to TCP traffic from everywhere currently

EDIT 2: -vvv flag output

```
ansible-playbook 2.9.13
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/qa/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/qa/.local/lib/python3.8/site-packages/ansible
  executable location = /home/qa/.local/bin/ansible-playbook
  python version = 3.8.5 (default, Jul 28 2020, 12:59:40) [GCC 9.3.0]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /home/qa/Projects/Final-Project/ansible/inventory as it did not pass its verify_file() method
script declined parsing /home/qa/Projects/Final-Project/ansible/inventory as it did not pass its verify_file() method
auto declined parsing /home/qa/Projects/Final-Project/ansible/inventory as it did not pass its verify_file() method
Parsed /home/qa/Projects/Final-Project/ansible/inventory inventory source with ini plugin

PLAYBOOK: test-playbook.yml ******************************************************************************************************
2 plays in test-playbook.yml

PLAY [bastion] *******************************************************************************************************************

TASK [Gathering Facts] ***********************************************************************************************************
task path: /home/qa/Projects/Final-Project/ansible/test-playbook.yml:1
<bastion_public_ip> ESTABLISH SSH CONNECTION FOR USER: ubuntu
<bastion_public_ip> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o 'IdentityFile="/home/qa/.ssh/bastion.pem"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ubuntu"' -o ConnectTimeout=25 -o 'ProxyCommand=ssh -W %h:%p -q ubuntu@10.0.1.49' -o ControlPath=/home/qa/.ansible/cp/13196dcaf6 bastion_public_ip '/bin/sh -c '"'"'echo ~ubuntu && sleep 0'"'"''
<bastion_public_ip> (255, b'', b'Connection timed out during banner exchange\r\n')
fatal: [bastion_public_ip]: UNREACHABLE! => {
    "changed": false,
    "msg": "Failed to connect to the host via ssh: Connection timed out during banner exchange",
    "unreachable": true
}

PLAY RECAP ***********************************************************************************************************************
bastion_public_ip                  : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0

```

# Answer
You defined multiple `ansible_ssh_common_args` vars per host. That does'nt work. Ansible will use only one of it (I asume the last). Also you try to reach the bastion host via 10.1.0.49 (but you do not mention that in your question). I think, the second `ansible_ssh_common_args` in the hostvars of `bastion` is wrong.

You could have this vars...

```
[bastions:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
...

[jenkins:vars]
ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W [%h]:%p -q ubuntu@10.1.0.49"'

```

Also - just a notice - ignoring the host key is not very "secure" - especially when you use a bastion host (which is more or less a man-in-the-middle which you need to trust).
> 1 votes

---
Tags: jenkins, amazon-web-services, ansible, amazon-ec2
---


# Question
Title: Jenkins: store build information for later reference
Is there a way to store custom information, for example my staging environment ID. I need this information for cleanup purposes later after the staging environment is no longer needed.

Ideally, I want a database table where I have these columns, `buildName`, `buildCommit`, `pullRequest`.

Then when the pull request is closed/merged I can simply find all `buildName`s and `buildCommits` for that pull request and remove them.

# Answer
If you want to use a database, you can always shell out to a database:

```
sh "mysql -u my_username -p my_password -h my_hostname -P 3306 -e \'INSERT INTO my_table (column1, column2, ...) VALUES (value1, value3, ...);\'  my_database"

```

You can also write out your data to a JSON or YAML or whatever type of file and then store it in Jenkins' built-in artifact storage with archiveArtifacts.
> 1 votes

---
Tags: jenkins
---


# Question
Title: A service by AWS that routes traffic based on simple logic
# Background

we currently use google distance matrix (GDM) apis a lot to help in core business functions. As the cost of GDM went up, we worked on switching on cheaper alternatives. We decided to use OpenStreetMap (OSM) as an alternative. Now we have OSM hosted on aws Elastic Service Container (ECS).

# Problem

Sometimes (for reasons beyond the scope of this question) the OSM service fails or times out. We put logic in the application code that if it fails (or times out, with a timeout being 1s), then switch back to GDM as a backup. The problem is that if there is a sudden burst of requests, using the ECS architecture these requests will stack up, and so if we have 20,000 requests that's a total potential lag of 20,000 seconds, and the the system crashes.

One way of solving this problem is putting in the application code logic that keeps track of the number of OSM timeouts TOs per time T(persisting that number into redis or something) and once it reaches past a certain number, we will switch back to GDM, and after Z time elapsing, we want to try using OSM again (the idea is that the server would be operational again).

# Question

Is it possible to do the above in an AWS Service that is specialized for such routing problems? I was thinking something like AWS Gateway but I couldn't find a place where routing logic can be put there.

# Answer
> 2 votes
You can use AWS APP MESH to route traffic between `OSM` and `GDM`. First, all traffic will be sent to `OSM` using `App Mesh`'s `VirtualRouter`.

`VirtualRouter` is an object to route traffic between `K8S` services. One service will be pointed to the `ECS` hosted `OSM`. Another service will be pointed to `GDM` using `External Service`

You can use a `Cronjob` which will run in a pod and sense timeout-related metrics from `ElasticCache`. If the condition matched - the code host in the pod and running as a `CronJob` will modify `VirtualRouter`.

---
Tags: amazon-ecs, fargate, api-gateway
---


# Question
Title: Sonarqube taking massive amounts of memory
I am running Sonarqube on a monolithic application on our CI server and the scanner (not the Sonarqube server) is taking over 60GB of memory.

Is this normal?

What can I do so the scanner will not use so much memory during the Sonarqube scan?

# Answer
> 1 votes
Please refer to the following article on the SonarQube - SonarScanner setup best practices. It will be good if the following hardware recommendations are considered for the SonarQube installations. Following are some of the important considerations.

* SonarQube server should be on a real DB not on H2.
* The analysis should occur very close to the SonarQube DB.

---
Tags: continuous-integration, cicd, sonarqube
---


# Question
Title: Ansible hosts group reference does not work
I'm trying for hours already to run a docker installation on a specific group of hosts.

This is my hosts.yml

```
all:
  hosts:
    01-dev:
      ansible_host: <IP1>
    02-dev:
      ansible_host: <IP2>
    03-dev:
      ansible_host: <IP3>

  children:
    docker:
      hosts:
        01-dev
        02-dev
    dev:
      hosts:
        01-dev
        02-dev
        03-dev

```

This is my site.yml

```

- name: Configure hosts
  hosts: dev
  tasks:
    - name: Update and upgrade apt packages
      become: true
      apt:
        upgrade: yes
        update_cache: yes
        cache_valid_time: 86400 #One day
    - name: Install needed network manager libs
      become: yes
      ansible.builtin.package:
        name:
          - network-manager
        state: present
    - name: "Configuring eth"
      become: yes
      community.general.nmcli:
        conn_name: "System ens18"
        ifname: ens18
        type: ethernet
        state: present
        autoconnect: yes
        ip4: "{{ansible_host}}/24"
        gw4: "192.168.3.1"

  hosts: docker
  become: true
  tasks:
    - name: Install aptitude using apt
      apt: name=aptitude state=latest update_cache=yes force_apt_get=yes

    - name: Install required system packages
      apt: name={{ item }} state=latest update_cache=yes
      loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools']

    - name: Add Docker GPG apt Key
      apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
        state: present

    - name: Add Docker Repository
      apt_repository:
        repo: deb https://download.docker.com/linux/ubuntu bionic stable
        state: present

    - name: Update apt and install docker-ce
      apt: update_cache=yes name=docker-ce state=latest

    - name: Install Docker Module for Python
      pip:
        name: docker

```

Then I run the command `ansible-playbook -i hosts.yml site.yml -vvv --ask-become-pass` and I get the error that there are no hosts for a group `docker`

What is wrong with my hosts file?

# Answer
I think it should be:

```
children:
    docker:
      hosts:
        01-dev:
        02-dev:

```

(The colon)
> 1 votes

---
Tags: docker, ansible, ubuntu
---


# Question
Title: Parameterized Kubernetes manifest files?
I'm learning Kubernetes, coming from an AWS/CloudFormation background to set up my company's infrastructure. One of the strengths of CloudFormation is the use a template that can be parameterized for re-used. So I can use the **same** template to deploy all our microservices in Fargate, giving it the Docker image, version, CPU/memory counts, etc for each microservice.

When using Kubernetes manifest files, is there good way to "templatize" manifest files? I've read kustomize, but as the title says it's "template-free," and to use it for all our microservices, I'll need multiple `/someapp/...` directory trees, which is NOT what I want.

Sure I can use `sed` but that seems archaic. I can use `yq` to massage my yaml files, but this also seems archaic. For either approach, changing a manifest file entails changing the corresponding `sed` and `yp` commands.

Any suggestions on how to approach this? How about 3rd party tools like Codefresh? How about `helm`? (I haven't looked at it yet.).

# Answer
I educated myself more about `helm` and it looks like it has these features that I need

* packaging
* templating
* release management, including rollbacks

so I'll study it more.
> 1 votes

---
Tags: kubernetes, helm
---


# Question
Title: Azure Devops - workflow/strategy for uploading only changed files to shared hosting provider after a build of static website (Jekyll)
**Scenario:**

I'm using the Ruby/Jekyll build process to generate a static website from markdown etc files via a templating process -- the same flow as the one used by Github Pages but instead of hosting it on Github I want to be able to upload it to my (existing) shared hosting provider and serve the files from there. (I already have DNS and everything in place with the web host.)

The hosting provider offers FTP and SSH via cPanel but no direct hook in to Git.

The build process (which I am doing manually for now, but will eventually become an automated build process and no doubt generate more questions!) creates/updates the static files in a '\_site' directory within my repo.

My local "CI" build (on my own pc) uses a development branch and then when happy with the changes I push them up into master.

**Where I'm stuck:**

I want to be able to use an Azure Devops release pipeline to get the files into my web host, triggered by a merge into master.

I have had this running successfully (triggered manually, but I don't think the trigger part is a problem) using an inbuilt FTP task to grab the contents of the '\_site' directory as an artifact and FTP them up to the web host.

However the FTP task (and the artifact) isn't very 'smart', in that it will re-upload everything every time I want to deploy even if only a few files have changed. This obviously takes longer and eats into my (metered) bandwidth for uploading (and seems like it is not good DevOps!)

Most often, only a small subset of files are actually changed by the build. This is usually where a new page is created or a stylesheet changed for example. Occasionally, all files are actually changed, such as if an "included" component changes so that all the static pages have to be re-rendered.

**What I'm looking for** is an approach or workflow to just upload the changed (and new) files, rather than all the files. It sounds like it ought to be easy, so perhaps I am missing something.

# Answer
I don't think you are missing any easy solutions because

1. the easy solutions probably rely on you having full access to the webserver -- which you don't have? The challenge is what is the best you can do given limited server access.
2. FTP does not have a reliable, built-in way to only upload changed files.

I think:

The viable solutions both amount to 'save hashes of the files on the server, then compare before upload'. However if you can get your pipeline to install and use `git-ftp` then `git-ftp` will do all that for you.
> 2 votes

---
Tags: git, azure-devops, continuous-deployment, jekyll
---


# Question
Title: GitLab CI/CD and building on Mac Mini with M1 Processor - Provision Profile
## I followed a guide

to setup a simple GitLab runner on my 2020 mac Mini with an M1 processor. **Everything builds great except for iOS.**

# My error:

```
Xcode build done.                                           33.0s
Built /Users/directories/build/ios/iphoneos/Runner.app.
$ cd ios
$ xcodebuild clean archive -workspace Runner.xcworkspace -scheme Runner -archivePath RunnerArchive
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild clean archive -workspace Runner.xcworkspace -scheme Runner -archivePath RunnerArchive
User defaults from command line:
    IDEArchivePathOverride = /Users/directories/ios/RunnerArchive
note: Using new build system
note: Building targets in parallel
** CLEAN SUCCEEDED **
note: Using new build system
note: Building targets in parallel
note: Planning build
note: Constructing build description
error: Provisioning profile "iOS Team Provisioning Profile: com.company.app" doesn't include the currently selected device "my Mac mini" (identifier 11111111-111-1111-1111-11111111). (in target 'Runner' from project 'Runner')
** ARCHIVE FAILED **
Cleaning up file based variables
00:00
ERROR: Job failed: exit status 1

```

If I use `flutter build ios` *from the command line, and even distribute with Xcode's GUI (no modifications), **everything works fine**.*

I noticed this post about changing the xcodebuild destination, but I'm not sure how to approach this with flutter.

# Here's my gitlab-ci.yml.

```
stages:
##  - test # All jobs related for testing such as Unit Test
#  - builda
  - buildi

#flutter_test: # Name of the lane
#  stage: test # type of stage
#  script:
#    - flutter test # Run Flutter test
#  tags:
#    - flutter # Tags for runner

#flutter_build_android: #Job name
#  stage: builda # kind of job
#  before_script:
#    - flutter packages get
#    - flutter clean
#  script:
#     - flutter build apk
#  artifacts:
#    paths:
#      - build/app/outputs/apk/release/app-release.apk
#  tags:
#    - flutter

flutter_build_ios:
  stage: buildi
  before_script:
    - flutter packages get
    - flutter clean
  script:
    - flutter build ios
    - cd ios
    - xcodebuild clean archive -workspace Runner.xcworkspace -scheme Runner -archivePath RunnerArchive
    - xcodebuild -exportArchive -archivePath RunnerArchive.xcarchive -exportOptionsPlist ExportOptions.plist -exportPath ./build
  artifacts:
    paths:
      - ios/build/Runner.ipa
  tags:
    - flutter

```

# flutter doctor. jic:

```
[✓] Flutter (Channel master, 1.26.0-18.0.pre.211, on macOS 11.2 20D64 darwin-arm, locale en-US)
    • Flutter version 1.26.0-18.0.pre.211 at /Users/User/Dev/flutter
    • Framework revision 643e65984a (7 hours ago), 2021-02-05 08:58:31 -0800
    • Engine revision b04955656c
    • Dart version 2.13.0 (build 2.13.0-0.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/User/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome)
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.53.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.19.0

```

It seems to be acting as though I'm trying to run the app on my Mac? Is that correct? *Why should it care?*

**I'm not sure one issue starts an another begins here**. I understand if I have posted in the wrong place. Thanks to anyone with anything to offer.

# Answer
> 1 votes
I needed to change the distribution type. Thanks!

---
Tags: gitlab, gitlab-ci-runner, macos, ios
---


title: trying to display 3 - 5 commands

text:
# Question
Title: trying to display 3 - 5 commands
I was trying to display a few commands with .stdout - the gives me the mixed output also with "item"

with item it gives me:

just the strings:

uname -a

uptime

but not the output of those commands

this is the play-book with commented stuff there that does not work:

```
    - name: To Display === UPTIME and KERNEL Version ===
#    - name: "To Display === {{ item }}"
      command: "{{ item }}"
      loop:
        - uname -n
        - uptime -p
        - uname -r

#        command: uname -n
#      shell: uptime -p; uname -r; rpm -qa --last kernel
#      register: OUTPUT
#    - debug: msg="{{ OUTPUT.stdout('\n') }}"
#    - debug: msg="{{OUTPUT.stdout}}"
#    - debug: var="{{OUTPUT.stdout}}"
#      shell: "{{item}}"
#      with_items: ['hostname', 'whoami']
#        - uptime -p
#
#        - uname -r
#        - rpm -qa --last kernel
...

```

# Answer
> 2 votes
If you just want to print a subset of the results of your commands on your terminal without using one or more `-v` flags, you can refactor your playbook to show just the standard output from each of the commands using a JSON query. For example:

```
---
- name: display info
  hosts: localhost
  tasks:
  - name: Display uptime and kernel info
    shell: "{{ item }}"
    with_items:
      - uptime
      - uname -n
      - uname -r
    register: output

  - debug: msg="{{ output.results | json_query('[].stdout[]') }}"

```

This will yield output similar to the following:

```
PLAY [display info] **********************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [localhost]

TASK [Display uptime and kernel info] ****************************************************************
changed: [localhost] => (item=uptime)
changed: [localhost] => (item=uname -n)
changed: [localhost] => (item=uname -r)

TASK [debug] *****************************************************************************************
ok: [localhost] => {
    "msg": [
        "22:48  up 4 days,  3:41, 2 users, load averages: 1.26 1.39 1.42",
        "localhost.local",
        "20.3.0"
    ]
}

PLAY RECAP *******************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

```

---
Tags: ansible
---


# Question
Title: What's better: 2 pods (on the same server) or 1 standalone application?
For a client we're going to roll out a certain type of software installation.

(I can give more details in the comments if you like.)

The question is: would you go for 2 pods (on the same server)?

Or would a single installation be more stable?

The software is stable as such but my concern is pods, by nature, are meant to be replaceable...

There is also the option of a single pod on the machine, but I have deep concerns about this approach...

My guess is that once 1 pod gets into to much trouble (memory pressure to name a thing) Kubernetes is going to restart it, as pods are meant to be replaceable.

(Bringing down the clients' application during the process.)

So I guess 2 pods is a solution here.

1 pod should be able to handle the load (his load + the extra load of the restarting pod).

What I don't know is whether 2 pods would be as stable as running the software on 1 node, without Kubernetes.

In the same process we're also going to roll out 2 pods on 2 virtual machines, with other software,

so the choice whether we do or don't use Kubernetes doesn't depend on this part of the implementation alone.

# Answer
> 2 votes
## Is the app stateless

> The software is stable as such but my concern is pods, by nature, are meant to be replaceable

This is your primary concern. Is the app *stateless* (e.g. can the requests be served by any of multiple instances without problem?). If **not** \- be very careful to run it on Kubernetes (e.g. don't use rolling-deployment) and don't run the app in the cloud :)

Apps running on Kubernetes or cloud should follow The Twelve Factor principles

## Number of Servers

It would be good to be able to use two or more servers. This reduce the Single-Point-Of-Failure, and you can e.g. take down one server for maintenance but still serve your users.

## App directly on Server or in Container

> pods (on the same server) or 1 standalone application?

An application runs as a *process* on the Operating System, whether you run it on a container or as non-container process. There is almost no runtime overhead, what you get with containers is *repeatability* and *maintainability*.

A container is designed to be *hermetically sealed*, so it is not sensitive to your servers configuration e.g. what language-settings or character encoding. This was a bigger problem before containers was used. With containers the app runs in an identical environment every time, except the *kernel*. In addition it is easier to maintain and manage processes when run as containers, you can e.g. set limits for CPU usage, Memory limit and they get its own network e.g. multiple containers on the same server can listen to port 8080 (from the applications standpoint).

If your apps run as containers on a server cluster, you can also easyli scale out or in by adding or removing servers.

## Control of resources

> My guess is that once 1 pod gets into to much trouble (memory pressure to name a thing) Kubernetes is going to restart it, as pods are meant to be replaceable.

Yeah, but this is a good thing. Kubernetes is mostly *self-healing*. If you don't have such "control-loops", you will need manual internvention - since it is the same app that e.g. may have memory leaks.

## Run app on Kubernetes or not

> whether we do or don't use Kubernetes doesn't depend on this part of the implementation alone

The first thing to check: **Is the app stateless?** and also, you should use **two or more servers** otherwise you get little advantage of running it in Kubernetes.

There is a cost to maintain Kubernetes. You need skills and you need to maintain an addition system. Make sure it adds enough value for you.

---
Tags: kubernetes
---


# Question
Title: AWS S3, as an organizer see empty bucket
I am an owner of organizer in on my aws account. When I enter S3 I see one folder, which is empty. But its being billed 8$ per month, so smth should be there.

Is it possible that one account, of my organization uploaded there some stuff and I dont see it ?

# Answer
> 1 votes
Does the bucket have versioning enabled? You should be able to see it in the bucket properties: Versioning: enabled. If so, when you are looking at the empty folder, at the top there is a switch "show versions", switch it on. Do you see some objects with hashes? Try to delete them. Be careful, there are versions and "delete markers", you have to delete both in order to completely empty the bucket.

Another option: you are billed for requests and data transfers https://aws.amazon.com/s3/pricing/?nc=sn&loc=4 If something is checking the bucket rapidly, it can generate some costs.

But most often the delete versions is the reason.

---
Tags: amazon-s3
---


title: docker mariadb access from remote

text:
# Question
Title: docker mariadb access from remote
I created a docker container with docker-compose in my VPS and I want to access it from my local computer but the connection will refuse. also, I allowed the 3306 port in the VPS.

my `docker-compose.yml` file:

```
version: "3"

services:
  mariadb:
    image: mariadb
    container_name: mariadb
    restart: 'always'
    volumes:
      - ./conf:/etc/mysql
    environment:
      MYSQL_ROOT_PASSWORD: ${password}
      MYSQL_DATABASE: ${database}
      MYSQL_USER:  ${username}
      MYSQL_PASSWORD: ${password}
    ports:
      - 3306:3306

```

how may I access the MariaDB server from my local computer?

# Answer
> 1 votes
Check netstat -tlpn on the VPS, can you see 0.0.0.0:3306 or something like that? If so, check the firewall. Both the firewall in the operating system and the firewall from the VPS provider (if there is any). As a last resort (and not a bad idea) - you can connect to your VPS via VPN - there are good openvpn tutorials on the internet. The reason why the VPN is a good idea - especially for a development server is that you may need to allow the user from everywhere (if you do not have a static IP address) and if you accidentally create some 'testuser' with 'testpassword' anybody from the internet will be able to connect to your db. So use good passwords, limit access to your public IP and use VPN if possible.

---
Tags: docker, docker-compose
---


# Question
Title: Is there an idiomatic way to create reusable Packer templates?
I'm creating about 10-12 Packer templates which almost all work the same way. Same builder (Amazon EBS), with some small variations in AMI names, and almost the same provisioner (Ansible Remote) - sometimes with additional variables and sometimes multiple playbooks.

But, much of the Packer templates remain the same.

I know I can use variables to get some of the changeable values into one place in the file. But I'm keen to cut down on all of the copy-pasta in the templates.

I could do this with a wrapper shell script utilising `jq` or something. But each complexity I add gives something else for others to learn. Try as I might, I can't seem to find a 'blessed' idiomatic way of doing this with Packer.

Is there an idiomatic way of doing this - or at least a generally accepted way?

# Answer
So far, I've taken to defining the default `builders` and `provisioners` we use, with user variables interpolated in where required, eg:

```
 "type": "amazon-ebs",
 "instance_type": "t2.micro",
 "ami_name": "{{ user `ami-name` }}

```

I've got files called eg. `packer-builders.json` and `packer-provisioners.json`, and then all the separate Packer templates in their own directories.

I've then written a quick Bash script that takes the name of the template one wants to build, finds all the `packer-*.json` files, and uses `jq --slurp` to merge them in (eg. `jq --slurp '.[0] * .[1] * .[2]' $LIST_OF_FILES`) with the supplied template at the end. It saves the output and sends that along to `packer build`.

As a bonus, I'm also using `jsmin` before hitting `jq` so that I can include comments in any of the JSON files.

It works well, but I'm not a *massive* fan of it because it's custom and it adds an additional barrier for entry for others coming across it (much more to consider than just `packer build something.json`!

So I'm really keen for additional answers here if there's a better way to do this.
> 3 votes

# Answer
Packer has taken an active decision not to build in such capabilities. This problem is much better solved by other tools such as jq, etc. We think the best way to leverage Packer is to wrap it if you need more ways to create the template.

It's very easy to create json in any programming language which gives you unlimited expressiveness when creating templates. One great way to manipulate templates is to define them in *jinja2* and preprocess it with Python.
> 3 votes

# Answer
Utilizing the HCL2 syntax is definitely the correct approach here. You can use the different building blocks to define different source blocks and then assign sources to the builders and even conditionally execute the provisioners and post processors on specific sources using only/except.

Using this approach you can easily accomplish what you are looking for. Here is a rough example adapted from the hashicorp documentation with multiple sources and ansible:

```
source "amazon-ebs" "first-example" {
    ...
}
source "amazon-ebs" "second-example" {
    ...
}
build {
  name = "my_build"
  sources [
    "source.amazon-ebs.first-example","source.amazon-ebs.second-example"
  ]

# I run on both sources
provisioner "ansible" {
        playbook_file = "common.yml"
  }

# Only runs on first example
provisioner "ansible" {
    only = ["source.amazon-ebs.first-example"]
    playbook_file = "playbook-a.yml"
  }

# Never runs on second example
provisioner "ansible" {
    except = ["source.amazon-ebs.second-example"]
    playbook_file = "playbook-b.yml"
  }
}

```

Depending on your source blocks and the builder being used, this opens up the ability to template multi-cloud, arch, distribution and purposed images from the same packer build command.
> 3 votes

# Answer
This is what source blocks are for in HCL2. I've been using this approach recently (define builder in a source block, then use it from various build blocks, filling in the variables as needed) and believe this to be the new best practice / idiom.
> 2 votes

---
Tags: packer
---


# Question
Title: Why I cannot access k3s service from pod in rasbian?
I have installed K3S kubernetes on rasbian, and created a following mysql deployment on it:

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 100Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-config
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-log
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 100Gi
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  ports:
  - port: 3306
    name: mysql
    targetPort: 3306
  selector:
    app: mysql

---

apiVersion: v1
kind: Service
metadata:
  name: mysql-nodeport
spec:
  type: NodePort
  selector:
    app: mysql
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 3306
      targetPort: 3306
      # Optional field
      # By default and for convenience, the Kubernetes control plane will allocate a port from a range (default: 30000-32767)
      nodePort: 30036

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  selector:
    matchLabels:
      app: mysql
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      securityContext:
        fsGroup: 999
      containers:
      - name: mysql
        image: hypriot/rpi-mysql:latest
        imagePullPolicy: "IfNotPresent"
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: mypassword
        ports:
        - containerPort: 3306
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: mysql-data
        - mountPath: /var/log/mysql
          name: mysql-log
        - mountPath: /etc/mysql
          name: mysql-config
      volumes:
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-data
      - name: mysql-config
        persistentVolumeClaim:
          claimName: mysql-config
      - name: mysql-log
        persistentVolumeClaim:
          claimName: mysql-log
      nodeSelector:
        mysql: master

```

I cannot access mysql by the above definied service:

I have checked the mysql service is accessable:

```
sudo kubectl exec -it mysql-d6656577c-6rdzr bash
root@mysql-d6656577c-6rdzr:/# echo > /dev/tcp/localhost/3306
root@mysql-d6656577c-6rdzr:/# echo $?
0
root@mysql-d6656577c-6rdzr:/# echo > /dev/tcp/mysql-d6656577c-6rdzr/3306
root@mysql-d6656577c-6rdzr:/# echo $?

```

0

But the service is not working:

```
root@mysql-d6656577c-6rdzr:/# echo > /dev/tcp/mysql/3306
bash: mysql: Name or service not known
bash: /dev/tcp/mysql/3306: Invalid argument
root@mysql-d6656577c-6rdzr:/#

```

Service description:

```
sudo kubectl describe svc mysql
Name:              mysql
Namespace:         default
Labels:            app=mysql
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"mysql"},"name":"mysql","namespace":"default"},"spec":{"p...
Selector:          app=mysql
Type:              ClusterIP
IP:                10.43.58.35
Port:              mysql  3306/TCP
TargetPort:        3306/TCP
Endpoints:         10.42.0.161:3306
Session Affinity:  None
Events:            <none>

```

Core DNS logs:

```
sudo kubectl logs -f coredns-d798c9dd-npbj4 --namespace=kube-system
.:53
[INFO] plugin/reload: Running configuration MD5 = 4665410bf21c8b272fcfd562c482cb82
   ______                ____  _   _______
  / ____/___  ________  / __ \/ | / / ___/  ~ CoreDNS-1.6.3
 / /   / __ \/ ___/ _ \/ / / /  |/ /\__ \   ~ linux/arm, go1.12.9, 37b9550
/ /___/ /_/ / /  /  __/ /_/ / /|  /___/ /
\____/\____/_/   \___/_____/_/ |_//____/
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:34250->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:47752->8.8.4.4:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:57505->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:51583->8.8.4.4:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:39172->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:39568->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:39343->8.8.4.4:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:40929->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:43962->8.8.8.8:53: i/o timeout
[ERROR] plugin/errors: 2 1587632103.896807637. HINFO: read udp 10.42.0.160:47330->8.8.8.8:53: i/o timeout

```

I cannot understand this, because 8.8.8.8 is accessable from host raspberry pi and 8.8.8.8 not contains local dns names (for instance: mysql)

```
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=10.10 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=11.3 ms

```

What can be the problem? Why I cannot access mysql?

# Answer
> 2 votes
It looks like you are configuring two services, mysql and mysql-nodeport to use the same port. Without information to indicate otherwise im assuming this is a 1 node setup with rasbian. I personally dont have raspbian installed to test, but try something like this:

```
---
apiVersion: v1
kind: Service
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  type: NodePort
  selector:
    app: mysql
  ports:
  - port: 3306
    name: mysql
    targetPort: 3306
    nodePort: 30036

```

Per the kubernetes service documentation: *NodePort: Exposes the Service on each Node's IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created. You'll be able to contact the NodePort Service, from outside the cluster, by requesting :*

If you want your service available on the node port, try updating your service and deleting the other service definition.

---
Tags: kubernetes, deployment, networking
---


# Question
Title: What would be the best way to improve this Gitlab CI/CD (Gitlab.com) pipeline's efficiency and consistency?
This project has a pipeline that runs integration tests against a spun up instance of Gitlab. Each Job in the integration test stage has its own instance testing different build distributions (es, cjs, original source). Unfortunately, the shared runners have limited resources and inconsistently cause these jobs to fail because the spun up GitLab instances have insufficient resources. This occurs more often when I have more than one instance spin up at a time since the jobs run in parallel.

Here is a test repo showcasing the problem and it's pipeline

Gitlab Support has suggested using a dedicated runner OR refactoring my pipeline. Since I'm trying to maintain a $0 cost for this open-source project, the only feasible suggestion (that I'm aware of) is the latter one.

I've tested doing just this, specifically splitting these integration tests into separate stages to stop creating multiple GitLab instances at the same time. This, however, has not improved the results. The only other idea I can think of is running all the integration tests in the same script, instead of separate stages or jobs, which would only require spinning up one instance of GitLab. In this solution, I would have to add some sort of id's to the data being created in the tests to avoid having clashes (i.e., creating a project must use a unique name)

What I want to figure out is if I'm overlooking something? Are there any better ways to improve the pipeline to avoid the resource bottlenecks causing the crashing?

# Answer
My solution to this problem was two fold.

**First**: As mentioned in the question, I was able to reduce the amount of concurrent Gitlab Instance runners to one, to avoid the usage of too many resource which was causing the shared runner freeze. To do this i moved all my integration tests into a single job. This didn't increase the time of the tests significantly because the largest time cost was the Gitlab instance setup.

**Second**: I utilized the retry functionality of the docker image, to respin the CI job if there was an error. I set the retry property to 2, that way it would catch erroneous instance issues, but still fail if a consistent error occurred.

This approach seems to be working well so far! Hopefully it holds out.
> 0 votes

# Answer
Can you explain the reason for why the "step\_script" installs the dependencies and not use a prebuild images that has all the dependencies installed?

### Solution

Based on the information you provided, Your test infrastucture rebuild even the test container from scratch.

You tests take a long time to be done as those lines indicate also a fresh composing of the docker container:

> (1/11) Installing ca-certificates (20191127-r2)
> (2/11) Installing nghttp2-libs (1.40.0-r1)
> (3/11) Installing libcurl (7.67.0-r3)
> (4/11) Installing expat (2.2.9-r1)
> (5/11) Installing pcre2 (10.34-r1)
> (6/11) Installing git (2.24.3-r0)
> (7/11) Installing c-ares (1.15.0-r0)
> (8/11) Installing libgcc (9.3.0-r0)
> (9/11) Installing libstdc++ (9.3.0-r0)
> (10/11) Installing nodejs (12.20.1-r0)
> (11/11) Installing yarn (1.19.2-r0)

If you build a docker image with those thing preinstalled, your Tests will run much faster.

This Process creates clean environment where the only change to it will be the code that has changed!!

The new Docker image then need to be only pulled ones and can be reused.

# Build/test infra

`docker run -v "$(pwd)"/target:/app:ro -name BUILDID jdalrymple/docker-compose-with-node yarn test`

run that for each of your tests.
> 1 votes

---
Tags: gitlab, gitlab-ci-runner
---


# Question
Title: Prometheus alert CPUThrottlingHigh raised but monitoring does not show it
I have installed Prometheus to monitor my installation and it is frequently raising alerts about CPU throttling.

The Prometheus alert rules to identify this alert is :

```
alert: CPUThrottlingHigh
expr: 100
  * sum by(container_name, pod_name, namespace) (increase(container_cpu_cfs_throttled_periods_total{container_name!=""}[5m]))
  / sum by(container_name, pod_name, namespace) (increase(container_cpu_cfs_periods_total[5m]))
  > 25
for: 15m

```

If I look at one of the pods identified by this alert, it does not seem to have any reason to throttle :

```
$ kubectl top pod -n monitoring my-pod
NAME            CPU(cores)   MEMORY(bytes)
my-pod          0m           6Mi

```

This pod has one container with these resources setup :

```
Limits:
  cpu:     100m
  memory:  128Mi
Requests:
  cpu:     25m
  memory:  64Mi

```

And the node that is hosting this pod is not under any heavy cpu use :

```
$ kubectl -n monitoring top node aks-agentpool-node-1
NAME                       CPU(cores)   CPU%      MEMORY(bytes)   MEMORY%
aks-agentpool-node-1       853m         21%       11668Mi         101%

```

On grafana, if I look at the chart for this pod, it never goes above `0,000022` of cpu usage

Why is it throttling ?

# Answer
The `CPUThrottlingHigh` is an alert created by the kubernetes-mixin project. There is an open issue (#108) to discuss this alert. I suggest that you read all the comments on this issue to better understand the problem.

In short, the problem is: When working with low CPU limits, spiky workloads can have low averages and still be being throttled.

Also, take a look at this issue (#67577) from Kubernetes project, which addresses a Kernel bug in CFS quotas that may cause unnecessary CPU throttling. The discussion is still open, and the Kubernetes project are even considering disabling CFS quotas for pods in the `Guaranteed` QoS (see #70585 for reference).

Consider the following options:

* Increase (or even remove) your container CPU limits
* Disable Kubernetes CFS quotas entirely (kubelet's flag `--cpu-cfs-quota=false`)
* Use a Kernel version that contains this fix (torvalds/linux 512ac99)
> 15 votes

# Answer
To piggy back off of @eduardo-baitello answer, A third option is to increase the `CPUThrottlingPercent` config here
> 2 votes

---
Tags: docker, kubernetes, monitoring, prometheus
---


# Question
Title: Ingress ip returns HTTP error DNS_PROBE_FINISHED_NXDOMAIN
I have the next ingress (output of "kubectl get ingress")

```
NAME   HOSTS   ADDRESS          PORTS   AGE
main   *       192.168.39.190   80      46m

```

But when I try to visit that IP address in chrome I get

```
Cannot access the website. Check if there's a write error in name.local
DNS_PROBE_FINISHED_NXDOMAIN

```

Any idea why? Everything is green on the dashboard, there are errors.

# Answer
> 1 votes
There are two main reasons for this issue to happen:

1. Your dns are not exposed.
2. Your code is redirecting to a https address (and since you are working in your local machine, most likely you don't have a secure certificate)

## CASE 1 - Exposing DNS

On linux you can solve it like:

* minikube ip
* vim /etc/hosts
* Add the ip from the first step and the hostname you want to expose, and save the file.

```
# For example
192.168.39.70   elasticsearch-es-http

```

No need to restart any service, it should work just like that. Add all the hostnames you need.

## CASE 2 - HTTPS on minikube

If your problem is 2, then you have to find a way for you application to not use HTTPS while you are using minikube.

---
Tags: kubernetes, ingress, http, minikube
---


# Question
Title: How to store/retrieve multiple ansible-vault passwords within/from a single file
**Update**: As @yaobin pointed out. It appears they removed the part about the multiple passwords being in a single file. It was here as can be seen from web archive:
https://web.archive.org/web/20201202040251/https://docs.ansible.com/ansible/latest/user\_guide/vault.html
But now it is gone:
https://web.archive.org/web/20210128225633/https://docs.ansible.com/ansible/latest/user\_guide/vault.html
So I am not sure if this problem can be solved anymore the way that was described in the manual at the time. It was apparently a manual bug :(

---

The manual says at storing passwords in files section:

> To store a vault password in a file, enter the password as a string on a single line in the file. Make sure the permissions on the file are appropriate. Do not add password files to source control. If you have multiple passwords, you can store them all in a single file, as long as they all have vault IDs. For each password, create a separate line and enter the vault ID, a space, then the password as a string. For example:

and there is an example:

```
dev my_dev_pass
test my_test_pass
prod my_prod_pass

```

However there is no usage exampes for this file. I tried many different ways. If I use `--vault-password-file` the `ansible-vault` sees only `default` entry independent of the number of entries in file. With `--encrypt-vault-id=test` I get:

```
ERROR! Did not find a match for --encrypt-vault-id=test in the known vault-ids ['default']

```

If I use `--vault-id abc@file_path` with `--encrypt-vault-id=test` then I get error

```
ERROR! Did not find a match for --encrypt-vault-id=test in the known vault-ids ['abc']

```

What is the purpose of the password file described in the Ansible manual and how does one use it?

Thanks!

# Answer
> 4 votes
This afternoon I also struggled on this. I think I've understood it a little bit more so I'd like to share it. But I'm also new to Ansible Vault so what I say here may not be completely correct. I used \[1\] as my main source of learning.

## References

## What May Have Confused You

\[1\] says a `vault ID` has the pattern `label@source`. But the symbol `@` delivers the meaning of "inside", "at", or "of" which makes people think a vault ID `test@password_file` means a line inside the file `password_file` with the label `test`.

**But this is the gotcha**: according to my test, the **entire content** in `password_file` is used as the password. In your example above, the password **you think** is "my\_test\_pass"; but the password **Ansible Vault sees** is `dev my_dev_pass\ntest my_test_pass\nprod my_prod_pass` (note the white spaces and the End-of-Lines).

Therefore, `test@file_path` does not select the line "my\_test\_pass". It actually means the following:

* At **encryption**, it means "use the entire content in `file_path` as the password to encrypt the given message and marks the result with the label `test`".
* At **decryption**, it means "use the entire content in `file_path` as the password to decrypt everything that is marked with the label `test`".

## Using Multiple Password Files

Therefore, if you want to use different password files, you need to do it this way:

* Create three files (I put them at different folders intentionally for demo): `~/pass_dev.txt`, `/tmp/pass_test.txt`, `./pass_prod.txt`.
* Put the passwords into the correct files. Example: `my_dev_pass` into `pass_dev.txt`.
* When you encrypt the file `my_dev_file.yml`, you have two options:
    + You can specify just one vault ID: `ansible-vault encrypt --vault-id dev@~/pass_dev.txt my_dev_file.yml`
    + You can specify multiple vault IDs but must also use `--encrypt-valut-id` to tell `ansible-vault` which one should actually be used to encrypt the file: `ansible-vault encrypt --vault-id dev@~/pass_dev.txt test@/tmp/pass_test.txt prod@./pass_prod.txt --encrypt-vault-id dev my_dev_file.yml`

When you need to decrypt some content, you may or may not know what password the content was encrypted with. In this case, you can pass in all the possible vault IDs: `ansible-vault decrypt dev@~/pass_dev.txt test@/tmp/pass_test.txt prod@./pass_prod.txt some_encrypted_file.yml`. And vault will automatically figure out which password to use. This is talked about in this section of \[1\].

This also explains why the `label` part is only used as a hint. In fact, you can pass in the vault IDs with completely wrong labels:

```
ansible-vault decrypt prod@~/pass_dev.txt dev@/tmp/pass_test.txt test@./pass_prod.txt some_encrypted_file.yml

```

And `ansible-vault` is still able to decrypt the file, because, essentially, `ansible-vault` uses the `label` as the hint to see which password should be tried first. If it doesn't succeed, it tries the other passwords.

But if you define the environment variable `ANSIBLE_VAULT_ID_MATCH`, `ansible-vault` will take the labels seriously and only try the passwords with matching labels, so the following will fail:

```
ANSIBLE_VAULT_ID_MATCH=1 ansible-vault decrypt prod@~/pass_dev.txt dev@/tmp/pass_test.txt test@./pass_prod.txt some_encrypted_file.yml

```

## Other Things in Your Question

I may not be completely correct in this part: I guess `ansible-vault` maintains an internal list of "currently available vault IDs". If no `--vault-id` is present on the command line, the only available vault ID is `default`. When `--vault-id` arguments are given, the `default` is overridden by whatever is provided.

Therefore, when you encrypted the target file using a `--vault-password-file`, without any other `--vault-id`, the only available vault ID was `default`. But by providing `--encrypt-vault-id=test` you were asking `ansible-vault` to encrypt the target file using a vault ID of "test" which was not available, hence the error "Did not find a match".

Later, when you provided `ansible-vault` with only `--vault-id abc@file_path` but asked it to encrypt the target file using `test`, `ansible-vault` still couldn't find the required vault ID, hence the error "Did not find a match" again.

You made the mistake because you thought `test@file_path` selects one password from all the available passwords in `file_path`, so by providing one password file, you thought you had provided multiple passwords. But that doesn't seem to be how `ansible-vault` works. You need to provide multiple password files (or, technically, multiple password sources which could also be prompts and scripts).

# Answer
> 2 votes
I totally misunderstood you. Here is a new attempt to actually answer your question. :)

1. Create a passwords file:

```
root@2ca77340d571:/# cat .passvaults
dev my_dev_pass
test my_test_pass
prod my_prod_pas

```
2. Create a file to encrypt:

```
root@2ca77340d571:/# cat extravaulty.yml
chocolate:banana

```
3. Encrypt the file:

```
root@2ca77340d571:/# ansible-vault encrypt --vault-id=dev@.passvaults extravaulty.yml
Encryption successful

```
4. View the raw file:

```
root@2ca77340d571:/# cat extravaulty.yml
$ANSIBLE_VAULT;1.2;AES256;dev
33336336336238326137393764316333623231336238323931306166626434653164326330656566
3561356333343435663538623661363661373461356461300a663361666331323031623530343930
62633230636566643339663637386438336539383162346634393031633165333033396238363163
6134383233346538330a326266626261346638303738313862656337396237343231326231656139
34376334663664343164303462356431306539316232323761386164643735376330

```

and the decrypted file:

```
root@2ca77340d571:/# ansible-vault view --vault-id=dev@.passvaults extravaulty.yml
chocolate:banana

```

As I understand it, when you use `--vault-id=dev@.passvaults` you are telling it to use `dev` as a hint (not the vault password) and `.passvaults` as the file where the encrypt/decrypt password is.

This means that you can also do this:

```
root@2ca77340d571:/# ansible-vault view --vault-id=prod@.passvaults extravaulty.yml
chocolate:banana

```

Or this

```
root@2ca77340d571:/# ansible-vault view --vault-id=.passvaults extravaulty.yml
chocolate:banana

```

Which is not intuitive to me. Does this help?

---
Tags: ansible, ansible-vault
---


# Question
Title: How to read array and loop server selection and deployment
I have configured jenkins parameter deployment job using active choices parameterize plugin. In my dev server section have two servers called, 192.168.94.139, 192.168.94.140

I want to read this array input and deploy to both servers. As an example if I select both servers artifacts should be deployed to both servers. How can I read those inputs to fulfill my requirement. Until this point I wrote an array to read inputs but it prints like this

> 192.168.94.139,192.168.94.140

```
my_array=($SERVER_SELECTION)
for i in ${my_array[@]}
do

   echo $my_array

done

```

# Answer
> 2 votes
Look this:

```
#!/bin/bash
#Get servers list
set -f
string=$DEPLOY_SERVER
array=(${string//,/ })
for i in "${!array[@]}"do
      echo "Deploy project on server ${array[i]}"
done

```

I found this link

# Answer
> 0 votes
An elegant way is to use **IFS environment variable** (Internal Field Separator) to define a *delimiter* when assigning a string list to array.

```
IFS="," SERVERS=($SERVERS) #BTW, no need to declare a new variable, just reassign

for SERVER in ${SERVERS[@]}
do
   echo $SERVER
done

```

---
Tags: jenkins, jenkins-plugins, shell-script
---


# Question
Title: Gitlab runner fails with connection timeout
I have gitlab runner with, `docker` as executor and `docker:latest` as default image.

Runner is connected to the project and runs pipeline, but it stuck at

> Reinitialized existing Git repository in /builds/sachith/omy-project/.git/
>
> fatal: unable to access 'https://gitlab.myhost.com:1234/sachith/omy-project.git/': Failed to connect to gitlab.myhost.com port 1234: Operation timed out

I logged to gitlab-runner running server and tried cloning project as `gitlab-runner` user and it worked.

Why am I getting this error?

# Answer
It was a simple mistake I made when I register `gitlab-runner`. I just used `gitlab-runner register [options]`

But when I register it with `sudo`, it was working properly.

`sudo gitlab-runner register [option]`

Runner is running in `Ubuntu-18.04` server.
> 0 votes

# Answer
This is likely because your requests were dropped before they landed on the GitLab host. Check your firewalls and other security rules after assured that the 1234 port is open
> 3 votes

---
Tags: continuous-integration, gitlab, gitlab-ci-runner
---


# Question
Title: Documentation of Azure DevOps Server 2019 Rest API
Is there anywhere a documentation, that ony references the RestApi 5.0? So I can find only what I am able to use?

# Answer
You can not choose versions on the start page of REST API but you can do that on any other page that describes calls (https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/work%20items/list?view=azure-devops-rest-5.0):
> 1 votes

---
Tags: azure-devops
---


title: straight python alternative to ansible

text:
# Question
Title: straight python alternative to ansible
Can anyone recommend an alternative to Ansible that lets one write straight Python code? In my group, we're finding that expressing pretty simple logic in Ansible ends up being too time-consuming and ugly to specify. Also, the bunny trails that you end up going down to debug simple Ansible problems take way too much time.

Sometimes it takes hours to do (or debug) something that would take 30 seconds in straight Python.

The nice things about Ansible are:

* A nice set of concepts like roles, hosts, tasks, and playbooks.
* A nice library of preexisting modules.

.. but if one were looking for something that preserves some of those nice things from Ansible, but allows one to write straight Python for all of the configuration and logic, are there any recommendations?

# Answer
pyinfra was designed for this purpose. Fabric can also be used to script configuration.
> 3 votes

---
Tags: ansible, configuration-management
---


# Question
Title: Disabling HTTP Basic auth for requests from specific ips in k8s ingress
Currently I have a webpage which is freely accessible from certain networks an requires HTTP basic auth otherwise. This behaviour is set in the nginx config. It looks something like this:

```
geo $authentication {
    default "Authentication required";
    SOME-IP "off";
    SOME-NETWORK1 "off";
    SOME-NETWORK2 "off";
}

...
auth_basic $authentication;
...

```

Now I want to move this webpage to a k8s cluster under ingress-nginx ingress controller. As I can see from the docs it has support for basic auth but provides no ways to allow access from specific ips/networks. Is there a way/another ingress controller/tool to configure said behaviour?

# Answer
> 1 votes
The thing I was looking for was external-auth in ingress-nginx. I created a simple service with nodejs which took over all the basic-auth logic. Then I used an external link to this service in k8s annotations for restricted resources.

annotation snippet:

```
  annotations:
    nginx.ingress.kubernetes.io/auth-url: http://service-name.default.svc.cluster.local:3000/auth

```

---
Tags: kubernetes, nginx, ingress
---


# Question
Title: REST API: create project with powershell returns unspecified internal error
I'm creating a a project with the code below.
The response is always an unspecified error.

> Invoke-RestMethod : {"$id":"1","innerException":null,"message":"TF400898: An Internal Error Occurred. Activity Id: 3fbed4b2-9751-41ba-acbe-4d20f02ae556.","typeName":"System.Web.Http.HttpResponseException, System.Web.Http","typeKey":"HttpResponseException","errorCode":0,"eventId":0}
> At line:1 char:1
> Invoke-RestMethod -Uri $adoTaskUri -ContentType "application/json-pat ...
> ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
> CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) \[Invoke-RestMethod\], WebException
> FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

I tried the body in postman and the projects are created just fine.

Can someone see what I'm doing wrong?
Listing of the projects works; the body works in postman; I can create tasks with a similar script.

```
$pacToken = ""
$organizationName = "BLECUST"

$adoHeader = @{"Accept"="application/json";Authorization=("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "",$pacToken))))}
#$adoHeader #accept about anything and add security in the header

#api to create
$adoTaskUri = "https://dev.azure.com/BLECUST/_apis/projects?api-version=5.1"

#list all projects
$response = Invoke-RestMethod -Uri $adoTaskUri -ContentType "application/json-patch+json"  -headers $adoHeader -Method GET
$response.value | ft name, visibility, url

$body='{
  "name": "FabrikamTravel18",
  "description": "Frabrikam travel app for Windows Phone",
  "capabilities": {
    "versioncontrol": {
      "sourceControlType": "Git"
    },
    "processTemplate": {
      "templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
    }
  }
}'

Invoke-RestMethod -Uri $adoTaskUri -ContentType "application/json-patch+json" -Body $body-headers $adoHeader -Method POST

```

# Answer
Your script works, just update the last content type to `application/json`:

```
Invoke-RestMethod -Uri $adoTaskUri -ContentType "application/json" -Body $body -headers $adoHeader -Method POST

```

PATCH is used to update a team project: https://docs.microsoft.com/en-us/rest/api/azure/devops/core/projects/update?view=azure-devops-rest-6.1
> 3 votes

---
Tags: azure-devops, powershell
---


# Question
Title: Azure service tags REST API and subscription level rights
**Goal**

I want to use the service tags REST API endpoint to get all the AzureCloud datacenter public IP addresses.

I am aware that I could manually download the generated `json` file from Microsoft.

My end goal is to use the endpoint to programmatically automate a task.

**Problem**

I can get a response with status code 200 of about 46k lines, but the AzureCloud tag is nowhere in the response body. It skips from AzureBotService to AzureCognitiveSearch. I believe AzureCloud should be between those two tags.

**Steps**

Firstly, I created an account using the AZ CLI tool with `az ad sp create-for-rbac -n "MyApp"`.

With a tenant ID, app ID/client ID, password/client secret, subscription ID. I can use `https://login.microsoftonline.com/{{ tenant_id }}/oauth2/token` to get a bearer token.

Using the bearer token, I can query the service tags using `https://management.azure.com/subscriptions/{{ subscription_id }}/providers/Microsoft.Network/locations/eastus/serviceTags?api-version=2020-05-01`.

**What I've done**

I came across a GitHub issue that is somewhat related to my problem stating that by design, we cannot get all the datacenter public IPs if the user does not have subscription level rights.

I tried the following commands to try to give subscription scope rights to my app, but to no avail:

* `az ad sp create-for-rbac -n "MyApp2" --role reader --scopes "/subscriptions/{{ subscription_id }}"` to create a new account while specifying reader role and scope of the subscription. (I have retried the API with the new IDs as well).
* `az role assignment create --assignee "{{ app_id }}" --role "Reader" --scope "/subscriptions/{{ subscription_id }}"` to create a new role and specify scope.
* `az role assignment create --assignee "{{ app_id }}" --role "Owner" --subscription "{{ subscription_id }}"` to create a new role and specify subscription.

My app still has the scope set to "This resource".

I suspect there is something I am misunderstanding about Azure, given I am completely new to Azure (just created a free trial account yesterday).

All help will be appreciated, thank you!

# Answer
To use servicetags api you have to register Microsoft.Netowork resource provider at azure subscription level.

Instead you can use these api:

to get the ip address list of a specified Azure Service in a specified Azure region: https://azinfo.azurewebsites.net/api/servicetags/{regionName}/{serviceName}

to get valid region names https://azinfo.azurewebsites.net/api/GetRegionNameList

to get valid service names https://azinfo.azurewebsites.net/api/GetServiceNameList

to get the all the ip address list of all Azure Services in a specified Azure region https://azinfo.azurewebsites.net/api/region/{regionName}
> 0 votes

---
Tags: azure
---


# Question
Title: Is it possible to mount an s3 bucket as a point in a docker container?
I have a Java EE packaged as war file stored in an `AWS s3` bucket. I will like to mount the folder containing the `.war` file as a point in my docker container. I have managed to do this on my local machine. Below is an example of a JBoss wildfly deployments. How can I use `s3` for this ?

`docker container run -d —name Application -p 8080:8080 -v `pwd` /Application.war: /opt/jboss/wildfly/standalone/deployments/Application.war jboss/wildlfly`

# Answer
> 3 votes
No you can't.

S3 is an object storage, accessed over HTTP or REST for example. Just as you can't mount an HTTP address as a directory you can't mount a S3 bucket as a directory.

Having said that there are some workarounds that expose S3 as a filesystem - e.g. 's3fs' project. How reliable and stable they are I don't know.

# Answer
> 4 votes
Yes , you can ( and in swarm mode you should )

# Answer
> 2 votes
Actually, you can use Fuse (eluded to by the answer above).

> S3FS-FUSE: This is a free, open-source FUSE plugin and an easy-to-use utility which supports major Linux distributions & MacOS. S3FS also takes care of caching files locally to improve performance. This plugin simply shows the Amazon S3 bucket as a drive on your system.

https://tecadmin.net/mount-s3-bucket-centosrhel-ubuntu-using-s3fs/

I haven't used it in AWS yet, though I'll be trying it soon. There is a similar solution for Azure blob storage and it worked well, so I'm optimistic.

# Answer
> 0 votes
Yes, you can. Use Storage Gateway service. It will give you a NFS endpoint. Mount that using kubernetes volumn. It is possible. I have already achieved this.

---
Tags: docker, amazon-web-services, deployment, amazon-s3, java
---


# Question
Title: Can I move SSL certificate files from one server to another for the same domain?
I have a website running at https://domain.com and IP a.a.a.a, with an SSL cert issued by GoDaddy. The server is deployed with Nginx. Everything is working fine as it is.

However I'm trying to deploy the same website with Docker in a new server with IP b.b.b.b, so I did the following:

1. Pull nginx image from Docker
2. **Copy the domain.com.chained.crt and domain.com.key files from server a.a.a.a to server b.b.b.b**
3. In the Docker file, I copy the cert files to the image
4. When I run the container and check nginx with `nginx -t`, it seems to be working fine.
5. Ports 443 and 80 are open for external requests
6. I check that the website is running by accessing to b.b.b.b:80 from an external client
7. Configure the DNS to resolve to b.b.b.b instead of a.a.a.a
8. Check that http://domain.com is working

Up to that point everything is working fine. But when I try to access https://domain.com I get the following errors:

* With firefox: ERR\_SSL\_PROTOCOL\_ERROR
* With chrome: SSL\_ERROR\_RX\_RECORD\_TOO\_LONG
* The site https://www.sslshopper.com/ssl-checker.html tells me this: `No SSL certificates were found on domain.com. Make sure that the name resolves to the correct server and that the SSL port (default is 443) is open on your server's firewall.`

The Nginx error logs don't tell me much, although I have them in debug mode.

My main question is: Can I copy the cert files from one server to another or do I have to generate them again?

Edit: This is the docker-compose.yml

```
sevices:
  nginx:
    build: ./nginx
    image: nginx
    ports:
      - "80:80"
      - "443:443"
  redis:
    image: redis
    ports:
      - "6379:6379"
  mongo:
    image: mongo
    ports:
      - "27017:27017"
    volumes:
      - /var/mongodata:/data/db

```

Dockerfile

```
FROM custom:latest

COPY nginx.conf /etc/nginx/nginx.conf
COPY /ssl/domain.com.key /etc/nginx/ssl/domain.com.key
COPY /ssl/domain.com.chained.crt /etc/nginx/ssl/domain.com.chained.crt

RUN apt-get -y install nodejs libssl1.0-dev  nodejs-dev node-gyp npm
[...]
CMD ["nginx", "-g", "daemon off;"]

```

nginx.conf

```
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log debug;

    ##
    # Gzip Settings
    ##

    gzip on;

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    #include /etc/nginx/sites-enabled/*;

    server {
        listen 80;
        listen [::]:80;
        listen 443;

        server_name www.domain.com;
        ssl_certificate /etc/nginx/ssl/domain.com.chained.crt;
        ssl_certificate_key /etc/nginx/ssl/domain.com.key;

        location / {
            root /domain.com/;
            try_files $uri$args $uri$args/ /index.html;
        }
    }
}

```

# Answer
> 1 votes
Your listen 443 need to have ssl parameter to tell Nginx that all connections accepted on this port should work in SSL mode.

See example at https://nginx.org/en/docs/http/configuring\_https\_servers.html#single\_http\_https\_server

Shown here for convenience:

```
server {
    listen              80;
    listen              443 ssl;
    server_name         www.example.com;
    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
    ...
}

```

---
Tags: docker, nginx, ssl
---


# Question
Title: Can I run multiple pipelines in a single GitLab repo using GitLab CI/CD?
I know that I can't have multiple gitlab-ci.yml files in one repo, but it still seems fairly limited. Say for example I have one set of tests I want to run whenever a change is pushed or on PRs, and another set I want to run every 24 hours. Is there a way to do that, or do I only get one set of tests I have to use whenever I want to run CI?

# Answer
> 14 votes
Yes, you can use the rules syntax. You can use this in combination with regex for commit message, ci\_pipeline\_source or any other available CI variables.

```

job1:
  script:
    - do something on schedule only
  rules:
    - if: '"$CI_PIPELINE_SOURCE" == "schedule"'
      when: always

job2:
  script:
    - runs on Merge request pipeline
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: always
    when: never

job2:
  script:
    - runs on changes to anything in src directory or Dockerfile
  rules:
    - changes:
        - src/*
        - Dockerfile

```

Note you can also include multiple CI templates in your gitlab-ci.yml. Additonally, you can include a CI template with "hidden" job templates that you can reference with extends:

```
# Include ci files
include:
 - local: '/templates/.scheduled-job-template.yml' # CI template with hidden job (.scheduled_job) that runs on schedule
 - local: '/templates/.lint-and-validate.yml' # contains jobs for linting and validating project

job1:
  extends:
    - .scheduled_job
  rules:
    - if: '"$CI_PIPELINE_SOURCE" == "schedule"'
      when: always

job2:
  script:
    - runs on Merge request pipeline
  rules:
    - if: $CI_MERGE_REQUEST_ID
      when: always
    when: never

```

In doing this you can compose the jobs/pipelines you want in its own yml file and then define the jobs using those templates in the gitlab-ci.yml, which will help keep things maintainable and clear if you are running numerous different pipeline/pipeline configurations from the same project.

# Answer
> 0 votes
I guess you can do it via `rules` keyword. It has multiple condition with environment variables or branch name or schedules. If you add detail about you want to do, i try to

Gitlab CI Rules

---
Tags: continuous-integration, gitlab, continuous-deployment, gitlab-ci-runner
---


# Question
Title: Howto run test on test computer instead of build computer, using gitlab
I'm learning gitlab and am asking for advice / best practice here.

I want to install a program to a different machine than the build computer, and run some automatic tests on that machine. How is this best done?

I think this can be accomplished with the "multi project pipeline" feature. Is this the simplest/best way?

Here is my plan:

I could have one (shell) runner and project for my build machine, and a different runner and project for my test machine. The two would be connected using "multi project pipeline" feature. The artifacts from the build pipeline would be installed on the test machine and then system tests would run on the test machine.

Is this the best way to solve this? Or is there a simpler/better way?

Edit: The test machine has special hardware/enviornment necessary for the program to run. That's why program needs to be installed there.

# Answer
> 1 votes
Answering my own question here. "Multi project pipeline" is not necessary here. You simply have a single project and mark jobs with different "tags". You can then register runners for these different tags, on different machines.

(Artifacts are transferred from one job to the next the same, regardless if the runners are run on the same machine or on different ones)

https://docs.gitlab.com/ee/ci/yaml/README.html#tags

---
Tags: gitlab, gitlab-ci-runner
---


# Question
Title: How can we prepare GitLab runners using Ansible deploys
**Given**

We run an in-house `GitLab` server, with many `projects` (aka "`repositories`")

We provision all servers using `Ansible` (and deploy projects using `pip`)

We deploy to

* dev.project.example.com
* test.project.example..com
* beta.project.example..com
* (and eventually to) www.project.example..com

**When**

We add `.gitlab-ci-.yml` to all `project`s' `repository` roots

We want to use `dev.project.example.com` as a runner for that `GitLab project`

**Then**

What Ansible playbooks could we write to provision `dev.project.example.com` as a `GitLab Runner` for that `project`?

# Answer
> 1 votes
A gitlab runner is a process that f.e. tests, compiles your project, pushes the artefact to you artefact store etc.

A Gitlab runner can be tagged inside Gitlab or via config.toml - so - you can assign runners via tags to Gitlab projects (shared).

Gitlab runner are not designed to run an application 24x7. So - you assign a project to a runner (or a tag or all) to build you application). If you want to deploy the project, use the K8S deployment inside Gitlab (that must be connected to a specific Kubernetes environment based on you Git-branches etc). Or (just an example) run an AWX task that is able to push your new artefact via the artefact storage (docker registry). Also you could just call a SSH remote command on a script (via Gitlab runner) to start a deployment - but don't use the runner to "host" your environment. They will stop (per default after 1h) without a return code.

---
Tags: ansible, gitlab, gitlab-ci-runner
---


# Question
Title: Add stages to Jenkins declarative pipeline through shared library
Is there a way to write a stage in a Jenkins shared library so that it can be added to declarative pipelines?

# Background

For many projects, I need to run tests on multiple different servers. My solution is to create a bunch of parallel stages, one for each of the servers that I want to run on. I've gotten to this pipeline (running on 2 servers as an example):

```
pipeline {
    agent any
    stages {
        stage('Test') {
            parallel {
                stage('San Jose') {
                    agent {
                        label "test && san-jose"
                    }
                    steps {
                        sh 'run-tests'
                    }
                }
                stage('Dallas') {
                    agent {
                        label 'test dallas'
                    }
                    steps {
                        sh 'run-tests'
                    }
                }
            }
        }
    }
}

```

Which is great, but I'd really like to keep my code DRY and not have to copy and paste this Test stage to every project I have (especially since this has to run on about 10 servers, with only the label changing each time).

I could put the whole pipeline into my shared libary (like Jenkins's example in the documentation), but then I can't customize the other stages (for example, adding a release stage).

What I'd really like to do is this:

```
pipeline {
    agent any
    stages {
        runOnServers {
            sh 'run-tests'
        }
        stage('Release') {
            echo 'release'
        }
    }
}

```

# Question

Is there a way I can do this?

# Answer
> 1 votes
Yes, but (to the best of my knowledge) you will have to use Scripted Pipeline within the shared library. This means that the closure that you will pass to the shared library (in the below example, the closure is `sh 'run-tests'`) will also have to be Scripted.

`Jenkinsfile`:

```
pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                runOnServers {
                    sh 'run-tests'
                }
            }
        }
        stage('Release') {
            echo 'release'
        }
    }
}

```

In your shared library, a file named `vars/runOnServers.groovy`:

```
def call(Closure closure) {
  parallel({
    SanJose: {
      node("test && san-jose") {
        stage('SanJose') {
          closure()
        }
      }
    },
    Dallas: {
      node('test dallas') {
        stage('Dallas') {
          closure()
        }
      }
    }
  }
}

```

---
Tags: jenkins, jenkins-pipeline
---


# Question
Title: Tool to produce nice output about desired vs. current state
I've been trying to stick to the "infrastructure as code" principle as much as possible in my work.

But after the devops project got more complicated I started loosing the centralized perspective because the scope of used technologies and complexity are very rich: terraform, terraformer, terragrunt, pscore, bash, Azure CLI, Azure DevOps CLI, AzureAD module, msbuild, Java, various REST API calls...

So I started writting scripts and code that calculate "desired vs current" state just for validation and overview, if everything is in the right state. Most of the time this information is everything I need, I don't need to "go to the desired state" because sometimes that actually means manual intervention (sometimes even from someone else).

The output of these scripts is simple, currently they write into stdout something like this:

```
Name of thing         Desired state      Current state     Result
----------------------------------------------------------------------
THING A               This               That              NOT GOOD
THING B               This               This              GOOD
THING C               This               ?                 Timeout after 5 minutes
...

Result:
- 2 things needs attention

```

My question is if there is some tool or standard targeted at this specific use case?

* I have scripts, I could call them "diff calculators" that can output whether some "thing" or "subthing of thing" is in desired state and what is the current state
* The tool produces nice table based UI output

# Answer
> 1 votes
I found Pester which is just a powershell unit testing that can save Nunit XML results which can be published inside the pipeline.

It's not "desired"/"current" state I had hoped for but it can in the end provide a nice overview of all the "things" whose states I need to observe.

# Answer
> 0 votes
This seems like the sort of thing that configuration management tools like ansible are intended to solve. You can run ansible in check mode to see what it would do.

---
Tags: configuration-management
---


# Question
Title: Command returns 0.0.0.0 for IP but only for leader
I have a 3 node docker swarm cluster and I am trying to get the IPs of each one via `docker node inspect node-1 --format '{{ .Status.Addr }}'` but I am having an issue where when the node I am trying for (example `node-1` from above), that I get back `0.0.0.0`. This only happens on the leader node, the others work just fine.

What is happening in this case? Also, how can I use docker commands to get the IP of all the nodes when checking with their hostnames or `docker node ls`?

# Answer
> 1 votes
I ended up using {{.ManagerStatus.Addr}} and stripping the port number from the results with sed.

```
for NODE in $(docker  node ls -f 'role=manager' --format '{{.Hostname}}'); do
  docker node inspect --format '{{.ManagerStatus.Addr}}' ${NODE} | sed 's/:2377//'
done

```

# Answer
> 0 votes
Related bug that i have found

> Status.Addr uses the gRPC library to determine the address of a given node as viewed by the manager. This means, for example, if a worker node was behind a proxy, it would give the proxy's address as Status.Addr, even if the worker itself didn't "know" it was behind a proxy.
>
> For ManagerStatus.Addr, the address given is the advertise address of the manager, as may have been set with --advertise-addr when doing init or join. The advertise address must be correct, because that's the address that the other managers know to connect to this manager at.

https://github.com/moby/moby/issues/35437

---
Tags: docker, docker-swarm
---


title: Ansible - Azure resource referencing

text:
# Question
Title: Ansible - Azure resource referencing
My aim is to have my vnet and subnet in a seperate resource group from the other parts of my infrastructure i.e Virtual Machines.

I have a short playbook that creates the resource group for my network (vnet & subnet), which works fine. I can build a VM via the portal and all is well.

My other playbook creates a resource group, creates a vmnic and VM. This playbook references the vnet and subnet created in the other resource group.

I'm encountering an error (see below) when referencing the resources in the network resource group I created. I found a previous post that has helped by suggesting the use of the "set\_fact" module.

I've tried different ways of entering set\_fact key values (full resource path / part resource path), but I keep getting an error. I suspect it maybe due to interpolation? Note the double "//" in the error message.

Could anyone provide some guidance on where I'm going wrong, please?

Error message:

> fatal: \[localhost\]: FAILED! =\> {"changed": false, "msg": "Error creating or updating network interface test-vm-vnic1 - Azure Error: InvalidRequestFormat\nMessage: Cannot parse the request.\nException Details:\n\tError Code: InvalidJsonReferenceFormat\n\tMessage: Reference Id /subscriptions/REMOVED-SUB-ID/resourceGroups/test-rg/providers/Microsoft.Network/virtualNetworks//providers/Microsoft.Network/virtualNetworks/vnet-ansible-test/subnets//subnets/snet-ansible-test is not formatted correctly. The Id is expected to reference resources of type virtualNetworks/subnets. Path properties.ipConfigurations\[0\].properties.subnet."}

Part of playbook:

```
  tasks:
   - set_fact:
       vnet_rg_id: "/subscriptions/REMOVED-SUB-ID/resourceGroups/rg-ansible-test"
       vnet_id: "/providers/Microsoft.Network/virtualNetworks/vnet-ansible-test"
       snet_id: "/subnets/snet-ansible-test"

   - name: Create resource group
     azure_rm_resourcegroup:
       name: "{{ rg }}" # this is var declared earlier in the playbook
       location: "{{ location }}" # this is var declared earlier in the playbook

   - name: Create virtual network inteface cards for VM
     azure_rm_networkinterface:
       resource_group: "{{ rg }}" # this is var declared earlier in the playbook
       name: "{{ nic_name }}" # this is var declared earlier in the playbook
       virtual_network: "{{ vnet_id }}"
       subnet: "{{ snet_id }}"
       location: "{{ location }}" # this is var declared earlier in the playbook

```

# Answer
> 1 votes
With a bit trial and error I was able to work out the values for my "vnet\_id" and "snet\_id" variables.

I found using the full ID for the virtual network and not having a "/" before the subnet variable (snet\_id) value fixed my problem.

At the moment I don't fully understand how Ansible/Azure puts it all together, but this has given me enough information to start to understand.

If anyone could point me to some documentation that explains the construction/interpolation of the variables it would be helpful.

```
  tasks:
   - set_fact:
       vnet_rg_id: "/subscriptions/REVMOVED-SUB-ID/resourceGroups/rg-ansible-test"
       vnet_id: "/subscriptions/REVMOVED-SUB-ID/resourceGroups/rg-ansible-test/providers/Microsoft.Network/virtualNetworks/vnet-ansible-test"
       snet_id: "snet-ansible-test"

   - name: Create resource group
     azure_rm_resourcegroup:
       name: "{{ rg }}" # declared earlier in the playbook
       location: "{{ location }}" # declared earlier in the playbook

   - name: Create virtual network inteface cards for VM
     azure_rm_networkinterface:
       resource_group: "{{ rg }}" # declared earlier in the playbook
       name: "{{ nic_name }}" # declared earlier in the playbook
       virtual_network: "{{ vnet_id }}"
       subnet: "{{ snet_id }}"
       location: "{{ location }}" # declared earlier in the playbook

```

---
Tags: ansible, azure-devops, azure
---


# Question
Title: How do I enable Google App Engine API with Terraform?
I'm attempting to enable the AppEngine service via Terraform but I'm getting an error:

```
Error: Error creating App Engine application: googleapi: Error 403: App Engine Admin API has not been used in project <redacted> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/appengine.googleapis.com/overview?project=<redacted> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., accessNotConfigured

```

As far as I know all that should be required to enable the service/API is:

```
// Enable AppEngine API - required to automagically create datastore
resource "google_project_service" "appengine_api" {
  project = var.project
  service = "appengine.googleapis.com"

  disable_dependent_services = true
}

```

# Answer
The terraform service account was located in a separate project and the API needed to be enabled for appengine in the account the Terraform service account runs in even though it was creating a resource in an another project.
> 1 votes

---
Tags: terraform, google-cloud-platform
---


# Question
Title: Jenkins API call (or Groovy builtin) that returns list of all currently running builds of jobs
There's plenty of questions asking how to return a list of all jobs on your Jenkins instance, or even to get a list of which jobs are currently running, but I have a more specific use-case.

I need to see if a single job is already running. As in, return one value if there is 1 builds of the job running, and a different value if 2 or more builds are running.

The use case here is that we've automated our image creation to build after successful unit tests. It's set to build a maximum of one image every seven hours, by checking the build time of the last image and cancelling the build if it's been less than 7hrs. This works perfectly for most cases. However, these images take ~20min to build. If it's been over 7 hours and **two** unit tests finish within less than 20min of each other, the second build doesn't see the first creating, and continues building. We're getting two functionally identical images made once every 7hrs, only minutes apart. I'd like to check the status of the controller job to know if it's already running, so that the second build can know to cancel.

I've tried curl-ing the following API, but it turns out it doesn't register individual builds, just that the job is running in general, which is useless in this case as it self-triggers since it checking means it's already running; there's no difference between a single build and multiple builds.

```
http://JENKINS_URL/api/xml?tree=jobs[name,url,color]&xpath=/hudson/job[ends-with(color/text(),%22_anime%22)]&wrapper=jobs

```

TL;DR: Is there a different call I can make that will return some list/file/content that indicates that multiple builds of the same job are currently running?

# Answer
> 7 votes
Turns out you can hit the following URL to get an XML output of all currently running builds, including their build numbers.

```
http://jenkinsURL/computer/api/xml?tree=computer[executors[currentExecutable[url]],oneOffExecutors[currentExecutable[url]]]&xpath=//url&wrapper=builds

```

I `grep`ed it for a count and used that for my calculations.

# Answer
> 0 votes
I used the Groovy script console to obtain it this way:

```
def executables = Jenkins.instance.computers.collect {c -> c.executors}.
def runs = Jenkins.instance.computers.collect {c -> c.executors}.
   flatten().
  findAll { executor -> executor.isBusy() }.
  collect { executor -> executor.getCurrentExecutable() }.
    collect { executable -> "${executable.displayName}: ${executable.number}" }

```

or if you want the `Build` class, this:

```
Jenkins.instance.computers.collect {c -> c.executors}.
  flatten().
  findAll { executor -> executor.isBusy() }.
  collect { executor ->
    def u = executor.currentExecutable.url
    def n = executor.currentExecutable.number
    def job_qual_name = u.split('/')[0..-2].findAll { it != 'job' }.join('/')
    def job = Jenkins.instance.getItemByFullName(job_qual_name, Job.class)
    job.getBuildByNumber(build.number)
  }

```

It's pretty painful that Jenkins doesn't provide something as simple as this with a clear, high-level API.

It's extra ugly that the paths used by the folders plugin jobs don't work with `Jenkins.getItemByFullName()` without munging. Ick. Also that `Jenkins.getItemByFullName()` doesn't seem to support getting a `Build`.

You won't want to put this in Pipeline code. Instead put it in your script library so it isn't subject to method authorization issues, and only returns the final results.

---
Tags: jenkins, jenkins-pipeline
---


# Question
Title: Cannot resolve services with service name inside a kubernetes pod
I cannot access a pod from another pod with its service name. Getting error as

> cannot resolve host `svcname`

When i try to view the information of /etc/resolv.conf, i do see ec2.internal as searches and ndots as 1. What does this means and how do i solve this to access a pod from another pod with the service name.

# Answer
> 0 votes
Your `/etc/resolve.conf` should include `search <currentnamespace>.svc.cluster.local svc.cluster.local cluster.local` to discover hostnames that aren't FQDN.

As an example, this is the content of my pod's `/etc/resolve.conf`:

```
nameserver 10.100.0.10
search staging.svc.cluster.local svc.cluster.local cluster.local eu-west-1.compute.internal

```

With this configuration, DNS resolution works like this:

1. Is the hostname a fully qualified domain name (FQDN)? (In other words, does it end with a dot, like "google.com.")
2. If it's an FQDN, query nameserver (`10.100.0.10`) for the hostname.
3. If it's not an FQDN, then append the **1st** element of the config **search** to the hostname. `svcname` -\> `svcname.staging.svc.cluster.local` and query the nameserver.
4. If no results found, try to append the **2nd** element of the config **search** to the hostname and query the nameserver.
5. ...

You want to resolve the hostname `svcname` but its FQDN is `svcname.<namespace>.svc.cluster.local.` and you need that **search** configuration to convert it to FQDN.

---
Tags: docker, kubernetes, deployment, networking
---


# Question
Title: Azure Dev Ops delete releases not going to production
I have several release pipelines that build to a UAT environment on a continuous integration. They await deployment to Production on an approval. A new release cancels the previous Production deployment.

Is there a way I can set retention so these deployments that will never be pushed to Production go away? I'd like to still retain the previous production deployments for roll-back purposes.

# Answer
The interface is a little vague, but if I go to Pipeline \> Edit then click "Retention" at the top, I can set values there that work.

Note: The updates/clean up only happen at... some time??? I'm not 100% sure when, but builds aren't immediately cleaned up if the policy changes.

The Days to Retain a Release box and the Minimum Releases to Keep influence each other, and the system seems to keep the build if either meets the criteria.

So, I set the UAT stage to 1 day / 1 release, so it always keeps AT LEAST 1 build, and always keeps all builds for AT LEAST 1 day.

I set the Prod stage to 3 day / 3 release, so it always keeps AT LEAST 3 builds, and always keeps all builds for AT LEAST 3 days.

Now it's much cleaner:

I hope this helps someone in the future! :)
> 2 votes

---
Tags: azure-devops, azure-pipelines, release-management
---


# Question
Title: How can I add a when clause for a specific upstream trigger in a Jenkins declarative pipeline?
I have a job defined as a declarative pipeline that gets triggered by a number of different upstream jobs. Depending on which upstream job triggered my job, I don't necessarily need to run all of the stages in my pipeline, so I want to specify a list of triggers for each stage.

I was hoping to use a `when` clause and `triggeredBy` conditions to determine when each stage runs, but the documentation isn't very detailed:

> triggeredBy
>
> Execute the stage when the current build has been triggered by the param given. For example:
>
> when { triggeredBy 'SCMTrigger' }
>
> when { triggeredBy 'TimerTrigger' }
>
> when { triggeredBy 'UpstreamCause' }
>
> when { triggeredBy cause: "UserIdCause", detail: "vlinde" }

Is there an `'UpstreamCause'` equivalent to the example for `'UserIdCause'` that would allow me to specify *which* upstream cause should trigger a specific stage? If so, what is the exact syntax? Basically I want to do something like:

```
when {
    anyOf {
        triggeredBy cause: 'UpstreamCause', detail: 'Job A'
        triggeredBy cause: 'UpstreamCause', detail: 'Job C'
    }
}

```

I'm also open to other approaches for accomplishing this.

# Answer
> Is there an 'UpstreamCause' equivalent to the example for 'UserIdCause' that would allow me to specify which upstream cause should trigger a specific stage?

Unfortunately, not in native Declarative syntax.

As you can see from the source code, UserIdCause is special-cased, but no other cause is:

```
    static boolean shouldRunBeAllowed(Cause causeClass, String cause, String detail){
        if( causeClass instanceof Cause.UserIdCause && Cause.UserIdCause.simpleName == cause){
            return detail == null || causeClass.userId == detail
        }else {
            return causeClass.class.simpleName.matches("(?i)\\.*${cause}.*")
        }
    }

```

So if you want to trigger conditionally based on which job triggered the build, you'll need to use Scripted syntax. For instance (I haven't tested this so no guarantees it will work without debugging):

```
script {
  def myJob = 'put-your-job-name-here'
  def causes = currentBuild.rawBuild.getCauses()
  def triggeredByMyJob = causes.any { cause->
    cause.class.toString().contains("UpstreamCause")) && cause.upstreamProject == myJob
  }

  if (triggeredByMyJob) {
    // put steps to execute when triggered by your job here
  } else {
    // put steps to execute when NOT triggered by your job here
  }
}

```

However, there's potentially a much easier way, although it's not strictly what you asked for: Give your downstream job a boolean parameter, for the sake of example let's call it `runMyStages`, and use a `when` clause to conditionally execute stages based on whether `runMyStages` is true or false. Then in your upstream jobs, you can set that parameter in your build step: `build(job: 'downstream-job-name', parameters: [booleanParam('runMyStages', false)])`.
> 1 votes

---
Tags: jenkins-pipeline, jenkinsfile
---