# Question
Title: Is there a system which automates everything (OS release, and above) to host websites on?
This is not really a DevOps question but more of a System Automation question (which DevOps covers only a part of, by popular opinion, so I hope it's okay).

I feel like some **5 USD IaaS VPS** with Ansible could give me the peace of mind of technical stability for say 15 years on a `debian:stable` system, but the `debian:stable` release itself will get old and vulnerable with the years.

Everything above the OS will generally not get old because by Ansible (given a correctly orchestrated playbook) will continuously update and upgrade it.

Yet the fact that the OS will indeed get old can't get out of my mind. Transferring websites from one IaaS to another even once per 4 or 8 or 12 or 16 years is not something I want to do in principle. One could say, well, you can't eat the cake and keep it whole.

I thought of using PaaS but PaaS solutions wouldn't necessarily bring me that peace of mind as well because my data might be "thrown" in some server environment with an old OS (could be old as 20 or 25 years) without me even knowing that and not all PaaS companies guarantee streamed OS release\_upgrade.

So, I desire some **full system automation** solution. Is there even such a thing which is usually stable and countable in earth in 2018? I ask this totally seriously, maybe I need to be less stressed about this, but maybe such technical solution (which isn't SaaS of course) exist and might suit my needs?

I just want to build my websites (usually Drupal) on the most automated, most upgraded system (OS and above) possible, in the budget of 5-30 USDs.

**Note:** I never provided hosting services and doesn't provide them now either - usually my websites are personal websites that only I myself manage.

# Answer
**TL;DR** Pick software that focuses on long-term support. Use containers so that you can separate the runtime you need for your app from the security patching of the underlying infrastructure.

**Long Answer:**

I used to run some old PHP sites running popular content management systems. The plugins would fall out of support such that I could not upgrade the content management system else the plug-ins would break. So then I would stick on the latest major version things worked on and hope that no new security holes would come. I then ran monitoring software and manually fought off any scripts that got injected through security holes. Then the operating systems that support that old version of PHP I needed would fall out of support. I then couldn't easily move the hoster to take better use of cheaper deals or high availability. So I would find ports of the legacy PHP I needed onto the oldest version of an OS that hosters would support. Total nightmare.

What this demonstrated to me was that some software isn't built to last more than three or four years. Millions of sites would have had the same issues as me but tens of millions more wouldn't have as they would have been shutdown else rebuilt from scratch on newer software. So the first lesson here is that if you think you need to build for the long term you need to figure out if your using software that cares about long-term support and has a published lifetime.

The world has moved on and the PHP7 world is taking a new approach to having a predictable software release cycle and lifetime (still quite short I might add, but more predictable). You should not just assume nor expect any distro or any community to be with you for the long haul unless that is exactly what they said they are trying to do. And if that is what they are trying to do then they won't do other things that are in conflict with that such as run hot new framework features that are trending on stackoverflow.

These days I happen to be helping a company that is running Node.js 8 and PHP 7.x on RHEL7 containers on kubernetes on AWS. They get long-term support of security updates with a published lifetime. I have automated the detection of new security patches to the PHP and Node.js containers. A weekly job checks the upstream container registry and if there is a new security patched version it is announce to a team chat room along with the command to patch the containers in the test environment. A commercial subscription to those patches is included in my managed kubernetes hosting costs. Yet as its all opensource I could fall back to using Centos7 if I wanted to cut some costs.

As I am running containers I don't care whatsoever what patches are being applied to the IaaS nor the version of kubernetes I am hosted on. I am on openshift.com and they have upgraded to 3.11 through security fixes without telling me. They just patch the worker VMs and bounce them and kubernetes starts my containers on other VMs. I am insulated from all the security patching of the cluster I am on because I am running containers that have inside them the minimal operating environment needed to run my app. That only changes when I choose to upgrade to a new container and with long-term security patch support; I don't need to do that for years. I understand that the Kubernetes hosts that run my containers themselves run a very stripped down distro to maximise their security and customer density. It doesn't matter to me. The idea of an IaaS stack of Linux that goes out of support seems a totally alien concept to me now even through I lived many years with that problem.

It also means that I am free to move to any cloud or hosting provider that can run my containers. It doesn't have to be kubernetes it could be Docker Swarm or whatever. All that I am betting on is that this better way of working with containers will be supported in the long term. I think that's a good bet. A container image is only a json file naming a load of tar files that are the layers in the image. Yes; its just tar files and json. As long as the container host can load my files from a tar and attach a TCP/IP stack my stuff will run. I am pretty confident that this approach will have a very, very long shelf life.

I don't think that anyone that is trying to run apps should start out on IaaS today. PaaS is one solution but tends to have very strong vendor lock-in. CaaS is the new sweet spot. Choice. Stability. Control. Portability. If it runs under docker on your laptop just push it to the container orchestrator you are renting space on. My containers only have one thing in them. The hosts that they run on only does secure container hosting.
> 5 votes

# Answer
> So, I desire some full system automation solution. Is there even such a thing which is usually stable and countable in earth in 2018? I ask this totally seriously, maybe I need to be less stressed about this, but maybe such technical solution (which isn't SaaS of course) exist and might suit my needs?

Yes, such a thing exists and is possible. You mention it yourself: *full automation* gives you exactly what you need, i.e. a system that evolves continuously with whatever the next 15 or 30 years throw up at us.

The only step that's missing for you right now is to not start your automation on the Ansible level, but dig deeper. I.e., you will want to automate the installation of the OS (or the choice of a base image, however your XaaS provider calls it), and the creation of your compute ressources (VMs, Docker or whatever you have), the networking, the quotas (RAM, CPU, storage etc.) and so on. Also, importantly, a version upgrade needs to be automated (for example as an A/B or blue-green deployment).

To *automate* that stuff means that you need to *configure* all those bits and pieces. Whatever you have configured (presumably in some text files) you can more or less easily run in alternative testing/development environments. Thus, you can then (automatically) test new releases of whatever part that changes to your heart's content. This, then, means that whenever any part - the OS being one of them - changes, you can immediately go along with that change.

By following *every* upgrade of your underlying stuff relentlessly, you make sure that you never get old.

Like your source code, all this configuration needs to go in your revision control system as well, so you have freedom to play with it, try new stuff, and maybe revert if it doesn't work.

To give you concrete examples, just as a starting point, you can check out Vagrant or Terraform (google "vagrant alternatives" for more). Sometimes, the choice of your XaaS provider guides you to a specific tool; or you might pick a tool and then look for a fitting provider. But that would be a topic for a different question.
> 0 votes

---
Tags: ansible, linux, automation, infrastructure, platform-as-a-service
---


# Question
Title: How to run multiple containers with port expose
I have 2 images on my docker toolbox, for jenkins and for artifactory. I can use the command "run" for each to create a running container, jenkins on port 8080 and artifactory on oprt 8081, using the -p flag. When I use the command "docker ps" I can see both containers.

My problem: I can only open one application at a time, for example: Open jenkins on URL 192.168.99.100:8080 (docker toolbox use this IP by default), then, open artifactory on URL 192.168.99.100:8081, the page "jFrog Artifactory is getting ready to work..." will be displayed and then the connection to the artifactory will be lost. But if I stop the jenkins container I could run the artifactory application properly.

I read that docker compose can help to run multiple containers but I didn't understand if it can help my case too.

Any help?

Notes:

* My "docker ps" output (plus another command for better display)
* I found out about nginx that can be used as reverse proxy but I managed to set only the Jenkins to work, the artifactory does not work. Seems like I am not configuring the .conf file properly. Is it possible to run artifactory via nginx without configuring SSL? Most of the examples I found had SSL in the .conf file.

# Answer
> 1 votes
My problem was that the docker-machine didn't have enough memory to run both services at the same time.

Using those commands fixed it:

```
docker-machine stop
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm default --cpus 2
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm default --memory 4096
docker-machine start

```

(The path to the VBoxManage.exe maybe be different for other users and it can be change to just "VBoxManage" if adding it to the environment paths)

# Answer
> 0 votes
Most probably the problem with artifactory container is not really related to the ports, check if the docker ps always shows the same container id, if not its probably dying and coming back up, when you start the containers, do you use anything in -v? Have you checked the docker logs of the artifactory container when jenkins is down? Do a docker logs xxxx using the ID of the artifactory container that dies to see what happened.

---
Tags: docker, jenkins, artifactory
---


title: SRE Role at Google

text:
# Question
Title: SRE Role at Google
I want to work at Google some day.

* What are the tools an SRE should really know before applying at Google?
* What are the things to expect on an SRE interview?
* System Design knowledge is required?
* Do I really need to know the algorithms and implementations?

# Answer
> 4 votes
I think there are two ways to go about this. You can either go deep in Systems Engineering or the reliability aspects of Software Engineering.

I'm a Systems Engineer myself. I think I got the job because I knew quite a bit about Linux internals (read Linux Kernel Development by Robert Love and no you don't need to be a kernel developer) AND Non-Abstract Large System Design (aka NALSD, read https://landing.google.com/sre/workbook/chapters/non-abstract-design/). I had experience running ISPs (DNS, Email, etc) and automating myself out of many SysAdmin tasks as well. It's also helped that I had a track record of contributing to open source projects.

On the Software Engineering side, NALSD comes up again. I'd also study SREcon talks about software projects developed by SREs while at the job, e.g libraries to make it harder for human mistakes to surface as production incidents, writing software for all kinds of automation and tooling, etc.

I'd recommend reading all SRE related books as well then trying to practice some of it in your lab at home or at work even. http://www.google.com/sre has 2 for free online. There are probably 3-5 more out there as we speak.

---
Tags: sre
---


# Question
Title: error validating data: ValidationError(Deployment): unknown field "spec" in
I know that `yml` files are temperamental and I still struggle to figure it out. Can anyone help out here to understand what is it about my `client-deployment.yml` file that makes Kubernetes want to issue the above error?

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: web
  template:
    metadata:
      labels:
        component: web
    spec:
      containers:
        - name: client
          image: ldco2016/multi-client:v1.2
          ports:
            - containerPort: 3000

```

I got the above error running `kubectl apply -f k8s`

`k8s` being one of the folders in the project with the `yml` configuration files.

# Answer
> 3 votes
Sure enough, everything and including the last `spec:` needed to be tabbed to the left once:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: client-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      component: web
  template:
    metadata:
      labels:
        component: web
    spec:
      containers:
        - name: client
          image: ldco2016/multi-client
          ports:
            - containerPort: 3000

```

Unfortunately, you can't tell the difference with how `yaml` is formatted when pasted here, so it would not have been an easy catch, but if you would be looking at the original file configuration you would have noticed it like I did when I looked a third time.

---
Tags: kubernetes, yaml
---


title: Docker Hub to VPS

text:
# Question
Title: Docker Hub to VPS
Note: I am a .NET Developer that is dabbling in DevOps. I want to learn.

**Current Situation:**

I have my .NET Core project dockerised. It sits on GitHub and is Open Source. Using Travis CI; as soon as I check some code into the GitHub repository, Travis CI builds a fresh docker image and pushes it to Docker Hub with two tags `$BUILD_NUMBER` and `latest`.

I have an Ubuntu VPS where I plan on running my dockerised applications.

**Question:**

Once the images are uploaded to Docker Hub (i.e. travis has finished the steps inside .travis.yml), how can I get those latest images to automatically run on my VPS?

This is where I am stuck.

I understand that once the docker containers are running on my VPS, I have to set up nginx as proxy ...etc, so I'm OK with that. I am just stuck on getting the latest docker image running on my VPS.

# Answer
> 1 votes
One typical solution is to add a deployment task to your Travis CI pipeline. This task may, for example, run a command on your Ubuntu VPS to pull and run the `:latest` image. You could use any number of techniques to accomplish this: a CM tool like Ansible or Chef, a Bash script or simply SSH.

Travis CI documentation has some information on deployment providers: https://docs.travis-ci.com/user/deployment/

---
Tags: docker, docker-compose, travis-ci
---


# Question
Title: How is Continuous Integration different from using git to integrate external code?
I have a conceptual doubt about CI using Jenkins. I know Jenkins can help me to integrate all code built by developers.

So the question is: How is this not already resolved with Github (or any other git tool)?

I can run `git stash`, `git pull origin master`, and/or `git stash apply` to integrate other code with my code.

So I think I am misunderstanding something about continuous integration. Can you clear my mind?

# Answer
> 1 votes
Merging code changes is definitely handled by Git and its tools. But Continuous Integration also includes **testing** and **building** the software. The development teams are provided with constant feedback on the status of their branch(es) and whether they are failing tests, builds, etc.

Jenkins provides the tools to enable this feedback. By creating a CI "pipeline" in Jenkins the developer gain much better insight into the build, beyond what simple Git merges and stashes provide.

# Answer
> 0 votes
Continuous Integration with Jenkins would handle code integration but that would not be its only role. This is what I think you are missing.

For continuous integration, you would also run your **testing** stack and **product building** steps. However, if you don't have testing (I would highly recommend it) and you have no need for a building stage, git would do just fine.

# Answer
> 0 votes
To extend others' answers, CI allows to have a "single place of truth" how the software builds and runs in terms of system environment dependencies.

With the rise of infrastructure as code you could of course say okay I have git to put my Dockerfiles for example but this makes somehow no sense.

Many open source projects on GitHub verify validity of pull requests through CI untegration and do double, even triple checks, that is even just one CI system appears not enough to achive high quality.

# Answer
> 0 votes
There are 2 aspects of the software integration (be it continuous or not):

* performing the technical steps to integrate multiple changes - which is what you're referring to in the git-based environments
* checking the quality of the integrated code - in the traditional CI methodology this is what Jenkins and other CI tools do

Jenkins won't technically do the integration steps itself, AFAIK it is not capable of doing that. Its operation is only triggered **after** the technical integration steps are completed, typically by the developers (in your case after you `git commit` and `git push` your changes to origin).

There is a different kind of CI tools out there, the gating-commits ones, which actually perform the technical integration, run the QA verifications on the result and, only on success of the verification, they also merge the result into origin. They effectively do the entire software integration work and are thus capable of guaranteeing no QA regressions in the end result.

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


# Question
Title: How do you write an SLO for a service when higher reliability is needed only during special events?
Special events such as BFCM (Black Friday / Cyber Monday).

# Answer
> 1 votes
it sounds as though the concept of "burst limits" may apply here. If high reliability is needed during foreseen special events of a generally similar duration, it probably is also needed during emerging events too. I suggest broad timescale SLOs (e.g. 99.9% successful responses per month) plus sliding SLOs based on demand, or fixed-limit SLOs instead of rates. An example might be, 99.95% successful responses at 1000qps, 99.99% success at 5000qps. Or, 99.9% successful responses, and no more than 5 failures per second regardless of load.

---
Tags: sre
---


title: Jenkins vs Azure DevOps Pipelines

text:
# Question
Title: Jenkins vs Azure DevOps Pipelines
I've been doing some research on the Azure DevOps solution that Microsoft recently unveiled.

Some background, I've been using Jenkins for years, and recently started exploring the containerisation rabbit hole (Docker, Kubernetes, etc),

I'm unsure about some of the aspects of Azure DevOps Pipelines, and it'd be awesome to get some feedback and clarity.

## TL;DR

1. Is Azure DevOps now competing with Jenkins, where they previously supported the Jenkins community via open source plugins for Jenkins?
2. Is it possible for me to host Azure DevOps Pipelines completely on premise, not just agents?
3. Is it possible to use a self hosted git solution (like GitLab on-premise) with Azure DevOps Pipelines?

## Longer version

1. Microsoft has developed various open-source plugins for Jenkins, such as the Azure App Service Jenkins plugin. There are many examples. To me it seems like the Azure DevOps (specifically Pipelines) solution is now competing directly with Jenkins, or am I missing something?
2. To me it seems that there is no way to host the Azure Pipelines solution on premise, or in a cloud provider of my choice. Yes, I can host my own agents where the bulk of the work is performed, but the actual execution of the pipeline logic happens on Microsoft's servers. And then I have to pay for parallel jobs. I'm comparing this to an on-premise (or cloud provider of choice) hosted Jenkins instance, where no payment is required, and no 3rd party is even aware that our pipelines are running. Am I missing something?
3. From what I can tell, Azure Pipelines has no support for self hosted repositories, I either put my code on GitHub or on Azure repos, nothing else. Thus, I can't even use this Pipelines solution if I have a privately hosted GitLab instance?

Thanks for any input.

# Answer
> 5 votes
I would love to get some clarity too maybe from a more authoritative source than myself (I'm sure I'm guilty of FUD too).

I've been looking to deploy to Azure using Kubernetes. I am similarly confused but I think that is because there isn't one clear path. I can't speak for Microsoft but their attitude to cloud seems to be they are happy to become "*all things to all men*". If you are using Azure, Microsoft don't seem to have a strong opinion on how you get there.

Microsoft are actively trying to evolve; e.g. Linux now dominates Azure

---

Clearly **Azure DevOps** deployment pipeline does exactly what Jenkins can do - so in that sense it is a competitor. There is also that slightly off-putting upfront Azure DevOps pricing for parallel pipelines.

On the one hand, Azure DevOps appears to be a re-branding of Visual Studio Team Services. So it will be familiar to people already within the traditional Microsoft development ecosystem. At the same time Microsoft are making great efforts to embrace technologies that are not traditionally Microsoft (Go, Java, Node.js, Python, Ruby, PHP etc).

It is early days - but it is not a surprise that Azure DevOps pipelines should prefer the Microsoft Git properties of Azure Repos and GitHub. In the same way that BitBucket pipelines prefers BitBucket and GitLab pipelines prefer GitLab.

---

***Meanwhile;***

The Azure Marketplace offers a Jenkins deployment that comes with Azure deployment plugins out of the box.

Many Jenkins plugins have been developed by the Azure DevOps team.

---

***in addition;***

Microsoft have put their backing behind Kubernetes related projects Helm and Draft. Helm is a package manager for Kubernetes. You can even use Helm to deploy a Jenkins installation into Kubernetes.

--

It would be interesting to see someone weigh up the benefits, costs and effort of running your own Jenkins in Azure verses using Azure DevOps pipelines.

... and then there is Jenkins-X.

So it would seem we have many options and decisions to make.

# Answer
> 2 votes
In answer to part 2 (maybe), it does seem like they're pitching it as an alternative to Jenkins, although there's plenty of documentation suggesting that it can all be used together (and here). When used with Jenkins though, it does seem to be more focussed on a deployment bridge. I was hoping that I could use it as a build agent with Jenkins as an orchestrator, like I could do with Jenkins & AWS CodeBuild. I haven't *seen* anything to suggest I could do so yet, but maybe... Multi-cloud deployments is very intriguing though...

# Answer
> 2 votes
1. Yes, because Azure Pipelines can do what Jenkins does. However, you don't have to throw the baby out with the bathwater. Microsoft continues to position their platforms such that integrations can occur with existing installations of just about anything. Many orgs have huge investments in tooling that is difficult to change. Rather than taking an all-or-nothing stance, Microsoft is embracing standards and a bring-your-own mentality, giving you ultimate choice as to how you want to implement the tools.
2. The agents technically are your pipeline as the tasks execute on the agents targeted within the pipeline. All you are configuring within the portal are the steps the pipeline will execute. The agents download tools/extensions necessary to execute the tasks. In addition, with the new YAML pipelines, the pipelines are defined within your code repos. As far as hosting is concerned, you can host Azure DevOps Server entirely on premise, within any cloud provider, or a combination of Azure VMs and Azure SQL.
3. Generic Git repositories are supported in Azure DevOps Services using the classic editor or both YAML and classic editor if using Azure DevOps Server (on-prem) at the moment. You can add GitLab repository integration by installing the extension.

---
Tags: jenkins, azure-pipelines
---


# Question
Title: Ansible cloudformation vs cloudformation
I would like to know the difference between \- AWS cloudformation \- Make AWS cloudformation template through Ansible (https://docs.ansible.com/ansible/latest/modules/cloudformation\_module.html)

I dont know why would i use Ansible if i already have AWs cloudformation

# Answer
> 1 votes
You wouldn't need to use Ansible for AWS cloudformation if you are fine with just using AWS cloudformation.

Ansible integrated AWS cloudformation so that you can convert your local Ansible files into an AWS cloudformation easily.

I'd suggest using Ansible since it provides a great way to test your stacks locally and then you would make the conversion to AWS cloudformation when ready. This is usage dependent however.

---
Tags: ansible, infrastructure-as-code, aws-cloudformation
---


# Question
Title: WorkItem Tracking error when performing clone operation in Azure Devops
Today I received an error when trying to clone test plans in Azure DevOps web portal. Steps:

1. In Visual Studio, I select the Test Case option
2. I find the Test Plan I want to clone, select it , and then select the "Clone test plan" button.
3. In the "Clone Test Plan" window, accept all defaults and click Clone.

Result: an error is received: "Clone operation encountered a WorkItem Tracking error while processing test case xxxx. Retry the operation. Error details: TF51535: Cannot find field 25."

It is extremely unfortunate that this issue happened today while I am trying to clone a large test plan. I will have to manually copy the hundreds of tests in order to have the new test plan ready for Monday morning.

# Answer
This is an indication that someone removed a field from work item configuration that was represented by `25`. It's more of an issue of clean-up not being done when fields are removed. See more about this error on Microsoft's Developer Community.

This other item in the community suggests a different problem when using a particular extension and a fix has been supplied.
> 1 votes

---
Tags: azure-devops
---


# Question
Title: Is it allowed to remove mounted directory from inside Docker container?
I have a container which is based on tomcat image and I have mounted 'webapps' folder to hosted machine directory '/app/webapps'. Now for some updations I want to remove this webapps folder from inside the container but when I execute command: `rm -rf webapps` below error is produced:

> rm: cannot remove 'webapps': Device or resource busy

So I want to know is it possible to remove mounted directory by executing a Linux command from inside the container or not?

# Answer
No, you sadly can't remove a volume that is in use by a container which is stated under 'Extended Description' here: https://docs.docker.com/engine/reference/commandline/volume\_rm/

However, I'd suggest using docker for its strength and restarting the docker container after updating the directory externally.
> 4 votes

---
Tags: docker
---


# Question
Title: How to setup Azure DevOps Pipelines and Releases with multiple apps
Wanting to deploy a collection of .NET Core API's (microservices) using Azure DevOps I run into some challenges:

1. Having 10+ small API's, how should I setup the Release Pipeline? One pipeline with one "stage" for each API/application? Or a separate Pipeline for each API?
2. The API's are deployed to IIS on Windows Server. I'm using the FTP Task now but it's really cumbersome as the AppPool needs to be stopped, then the code is copied over, then the AppPool is started again. I know (non-disruptive) deployment on Azure with App Service is way easier with deployment slots, etc. but what tools can I use on a plain VPS with IIS on Windows Server?
3. How can I transform or inject the correct `appsettings.json` values for each environment during Release using Azure DevOps? I could use Pipeline variables but they seem to be shared across the whole Pipeline, so I would need a separate Pipeline for each API then (see question 1). There's the task "Magic Chunks" but it doesn't handle arrays well (which is widely used for Serilog for example). Environment variables on the target machine would be an option, but the API's are deployed to IIS so how can I separate the environment variables per API (there could be the same keys with different values for multiple API's)?

# Answer
> 2 votes
1. I use separate pipeline for each app
2. you could use powershell task to restart IIS, but I dont think there is a way to do this without shutting down the website. You can also reconfigure website, so copy new code to location X, repoint website to location X, restart website. Then you can easily point it back if something fails and switch is almost instanteneous
3. You can use library variable sets (or groups, dont remember). those can be tied to the stage in the release. it might also be possible to scope regular variables, but I've never tested that.

# Answer
> 0 votes
1. Depends on whether or not these small APIs change together or separately (meaning you may have code changes for only 1 API and be able to deploy it distinctly vs. deploy it all together). If you may have distinct deploy needs, set up separate pipelines.
2. There are extensions specifically for deploying IIS applications that give you all of the features necessary to properly deploy these sites and control other aspects of IIS.
3. There are plenty of extensions and built-in features for transforming configuration files or modifying them using variables from within your pipeline. In addition, each environment can have specific variables so that you can configure the same named variable, but change its value per environment.

---
Tags: azure-devops, azure-pipelines
---


# Question
Title: DevOps in research and science projects?
Is DevOps methodologically anyhow different or even applicable in the academia field if used in research and science projects?

# Answer
> 2 votes
*Disclosure - I have not worked in proper ("Academia") research and science projects.*

DevOps should be just fine for researchers. As in the commercial world, the interesting bit will be to pick the line where the DevOps teams start and where the lower level base ops begins. This is not a contradiction. You may still have a dedicated ops team which provides the hardware, networking, OS, container management (Kubernetes ect. if you have something like this) and so on.

The most crucial part is that these ops guys now provide the *base* for the other teams. This means there is *not* a hand-over of software between the other teams and ops. Ops has the responsibility to provide the DevOps teams with an infrastructure (or platform, whatever you may call it in your case) so they can do their slightly higher-level stuff in a self-sufficient manner. The base ops team would do the hard lifting (i.e., IAM, license stuff, security issues etc.).

There is a plethora of possible ways to structure this. E.g., if you are in a non-techy research field (say, statistics, where people know `R` but nothing much else), you will have a different structure than if your researchers are hardcore coders/OS experts (say, the VR department where researchers program GPUs etc.).

---
Tags: culture, academia
---


# Question
Title: How to test an ansible playbook using molecule inside docker locally?
When molecule is run on travis, the build is successful:

```
$ molecule test
--> Validating schema /home/travis/build/030/ansible-firefox/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    ├── lint
    ├── destroy
    ├── dependency
    ├── syntax
    ├── create
    ├── prepare
    ├── converge
    ├── idempotence
    ├── side_effect
    ├── verify
    └── destroy

--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in /home/travis/build/030/ansible-firefox/...
Lint completed successfully.
--> Executing Flake8 on files found in /home/travis/build/030/ansible-firefox/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on /home/travis/build/030/ansible-firefox/molecule/default/playbook.yml...

Lint completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=1    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'dependency'
Skipping, missing the requirements file.
--> Scenario: 'default'
--> Action: 'syntax'

    playbook: /home/travis/build/030/ansible-firefox/molecule/default/playbook.yml

--> Scenario: 'default'
--> Action: 'create'

    PLAY [Create] ******************************************************************

    TASK [Log into a Docker registry] **********************************************
    skipping: [localhost] => (item=None)

    TASK [Create Dockerfiles from image names] *************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Discover local Docker images] ********************************************
    ok: [localhost] => (item=None)
    ok: [localhost]

    TASK [Build an Ansible compatible image] ***************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Create docker network(s)] ************************************************

    TASK [Create molecule instance(s)] *********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) creation to complete] *******************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    PLAY RECAP *********************************************************************
    localhost                  : ok=5    changed=4    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'prepare'
Skipping, prepare playbook not configured.
--> Scenario: 'default'
--> Action: 'converge'

    PLAY [Converge] ****************************************************************

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

    TASK [ansible-firefox : Download.] *********************************************
    changed: [instance]

    TASK [ansible-firefox : remove the Firefox package] ****************************
    ok: [instance]

    TASK [ansible-firefox : Dependencies.] *****************************************
    changed: [instance] => (item=bzip2)
    changed: [instance] => (item=gtk3)
    changed: [instance] => (item=libXt)

    TASK [ansible-firefox : Create directory.] *************************************
    changed: [instance]

    TASK [ansible-firefox : Unarchive.] ********************************************
    changed: [instance]

    TASK [ansible-firefox : Symlink.] **********************************************
    changed: [instance]

    TASK [ansible-firefox : Create icons directory.] *******************************
    skipping: [instance]

    TASK [ansible-firefox : Copy firefox logo.] ************************************
    skipping: [instance]

    TASK [ansible-firefox : Create desktop icon.] **********************************
    skipping: [instance]

    RUNNING HANDLER [ansible-firefox : Check version.] *****************************
    changed: [instance]

    PLAY RECAP *********************************************************************
    instance                   : ok=8    changed=6    unreachable=0    failed=0

--> Scenario: 'default'
--> Action: 'idempotence'
Idempotence completed successfully.
--> Scenario: 'default'
--> Action: 'side_effect'
Skipping, side effect playbook not configured.
--> Scenario: 'default'
--> Action: 'verify'
--> Executing Testinfra tests found in /home/travis/build/030/ansible-firefox/molecule/default/tests/...
    ============================= test session starts ==============================
    platform linux2 -- Python 2.7.14, pytest-3.3.0, py-1.5.2, pluggy-0.6.0
    rootdir: /home/travis/build/030/ansible-firefox/molecule/default, inifile:
    plugins: testinfra-1.16.0
collected 1 item

    tests/test_default.py .                                                  [100%]

    =========================== 1 passed in 4.16 seconds ===========================
Verifier completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Delete docker network(s)] ************************************************

    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=2    unreachable=0    failed=0

The command "molecule test" exited with 0.
Done. Your build exited with 0.

```

When run locally, it is able to test, but it fails on the last step:

```
[username@localhost ansible-firefox]$ docker run --rm -it -v $(pwd):/tmp/$(basename "${PWD}") -w /tmp/$(basename "${PWD}") retr0h/molecule:latest molecule test
--> Validating schema /tmp/ansible-firefox/molecule/default/molecule.yml.
Validation completed successfully.
--> Test matrix

└── default
    ├── lint
    ├── destroy
    ├── dependency
    ├── syntax
    ├── create
    ├── prepare
    ├── converge
    ├── idempotence
    ├── side_effect
    ├── verify
    └── destroy

--> Scenario: 'default'
--> Action: 'lint'
--> Executing Yamllint on files found in /tmp/ansible-firefox/...
Lint completed successfully.
--> Executing Flake8 on files found in /tmp/ansible-firefox/molecule/default/tests/...
Lint completed successfully.
--> Executing Ansible Lint on /tmp/ansible-firefox/molecule/default/playbook.yml...

Lint completed successfully.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    failed: [localhost] (item=None) => {"attempts": 1, "censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": false}
    fatal: [localhost]: FAILED! => {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": false}

    PLAY RECAP *********************************************************************
    localhost                  : ok=1    changed=1    unreachable=0    failed=1

ERROR:
An error occurred during the test sequence action: 'destroy'. Cleaning up.
--> Scenario: 'default'
--> Action: 'destroy'

    PLAY [Destroy] *****************************************************************

    TASK [Destroy molecule instance(s)] ********************************************
    changed: [localhost] => (item=None)
    changed: [localhost]

    TASK [Wait for instance(s) deletion to complete] *******************************
    failed: [localhost] (item=None) => {"attempts": 1, "censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": false}
    fatal: [localhost]: FAILED! => {"censored": "the output has been hidden due to the fact that 'no_log: true' was specified for this result", "changed": false}

    PLAY RECAP *********************************************************************
    localhost                  : ok=1    changed=1    unreachable=0    failed=1

ERROR:

```

How do other people run molecule inside docker on their local machines?

# Answer
Your molecule run is failing in a very early stage, when it first tries to delete a possibly existing container before starting everything over.

Since you have a default configuration and your make a normal run of molecule, there is absolutely no valuable output in your log.

You have to run molecule in `--debug` mode to get something usable. And I'd bet a case of champagne that the error you will see poping out is that ansible is not able to find `docker or docker-py`.

If I'm right, your solution will then be `pip install docker`
> 1 votes

---
Tags: docker, ansible, molecule
---


title: How to take a backup of Ansible tower?

text:
# Question
Title: How to take a backup of Ansible tower?
Currently we have an `awx` running on a `VM` using containers:

```
CONTAINER ID     IMAGE                        COMMAND                  CREATED             STATUS              PORTS                                                 NAMES
dfb9fa57a8eb    ansible/awx_task:latest      "/tini -- /bin/sh -c…"   2 months ago        Up 6 days           8052/tcp                                              awx_task_1
60dcb5340ca5    ansible/awx_web:latest       "/tini -- /bin/sh -c…"   2 months ago        Up 6 days           0.0.0.0:80->8052/tcp                                  awx_web_1
e80aaddee738    postgres:9.6                 "docker-entrypoint.s…"   2 months ago        Up 6 days           5432/tcp                                              awx_postgres_1
54f20decccfe    ansible/awx_rabbitmq:3.7.4   "docker-entrypoint.s…"   2 months ago        Up 6 days           4369/tcp, 5671-5672/tcp, 15671-15672/tcp, 25672/tcp   awx_rabbitmq_1
0e7ed8c75796    memcached:alpine             "docker-entrypoint.s…"   2 months ago        Up 6 days           11211/tcp                                             awx_memcached_1

```

What is the recommended way for backing up our `awx` instance:

a) Take an export of the VM using `ovf`?

b) Just copying the volume where the pgdata is held enough?

c) Running

```
docker exec -t <postrges_container_id> pg_dumpall -c -U postgres > dump_`date +%d-%m-%Y"_"%H_%M_%S`.sql

```

# Answer
All you need is a backup of the postgres database and the projects (to be safe but they should be rebuildable by pulling them again from your VCS in most cases).

* Exporting an ovf of you full vm is really an overkill IMHO.
* Copying the volumes (pgdata and projects) is by far the simplest solution (the one I actually use). You simply have to put the folders back in place, and `docker-compose up -d` the correct version and you are set. **But** to make sure your backup is consistent, **you need to stop AWX before copying the dirs**, especially for postgres.
* Dumping the postgres database and copying the projects will let you do a backup while AWX is running. For your recovery, you will have to first pop-up a posgres container and reinject the dump before starting all the other containers.

Keep in mind that AWX is the dev version of Tower. As such, there is no real "recommendation" for backups. So the above explanation simply reflect my own experience with AWX. The commercial Tower version embarks the backup in it's deployment playbook. I have never played with it.

If you did not experienced with an AWX upgrade yet, you should be aware that they are sometimes working but can be a real pain (export from old version / import to new version / re-set all the user passwords and jobs credentials). So a backup to quickly rollback when testing the upgrade is *vital* in this case.

Hope this will help you make a wise choice ;)
> 2 votes

---
Tags: ansible, backup, awx
---


# Question
Title: Best practice for Jenkins docker to deploy to other container
I'm currently experimenting with docker with the potential of using it in future professional projects and am a bit confused about best practices.

In my experimental setup I have three docker containers, all currently running on the same server, though that might change in future projects: \- Git server (Gitea) \- Jenkins server \- Web app (Tomcat)

Pulling the source code from git and building the war is no problem. Now I'm running into difficulties actually deploying it.

My current solution: I've modified the tomcat docker so I can deploy the resulting war to the tomcat docker and restart it inside the docker. I've read that this is bad practice and I understand the reasoning, so I need another solution.

Building the docker container from another docker container is also said to be bad practice and I also understand the reasoning for that, so that's a no-go, too.

An idea is to ssh to the host system and then either deploy the webapp to a folder shared with the tomcat container or rebuild the container. That would probably work and be future-proof if the tomcat docker moves to a different host, but it doesn't feel docker-like from my limited docker understanding.

The last idea is to make it so the tomcat docker container builds the webapp itself, i.e. does the git clone, mvn package and so on itself. That still needs to be triggered, possibly by an ssh connection to the host.

In both those cases I'd need to expose a docker-capable user to remote login, which I don't really want to do.

I can only find information on bad practice, not on how to actually solve this specific problem in a good way. What is the actual correct way to do this?

# Answer
> 1 votes
Where you say:

> Building the docker container from another docker container is also said to be bad practice and I also understand the reasoning for that, so that's a no-go, too.

Perhaps there are bad ways of doing that but it can be a solid pattern. By way of example if you use openshift Kubernetes it runs s2i as builder images on your cluster. s2i checks out your code from git, compiles it, and pushes it to a new layer in your docker repo. It has an incremental flag where it will tar up your library deps folders at the end of a build and store as a docker layer. Then the next time you build it does a clean checkout then untars the libraries from the last build. That speeds up the next build a lot as it has the local maven cache from the last build. It also means the s2i build container can be launched on a different host in the cluster at each execution and it just connects to git and the central container registry and does a fast repeatable build.

s2i is a stand alone tool that can use your local docker demon. So it acts as a single commandline ”compile my stuff into an updated docker image”. There are community supported s2i images for php7, node.js, Java etc. I recall that the java s2i will run a maven build with the “openshift” profile and expects your to copy the built WAR to “./deployment”. When you run the image that s2i writes out to your container registry it launches wildfly that is in the base layers and it deploys whatever finds in the deployment folder (but double check its been a while since I looked at it).

In your case If you are using Jenkins I suggest you take advantage that it supports building docker images. Append a docker pipeline step to create your image and push it to your chosen container registry. Enterprises that use Jenkins to build and Nexus for storing JARs and WARs are now using Nexus as their container registry. They can stick with Jenkins and Nexus and simply reconfiguration things to move into the world of containers.

I should also point out that you can be more “microservice-like” by skipping installing tomcat. You can use maven jetty plugin or maven tomcat plugin to just run the code with “mvn jetty:run” or “mvn tomcat7:run”. You can set a full blown config file for the servlet container via the plugins. Maven let's your set whatever jvm options you want. (note: after Tomcat 7 there doesn't seem to be support for this modern approach see the next paragraph where the mainstream now uses Jetty for this).

If you like spring you can use spring boot to build an excutable JAR that runs your webapp. The JAR will be large as it has everything to run the webapp including the servlet container packed into a single JAR. You can run it as “java -jar” and it runs your webapp in an embedded servlet container. Better yet configure it's maven plugin to make an executable jar you can simply run as “./my-app-1.0.0.jar” and it will lunch. That makes building a docker image trivial. You don’t have to install tomcat you only need a container with Java on it and copy in your spring boot executable JAR and run it as the CMD. Spring Boot is very mainstream for Java microservices and it runs Jetty under the bonnet.

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


# Question
Title: How do you hide sensitive information held in variables on a docker-compose file
I am fairly new to DevOps. I have managed to build myself a CI/DI pipeline for my open source project.

As soon as I check-in some code into GitHub, Travis CI takes over, it builds a fresh docker image of my code, pushes it to DockerHub, then the `after_success` step within my `.travis.yml` connects to my VPS via SSH, and runs a script on there which basically does a `docker-compose down` followed by a `docker-compose pull && docker compose up`.

All seems to be working correctly. But I have an issue with my `docker-compose.yml`. Right now as you can see, it has all my environmental variables. Those are considered secret information. How do I hide them from the `docker-compose.yml` file whilst having everything still working as before?

**UPDATE**

I went and created myself a `variables.env` file in the same directory as the `docker-compose.yml`. Inside the `.env` file, I put my old variables, for example:

```
Database__DefaultConnectionString: "Server=database;Port=5432;Database=bejebeje_identity;User Id=postgres;Password=admin;"

```

But in Travis CI I get the following error:

> environment variable name 'Database\__DefaultConnectionString: "Server' may not contains whitespace.

# Answer
> 4 votes
Use environment variables on your host that are read by your `docker-compose.yml` file. There are a couple ways to accomplish this. One way is to create a `.env` file on the host that contains your variables. Docker Compose will read these variables and apply them to your configuration.

Alternatively, or in conjunction with a `.env` file, you can set environment variables in your shell. These variables will be applied the same way as those read from a `.env` file and actually take precedence.

Read more here: https://docs.docker.com/compose/environment-variables/

---
Tags: docker-compose, travis-ci, servers
---


title: What is an artifactory?

text:
# Question
Title: What is an artifactory?
There are quite some questions and answers that mention "***artifactory***".

I wouldn't be surprised if it is somehow related to .

**My questions**:

* What is actually an "artifactory" (in the context of DevOps)?
* Why are artifactories used?

# Answer
Artifactory is a product by JFrog that serves as a binary repository manager. That said very often one will use a 'artifactory' as a synonym of the more general binary repository, much like many people use Frigidaire or fridge to denote the refrigerator regardless if it is a Frigidaire brand or not.

The binary repository is a natural extension to the source code repository, in that it will store the outcome of your build process, often denoted as artifacts. Most of the times one would not use the binary repository directly but through a package manager that comes with the chosen technology.

In most cases these will store individual application components that can later be assembled into a full product - thus allowing a build to be broken in smaller chunks, making more efficient use of resources, reducing build times, better tracking of binary debug databases etc.

Here are some of the most popular package managers that can be managed using a binary repository:

* Java: jar, ear, war etc has Maven and the official MavenCentral. There are many other package managers that will use the maven binary repository format as well (ivy, gradle etc).
* .Net: nuget for .NET components (DLL and EXE) but can also be used as a distribution mechanism under windows thorugh systems like Chocolatey. Newer versions of Powershell can also leverage this to distribute powershell modules though the powershell gallery of which one could build a local distribution with a binary repository and a repository in nuget format. Also check OneGet if Windows distribution management is of interest to you.
* In JavaScript: we have npm which is one of the most popular, will require nodejs.
* In python: there is pip and the official package index pypi, which one can also create a local instance through binary repository that will support the format.

This list is far from complete, just gives an idea of what's out there.

The binary repository can allow to host all of these under one roof, making their management much simpler for teams. Note that you do not need a very large team to start reaping benefits from binary package management. The initial investment is not very large and the benefits are felt immediately. Especially now that more and more platforms, frameworks and languages are integrating this dependency management directly in them. Their biggest advantage I have found however was to create an environment that your programmers will find natural and comfortable making it essential. It helps you as a devops creating a solid tool-chain and it helps them making the overall experience fit naturally in their stack of choice.

As I said earlier there are many products out there that can serve as binary package managers, some more generic than others in their target usage, varying also widely in their accessibility and prices.

My personal opinion is that binary repositories are as vital a part of a well designed devops setup as the source code repository or continuous integration.
> 128 votes

# Answer
The way it helped me understand initially, the difference between source code repository and binary repository was to think of it like: * Github or Bitbucket is useful to maintain all 'code' * Jfrog Artifactory is useful to maintain the built 'binary' At least till I was comfortable with these terms!

Also, the importance of Artifactory can be understood in relation to the philosophy of DevOps to "Build once, Deploy always". It goes a long way in Continuous Integration to build your binary once, put it into Artifactory and then call it from there to deploy into all of the different environments. That way, we are sure that the code that works in Dev is the one pushed to Prod and will work there.
> 26 votes

# Answer
Artifactory is a Binary Repository Manager product from Jfrog.

You're right - being a binary repository manager it is typically used to manage storage of generated and used in the software development process.

From Artifactory's main webpage:

> As the first, and only, universal Artifact Repository Manager on the market, JFrog Artifactory fully supports software packages created by any language or technology.
>
> ...
>
> ...Artifactory provides an end-to-end, automated and bullet-proof solution for tracking artifacts from development to production.

The usages you mentioned suggest it may be popular enough for a generic trademark in DevOps.
> 12 votes

# Answer
I think complicating things is what everybody is getting appreciated for nowadays. I will try to answer this question in short .

Source Repository is used for storing code and its versions, while artifactory is used for storing the executable programs that are outputs of those code \[ binaries - dll, jar, war, ear, msi, exe files etc.\]

Now the reason why you would want to place them separately in a repo which is different from your code could be many - right from secure access, hacking threat, preventing unintentional downloads of malicious/modified jars or to simply have a separate avenue for the clients who will be using your binaries to develop their code.

The technology of SCM could have divulged itself into creating 2 kind of users ( one with developer privileges who will be able to access the source code and another as a client who will just be able to access binaries). But it did not take that route! So now we have artifactories.
> 11 votes

# Answer
**An artifact**

Is something that is produced/generated/crafted out of a specific process

> Jar out of a Java project build.
>
> Question out of your mind
>
> Car out of a factory
>
> New song

**A repository**

Is a receptacle where things are persisted

> Github for a Java project.
>
> StackExchange for your daunting questions

IN THEORY, an **Artifact**-*ory* would be a repository of artifact where they are persisted and managed throughout their life cycle.

In the context of DevOps, Artifactory is a product that manages binary artifacts. It stores and manages different types (Jar, Python and npm packages, etc...) that you produce out of your builds and re-use at compile or deployment time.
> 5 votes

---
Tags: terminology, artifacts, artifactory
---


# Question
Title: External access to internet from Kubernetes Pods
I'm having troubles with network access from pods. I had installed new Kubernetes cluster with flannel-network plugin, Checking the health of server - good.

I tried to check network via busybox: `kubectl run -it --rm --restart=Never busybox -n microservices --image=busybox sh`, then `ping 8.8.8.8` results in drop.

But `ping 8.8.8.8` succeeded when executed from `kubectl exec -it kube-flannel-ds-amd64-xxxx -n kube-system` (checking network inside flannel pod).

What can it be? I think it can be something with flannel or docker network configuration. But i did not find information about it.

I tried to change iptables configs, reinit cluster, create and changing docker network interfaces.

I have no more ideas, what can I do?

P.S. There is the same server installed before me and their settings and installation procedure are identical. And their connection is good.

# Answer
I found the solution ...

Check your network interfaces (`ifconfig -a cni0`). Good config is:

> cni0: flags=4163 mtu 1450 inet 10.244.0.1 netmask 255.255.255.0 broadcast 0.0.0.0...

That subnet (10.244.0.0) configured in flannel-deploy.yaml

But, by default, a new server may have:

> cni0: flags=4163 mtu 1450 inet 192.168.0.1 netmask 255.255.255.0 broadcast 0.0.0.0...

Change it to:

`ifconfig eth0 10.244.0.1 netmask 255.255.255.0 broadcast 0.0.0.0`
> 3 votes

---
Tags: kubernetes, networking
---


# Question
Title: Unable to validate certificate chain: cert.pem in Zimbra mail server
I am trying to install let's encrypt SSL in my Zimbra mail server but getting below error when running below command.

```
/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem

```

**Error**:

```
** Verifying ‘cert.pem’ against ‘privkey.pem’
Certificate ‘cert.pem’ and private key ‘privkey.pem’ match.
** Verifying ‘cert.pem’ against ‘chain.pem’
ERROR: Unable to validate certificate chain: cert.pem: C = US, O = Let’s Encrypt, CN = Let’s Encrypt Authority X3
error 2 at 1 depth lookup: unable to get issuer certificate

```

# Answer
> 2 votes
> This error occurrs because you do not add the root CA in your chain.pem file:

for solutions add below chain in your chain.pem file:

```
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

```

OR you can use below script for install Let's Encrypt SSL in your Zimbra server:

```
#!/bin/bash

# SSL certificate installation in Zimbra
# with SSL certificate provided by Let's Encrypt (letsencrypt.org)
# Author: Subhash (serverkaka.com)

# Check if running as root
if [ "$(id -u)" != "0" ]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

read -p 'letsencrypt_email [xx@xx.xx]: ' letsencrypt_email
read -p 'mail_server_url [xx.xx.xx]: ' mail_server_url

# Check All variable have a value
if [ -z $mail_server_url ] || [ -z $letsencrypt_email ]
then
      echo run script again please insert all value. do not miss any value
else

# Installation start
# Stop the jetty or nginx service at Zimbra level
su - zimbra -c 'zmproxyctl stop'
su - zimbra -c 'zmmailboxdctl stop'

# Install git and letsencrypt
cd /opt/
apt-get install git
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

# Get SSL certificate
./letsencrypt-auto certonly --standalone --non-interactive --agree-tos --email $letsencrypt_email -d $mail_server_url --hsts
cd /etc/letsencrypt/live/$mail_server_url
cat <<EOF >>chain.pem
-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
EOF

# Verify commercial certificate
mkdir /opt/zimbra/ssl/letsencrypt
cp /etc/letsencrypt/live/$mail_server_url/* /opt/zimbra/ssl/letsencrypt/
chown zimbra:zimbra /opt/zimbra/ssl/letsencrypt/*
ls -la /opt/zimbra/ssl/letsencrypt/
su - zimbra -c 'cd /opt/zimbra/ssl/letsencrypt/ && /opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem'

# Deploy the new Let's Encrypt SSL certificate
cp -a /opt/zimbra/ssl/zimbra /opt/zimbra/ssl/zimbra.$(date "+%Y%m%d")
cp /opt/zimbra/ssl/letsencrypt/privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key
sudo chown zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial/commercial.key
su - zimbra -c 'cd /opt/zimbra/ssl/letsencrypt/ && /opt/zimbra/bin/zmcertmgr deploycrt comm cert.pem chain.pem'

# Restart Zimbra
su - zimbra -c 'zmcontrol restart'

# setting auto https redirect
cd /opt && touch https-redirect.sh && chown zimbra:zimbra https-redirect.sh && chmod +x https-redirect.sh
cat <<EOF >>/opt/https-redirect.sh
zmprov ms $mail_server_url zimbraReverseProxyMailMode redirect
EOF
su - zimbra -c '/opt/https-redirect.sh'
rm /opt/https-redirect.sh
if

```

read this link for more details: https://github.com/SubhashPatel/Install-Zimbra-mail-server-ubuntu/blob/master/configure-ssl-zimbra.sh

---
Tags: ssl
---


# Question
Title: Programmatically scrape the latest version of Tomcat for an installation script
Looking for some assistance or ideas on how to grab the latest version of a Tomcat release from their website or other website.

I came across these Stack Overflow/Stack Exchange links that were relevant below:

..But unfortunately both led to some dead-ends. It did give me some ideas though.

I have some installation scripts where the download URL is predictable based on the version number of the software, so if there's a consistent way of scraping for the latest version of the software I simply add a variable into the script for it to curl / grep for that version on the text and use that variable for download links, untaring, moving, etc.

Hoping to do something with Tomcat in the same vein. A installation script I won't need to keep updating (unless they change their site).

Any sort of thoughts, ideas, are appreciated.

I've also looked at http://tomcat.apache.org/whichversion.html which lists the "Latest Released Version" and this seems like maybe the best, more reliable location to grab the version, but I had trouble getting that with Curl / Grep because of the table structure. I am only just scratching the surface with learning those commands, so maybe someone more well versed could get that working, otherwise I'm definitely open to other thoughts!

```
curl -i https://api.github.com/repos/apache/tomcat/tags | grep '"name"' | head -1 | egrep -o "([0-9]{1,}\.)+[0-9]{1,}"

```

It seems to work but I am not sure if I am entirely happy with it. An additional use-case that I thought of, is it would be nice to grab the latest version of each major version instead of just the absolute latest.

Do you have suggestions on how you would parse the highest number with the link you provided, and/or how to start in one of those directories and parse the highest there? That way for example I could create a latest version install script for Tomcat 7, 8, 9, etc.

Thank you!! (Like I said I am just getting started, so please my apologies with the lack of knowledge but I do appreciate digging in and understanding how the commands work or reached their conclusion)

# Answer
I've created a couple crude methods of grabbing the latest major versions of releases, as well as absolute latest.

```
# Grab Latest Tomcat 7
curl -i https://www-us.apache.org/dist/tomcat/tomcat-7/ | grep -Po '(?<=(<a href="v)).*(?=/">v)'

# Grab Latest Tomcat 8
curl -i https://www-us.apache.org/dist/tomcat/tomcat-8/ | grep -Po '(?<=(<a href="v)).*(?=/">v)'

# Grab Latest Tomcat 9
curl -i https://www-us.apache.org/dist/tomcat/tomcat-9/ | grep -Po '(?<=(<a href="v)).*(?=/">v)'

# Grab Latest Tomcat
curl -i https://api.github.com/repos/apache/tomcat/tags | grep '"name"' | head -1 | egrep -o "([0-9]{1,}\.)+[0-9]{1,}"

```

It's a bit of a hack where I'm looking for text in-between two values on a web page to grab the version number. It's crude and I'm sure there's a more elegant way to grab this, but this what I was able to figure out with my skillset! Maybe it can help someone in the future, but if anyone has better ideas I'm all ears.
> 0 votes

# Answer
In general, I would not recommend scraping version numbers and download URLs from websites. You will end up having to modify your scripts when they inevitably end up breaking — I have learned this the hard way time and time again.

For example, take the following script I wrote in 2016 to scrape the latest Tomcat version:

```
curl https://tomcat.apache.org/whichversion.html | awk -n '
/class="detail-table"/ {
    phase = 1
}
phase == 1 && /<th>/ {
    target_column++
    if (/Actual release revision/) phase = 2
}
phase == 2 && /<tr>/ {
    current_column = 0
}
phase == 2 && /<td>/ {
    current_column++
}
phase == 2 && current_column == target_column && !/alpha|beta|superceded/ {
    print substr($0, match($0, /[0-9]+\.[0-9]+\.[0-9]+/), RLENGTH)
    exit
}'

```

Unfortunately, that script **no longer works**, and I do not know when it broke. No amount of fancy scripting will save you from unexpected structural changes to a website you are scraping.

Sure, maybe a little bit of finagling will fix this one particular script, but if you try to download all your dependencies this way, you'll be playing catch-up till the end of time. Aim for a solution that you only need to code once.
> 0 votes

---
Tags: shell-script, tomcat
---


# Question
Title: Cancel sibling snapshot dependency on failure
I have a simple build chain configure in TeamCity:

```
                         build ->
create-base-image ->                      -> docker publish
                         test  ->

```

I have the "On failed dependency: cancel build" option enabled. So if either `build` or `test` fails, the queued `docker publish` step will be cancelled.

However if `build` fails, the `test` step continues to run all the way through and visa versa.

I would like to cancel all sibling tasks if any of them fail. Or if a dependent step is cancelled (`docker publish`) I would like all currently running dependencies of that to be stopped.

Someone asks the same question here: https://teamcity-support.jetbrains.com/hc/en-us/community/posts/206926235-Cancel-other-snapshot-dependencies-if-one-dependency-fails-

But I'm not sure if the linked YouTrack issue is actually solving this problem.

# Answer
> 2 votes
I was unable to find a way to configure the build to behave like I wanted. Instead I needed to start using the TeamCity API to achieve this.

In the `build.sh` and `test.sh` file that TC runs, I extended the failure function (simple bash function we call whenever our build script fails):

```
teamcityFailure () {
    . ./cancel_build_chain.sh
    echo "##teamcity[buildProblem description='$1']"
    exit 1
}

```

This now calls off to this new `cancel_build_chain.sh` script, which looks something like this:

```
#!/bin/bash

teamcityProgress () {
    echo "##teamcity[progressMessage '$1']"
}

teamcityProgress "Build step has failed, attempting to cancel the rest of the build chain..."

BUILD_ID=$TEAMCITY_BUILD_ID # passed in from build chain configuration

# Use the current failed step ID to query for the snapshotDependency "from:" here - which returns the final "docker publish" step
FINAL_STEP_DATA=$(curl --silent --request GET \
    "https://teamcity/app/rest/builds/project:MyProjectName,snapshotDependency:(from:(id:$BUILD_ID),includeInitial:true),defaultFilter:false" \
    --header "Content-Type: application/xml"")

# From the "docker publish" step, parse the XML and fetch out all dependent step IDs. One will be this current step, the others will be its sibling steps
# We do this twice, once for queued steps, and once for currently running steps. This is because we need to cancel running vs queued builds differently.
QUEUED_DEPENDENT_STEP_IDS=$(echo $FINAL_STEP_DATA \
 | grep -Eo '<snapshot-dependencies.+<build id="[0-9]+".+state="queued"' \
 | grep -Eo 'id="([0-9]+)"' \
 | grep -Eo '[0-9]+')

# Now remove the current step ID
QUEUED_DEPENDENT_STEP_IDS=${QUEUED_DEPENDENT_STEP_IDS/$BUILD_ID/}

# trim leading / trailing whitespace
QUEUED_DEPENDENT_STEP_IDS=QUEUED_DEPENDENT_STEP_IDS | sed 's/ *$//'

RUNNING_DEPENDENT_STEP_IDS=$(echo $FINAL_STEP_DATA \
 | grep -Eo '<snapshot-dependencies.+<build id="[0-9]+".+state="running"' \
 | grep -Eo 'id="([0-9]+)"' \
 | grep -Eo '[0-9]+')

# Now remove the current step ID
RUNNING_DEPENDENT_STEP_IDS=${RUNNING_DEPENDENT_STEP_IDS/$BUILD_ID/}

# trim leading / trailing whitespace
RUNNING_DEPENDENT_STEP_IDS=RUNNING_DEPENDENT_STEP_IDS | sed 's/ *$//'

for DEP_ID in $QUEUED_DEPENDENT_STEP_IDS
do
    teamcityProgress "Cancelling queued build step $DEP_ID"
    curl --silent --request POST \
        "https://teamcity/app/rest/buildQueue/project:MyProjectName,id:$DEP_ID" \
        --data "<buildCancelRequest comment='Another part of the build chain failed so this sibling step was cancelled.' readdIntoQueue='false' />" \
        --header "Content-Type: application/xml"
done

for DEP_ID in $RUNNING_DEPENDENT_STEP_IDS
do
    teamcityProgress "Cancelling running build step $DEP_ID"
    curl --silent --request POST \
        "https://teamcity/app/rest/builds/project:MyProjectName,id:$DEP_ID" \
        --data "<buildCancelRequest comment='Another part of the build chain failed so this sibling step was cancelled.' readdIntoQueue='false' />" \
        --header "Content-Type: application/xml"
done

```

Not super elegant but it gets the job done and prevents build agents sitting there running build steps for builds which have already failed.

---
Tags: build-pipeline, teamcity
---


# Question
Title: Keeping graphs of terminated Kubernetes pods in Prometheus/Grafana
I love using Prometheus/Grafana to monitor and tune resource usage on my Kubernetes clusters. When pods are terminated, however, the graphs are disposed of it seems.

I am looking for a solution to this problem.

For informed decisions on how to tune resource requests I need history to be kept.

Does anybody know how to keep graphs for deleted Kubernetes pods in Prometheus/Grafana.

I am currently using this deployment: https://itnext.io/kubernetes-monitoring-with-prometheus-in-15-minutes-8e54d1de2e13

# Answer
> 5 votes
The metrics for deleted pods still exists on the Prometheus Time Series Database. The problem is that the Grafana dashboards imported from kubernetes-mixin create the pod list when loading the dashboards.

To change this in Grafana, open the `Variables` menu, then change `$pod` variable to refresh `On Time Range Change`:

Go back to the panels and change the time range (e.g., to "This Month"). The deleted pods for that period should be listed in the dropdown menu.

---
Tags: kubernetes, prometheus, grafana
---


title: AWS EKS CronJob resource not found

text:
# Question
Title: AWS EKS CronJob resource not found
I have an Amazon EKS Kubernetes cluster and have the need to run a CronJob on it. However, when I published the manifest to k8s, the object is there, I can list it, get it, but I cannot describe it and see its events. Also, it doesn't seem to start at all. According to my cron pattern, it should have started on the first hour.

What I have done so far:

I have created the manifest for the CronJob:

```
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: aws-ecr-token
  namespace: default
  labels:
    app: aws-ecr-token
    component: infrastructure
spec:
  schedule: "* */11 * * *"
  jobTemplate:
    metadata:
      name: aws-ecr-token
      namespace: default
      labels:
        app: aws-ecr-token
        component: infrastructure
    spec:
      completions: 1
      backoffLimit: 3
      activeDeadlineSeconds: 60
      parallelism: 1
      template:
        metadata:
          name: aws-ecr-token
          namespace: default
          labels:
            app: aws-ecr-token
            component: infrastructure
        spec:
          containers:
          - name: aws-ecr-token
            image: docker pull mesosphere/aws-cli
            command:
            - "sh"
            - "-c"
            - "$(aws ecr get-login --no-include-email)"
            env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: aws-ecr
                  key: accessKey
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: aws-ecr
                  key: secretKey
            - name: AWS_DEFAULT_REGION
              valueFrom:
                secretKeyRef:
                  name: aws-ecr
                  key: defaultRegion
            volumeMounts:
            - name: aws-ecr-config
              mountPath: /root/.docker
          restartPolicy: OnFailure
          volumes:
          - name: aws-ecr-config
            secret:
              secretName: aws-ecr-config

```

Deployed it using:

```
$ kubectl apply -f aws-ecr-token-cron-job.yaml

```

I can get it:

```
$ kubectl get cronjobs
NAME            SCHEDULE      SUSPEND   ACTIVE    LAST SCHEDULE   AGE
aws-ecr-token   * */11 * * *   False     0         <none>          26m

```

But it never gets scheduled.

When I try to describe it, it shows:

```
$ kubectl describe cronjobs
Error from server (NotFound): the server could not find the requested resource

```

Any ideas why?

My version is:

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.0", GitCommit:"fc32d2f3698e36b93322a3465f63a14e9f0eaead", GitTreeState:"clean", BuildDate:"2018-03-26T16:55:54Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10+", GitVersion:"v1.10.11-eks", GitCommit:"6bf27214b7e3e1e47dce27dcbd73ee1b27adadd0", GitTreeState:"clean", BuildDate:"2018-12-04T13:33:10Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}

```

Thanks in advance :)

# Answer
There was an error in Kubernetes that causes failure when using `kubectl describe` with the `cronjob` resource. It was fixed at some point between the `v1.10.x` and `v1.12.x` versions (more info in this issue #45418).

You said:

> According to my cron pattern, it should have started on the first hour.

But your schedule is `* */11 * * *`, and it means: “At every minute past every 11th hour.”

I did not understand what you exactly meant with "on the first hour", but if you are talking about running the job on every new hour, the schedule should look like this: `0 * * * *`
> 0 votes

---
Tags: amazon-web-services, kubernetes
---


# Question
Title: How to use same Helm dependency in many charts?
For example, I have this charts structure:

```
├── parentChart
│   ├── charts
│   │   ├── childChart1
│   │   │   ├── charts
│   │   │   │   └── postgresql-3.11.6.tgz
│   │   │   ├── Chart.yaml
│   │   │   ├── requirements.lock
│   │   │   ├── requirements.yaml
│   │   │   ├── templates
...
│   │   │   └── values.yaml
│   │   ├── childChart2
│   │   │   ├── charts
│   │   │   │   └── postgresql-3.11.6.tgz
│   │   │   ├── Chart.yaml
│   │   │   ├── requirements.lock
│   │   │   ├── requirements.yaml
│   │   │   ├── templates
...
│   │   │   └── values.yaml
│   └── Chart.yaml
...

```

In the childChart1 and childChart2 I have this dependency: Child1:

```
dependencies:
  - name: postgresql
    version: 3.11.6
    repository: alias:stable
    alias: child1-postgres
...

```

Child2:

```
dependencies:
  - name: postgresql
    version: 3.11.6
    repository: alias:stable
    alias: child2-postgres
...

```

First problem: I expect that after deploy parent chart I will have 4 deployment:

1. childChart1
2. childChart1 Postgresql
3. childChart2
4. childChart2 Postgresql

Am I right?

If I don't do anything wrong with a first problem, why I see this message when I trying to deploy this charts:

```
$ helm install $opts --name $NAME --namespace $NAME $package --wait --timeout 9999
Error: release test failed: secrets "test-postgresql" already exists

```

P.S. I have this helm version:

```
$ helm version
Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}

```

# Answer
> 2 votes
Finnaly, I found the solution, thanks to @simbo1905.

All that I need to fix that problem: values.yaml Child Chart 1 (or two)

```
postgresql:
  nameOverride: chart-1-postgres

```

In the Child Chart 2 `nameOverride` became to chart-2-postgres.

---
Tags: kubernetes, helm, openshift
---


# Question
Title: replacing values in shell script using sed
My shell script looks like this:

```
FAILED_REQUEST_DIRECTORY=/bla/bla2 \
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1234 \
     -jar /xyz/abc-service-1.0-SNAPSHOT.jar \
     --server.port=1111 \
     --server.address=127.0.0.1 \
     --kafka.bootstrap.servers=10.111.11.11:3197,10.112.12.111:3197,10.123.44.25:3197 \
     --topic.pushcrew.encryptionKey=abc-def-egh \
     --spring.application.name=name-sevice \
     --fb.verification.token=token \
     --management.trace.include.payload=true \
     --topic.pushcrew.hits=activity-logs \
     --max.block.ms=1000 \
     --pager.duty.api.key=apikey \
     --dsn=dsn

```

If I have to replace values of keys in the command, for ex: replacing value of key `--server.address` with the value to shell script through a variable, how would I do it?

I understand it would look like following if I had to replace value for key --server.address:

```
sed -i "s#--server.address=.* #$SERVER_ADDRESS#g;

```

But how do I maintain the space that has to be there after the replacement and how do I make sure that part int the key only after `=`(equals to) and before  (space) gets replaced.

# Answer
Negation to the rescue:

```
sed -i "s/server.address=[^\ ].*\ /server.address=${SERVER_ADDRESS} /g"

```

This is telling to search zero or more characters (`.*`) NOT matching whitespace (`[^\ ]`) up to the first whitespace.

A good pattern is not to use real values to be replaced (`10.111.11.11:3197`) but to use a mark like `###SERVER_ADDRESS###`. If something goes wrong you can easily post-check with

```
grep "###" && exit -1

```

This can avoid continuing with dangerous values (mixing dev/pre/pro values)
> 2 votes

# Answer
You can do this using **perl**

For Example

```
perl -pi -e "s/server.address=localhost/server.address=${SERVER_ADDRESS}/g" file_path

```

This command change server address value localhost to vaariable value.

Hope this works
> 1 votes

---
Tags: shell-script, bash
---


# Question
Title: Cleanest way to prematurely exit a jenkins pipeline from inside a withEnv
In a Jenkins scripted pipeline with the below structure, the `return` command will exit only the `withEnv`.

```
node{
    withEnv([...]){
        stage('1'){
        ...
        }

        stage('2'){
        .....
        }

        if( env.BRANCH_NAME != 'master' ) {
            currentBuild.result = 'SUCCESS'
            return
        }

        stage('3'){
        ...
        }
    }

    stage('4'){
        withEnv([...]){
            ...
        }
    }

    stage('5'){
        ...
    }

    stage('6'){
    ...
    }
}

```

How can I stop the entire pipeline after stage2 with SUCCESS?

# Answer
Just the way you can exit any stage prematurely by using `return` keyword, you can use the `return` keyword (outside of the stage) to exit the entire pipeline prematurely. You can re-use the `currentBuild.result` value outside of `Stage 4`. See below.

```
node{
    withEnv([...]){
        stage('1'){
        ...
        }

        stage('2'){
        .....
        }

        if( env.BRANCH_NAME != 'master' ) {
            currentBuild.result = 'SUCCESS'
            return
        }

        stage('3'){
        ...
        }
    }

    stage('4'){
        withEnv([...]){
            ...
        }
    }

    if(currentBuild.result == 'SUCCESS') {
        return //this will exit the pipeline
    }

    stage('5'){
        ...
    }

    stage('6'){
    ...
    }
}

```
> 2 votes

# Answer
I think you are looking for **error()** function, this question has been answered somehow in: This question: Abort current build from pipeline in Jenkins
> 1 votes

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


# Question
Title: How to use port 5433 with Azure managed postgres
We are looking to use Azure managed postgres but I am having some issues with connecting on port `5433` I can connect on port `5432` fine. I need just port 5433 to work, is there a way to access that port?

# Answer
You can not change the port that Azure Database for PostgreSQL server uses. Connections to your Azure Database for PostgreSQL server communicate over port **5432**. When you try to connect from within a corporate network, outbound traffic over port 5432 might not be allowed by your network's firewall. If so, you can't connect to your server unless your IT department opens port 5432.

If you truly need to use port 5433 you can install PostgreSQL on an Azure VM (IaaS).
> 2 votes

---
Tags: azure, postgresql
---


title: How to change PagerDuty incident name?

text:
# Question
Title: How to change PagerDuty incident name?
I have AWS Cloudwatch hooked up with PagerDuty. Whenever an alert goes out, it goes to PagerDuty, which then sends us a message in Slack. The problem is, this is what it shows in the chat:

> *Triggered #3362:* Maximum CPUUtilization of 53.6 GreaterThanOrEqualToThreshold 50.0 for InstanceId i-xxxxxxxxx

That's about as useful as a rock. There's no way I could interpret the instance ID, nor should I have to read all that stuff at a glance and figure out what's wrong.

The question is, how do I change the incident name that gets generated on PagerDuty, or is this something that can be done in Cloudwatch, or am I hosed?

# Answer
Within the CloudWatch integration in PagerDuty, you can change the "Derive name from" field to something like "Alarm Description".
> 5 votes

# Answer
Based on the PagerDuty documentation on Cloudwatch, it doesn't look like it's configurable:

https://www.pagerduty.com/docs/guides/aws-cloudwatch-integration-guide/
> 2 votes

---
Tags: monitoring, amazon-cloudwatch, slack, pagerduty
---


# Question
Title: Structuring Ansible playbooks for low volume, purpose-built images
I hope this question is not too vague / opinion-based:

I need to create and maintain a handful of virtual machines that get packaged up and deployed out to thousands of users, depending on specific requirements. Everyone is doing roughly the same job, but different people need different tools. This is important because I don't think I can structure things around roles (though I'm happy to be told I'm wrong).

They way I have things structured now is:

```
vagrant-directory
|-Vagrantfile # Multi-host setup, with one machine per "use-case"
|-scripts/ # Shell scripts run by Vagrant (mostly used to install Ansible prereqs)
|-ansible/ # All Ansible-related files
|----Playbook1.yml # One playbook per use case
|----tasks/ # Contains task files for everything I want to do
|------install/ # All task files related to installing software
|------apt-update.yml # For example, a script to run apt update
|------iptables-flush.yml # Disable iptables

```

With this approach, it basically means that when I get a requirement for a new machine, I have to create a new Playbook42.yml, use `import_tasks` for the tasks that I need, create any machine-specific tasks, and then provision and export.

Is there a more "Ansible official" or industry standard approach to doing this?

# Answer
> 2 votes
Unless I totally missed your question, roles are exactly what you need in this case. I'll use examples from my real world. My code below is just to illustrate my point (so it is not fully runnable, might contain errors and is not bullet proof rocket science: you will probably have to adapt/overcome tools limitations). But at least you'll be able to tell me if I got you wrong.

Let's say your servicing a large community of developers on different techs: java, php, nodejs, scala, python, ruby... needing some tools as well like apache, nginx, postgres, mysql, redis...

You have a role for each of these techs/tools, and possibly use existing ones from galaxy that you don't even have to write and that you can download at provisioning time. These roles can possibly be controlled with vars to choose e.g. versions. (see vagrant provisionner config below)

Now, one way you can activate/deactivate roles in a play is with the use of tags

Your unique playbook could look something like this

```
- name: Vagrant provisionning playbook
  hosts: all

  pre_tasks:
    # whatever you need to do before roles

  roles:
    - role: php
      tags: [php]
    - role: java
      tags: [java]
    - role: nginx
      tags: [nginx,php] # if you always deploy php with nginx
    - role: redis
      tags: [redis]
    # more roles here

    tasks:
      # Whatever tasks are needed to be played after roles

```

With such a structure, you can now configure your ansible provisioinner in vagrant defining the tags and specifying the vars needed to provision with your single playbook.

```
Vagrant.configure(2) do |config|

  config.vm define "php_application" do |php_application|

    # Some config for vm
    php_application.vm.provision "ansible" do |ansible|
      ansible.playbook = "playbook.yml"
      ansible.tags = "php,nginx,untagged"
    end

  end

  # Host vars declared globally. You might be able to do
  # it on host by host basis but the doc does not specify it
  config.vm.provision "ansible" do |ansible|
    ansible.host_vars = {
      "php_application" => {"php_version" => "7.2"}
    }
  end
end

```

Does this fit your needs ?

Note: if a single playbook is too much of a hassle, you can still use the roles and assemble in each playbook the techs/tools you need and reuse things that you will need in several places.

---
Tags: ansible, vagrant
---


# Question
Title: No space left on device when running job on photon-os
I'm using gitlab and gitlab-ci along with gitlab-runner.

Gitlab-runner is choking on my build jobs for a day now and I can't find a way to solve the problem.

The problem appears when the `npm install` command runs :

```
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/array-initial-dd86c469/.jshintrc'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/color-support-612f9677/index.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/clone-94e64b37/clone.iml'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/async-each-23f1cf68/README.md'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/extend-b499a705/.travis.yml'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/function-bind-b92d92f1/implementation.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/fs.realpath-89c6342a/old.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/balanced-match-601d32f6/LICENSE.md'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/default-resolution-1ee87648/index.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/archy-6b1fc3a7/test/beep.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/array-initial-dd86c469/LICENSE-MIT'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/core-util-is-c201cb52/lib/util.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/concat-map-071c084f/example/map.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/buffer-equal-a9e86a30/example/eq.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/gulp-02a15240/package.json'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/flagged-respawn-ed938be5/lib/is-v8flags.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/extend-b499a705/CHANGELOG.md'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/function-bind-b92d92f1/index.js'
npm WARN tar ENOSPC: no space left on device, open '/builds/sites/mysite/.npmcache/lib/node_modules/.staging/default-resolution-1ee87648/node-version.js'
Unhandled rejection Error: ENOSPC: no space left on device, open '/root/.npm/_cacache/index-v5/48/51/88ad48f396d262bcea9e42159a40a93446826c57af0b1c54d2699aca3607'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/de/70'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/de/70'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/2f/98'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/5d/36'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/2d/fa'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/f8/8f'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/7d/c9'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/1e/e2'
Unhandled rejection Error: ENOSPC: no space left on device, mkdir '/root/.npm/_cacache/index-v5/b8/3c'

```

Gitlab-runner is running in a docker container on a photon-os machine.

The cache directory of the runner itself (`/builds/sites`) is only 60M.

Here is the result of `df -h` on the host (photon-os)

```
Filesystem      Size  Used Avail Use% Mounted on
overlay          16G   13G  2.0G  87% /
tmpfs            64M     0   64M   0% /dev
tmpfs          1000M     0 1000M   0% /sys/fs/cgroup
shm              64M     0   64M   0% /dev/shm
/dev/root        16G   13G  2.0G  87% /etc/gitlab-runner
tmpfs          1000M  652K  999M   1% /run/docker.sock
tmpfs          1000M     0 1000M   0% /proc/acpi
tmpfs          1000M     0 1000M   0% /sys/firmware

```

and here, df -hi

```
Filesystem     Inodes IUsed IFree IUse% Mounted on
overlay          1.0M 1021K  3.8K  100% /
tmpfs            250K    15  250K    1% /dev
tmpfs            250K    16  250K    1% /sys/fs/cgroup
shm              250K     1  250K    1% /dev/shm
/dev/root        1.0M 1021K  3.8K  100% /etc/gitlab-runner
tmpfs            250K   470  250K    1% /run/docker.sock
tmpfs            250K     1  250K    1% /proc/acpi
tmpfs            250K     1  250K    1% /sys/firmware

```

# Answer
Well this seems to be a docker issue. It’s keeping a whole lot of dangling volumes.

check if you have some :

```
docker volume ls -qf dangling=true

```

Get rid of them with :

```
docker volume rm $(docker volume ls -qf dangling=true)

```
> 2 votes

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


# Question
Title: How do I run ansible on one host at a time and break on a failure
I've got an Ansible playbook where I want to update a number of flaky devices in sequence. I can use `serial:1`, but I want to stop the playbook altogether if I get a failure so I can fix it before proceeding instead of accumulating errors.

I'd also like to restart the playbook at the same host I stopped on. Currently using Ansible v2.0, but can also switch to a newer version if that sort of a feature is only available in newer versions.

# Answer
> 16 votes
Your playbook will stop when a failure occurs and you're using `serial: 1` according to the documentation.

> By default, Ansible will continue executing actions as long as there are hosts in the group that have not yet failed.

That said there seems to be some confusion in the community over the default behavior, and it seems to have changed--or been buggy--somewhere between 1.8 and 2.1.

So, if `serial: 1` doesn't suffice, use this additional setting:

`max_failure_percentage: 0`

> In some situations, such as with the rolling updates described above, it may be desirable to abort the play when a certain threshold of failures have been reached. To achieve this, as of version 1.3 you can set a maximum failure percentage...

==

As for retrying your playbook, you should be seeing a failure message like this:

`to retry, use: --limit @/home/user/site.retry`

Use that `--limit` flag and on your next execution of `ansible-playbook` and it will continue from where it failed.

Retry files will be created unless you've set `retry_files_enabled = False` in your configuration.

Alternatively, `--start-at-task` may also work.

Sources:

https://github.com/ansible/ansible/issues/1663

https://github.com/ansible/ansible/issues/16241

http://docs.ansible.com/ansible/playbooks\_delegation.html#rolling-update-batch-size

http://docs.ansible.com/ansible/playbooks\_delegation.html#maximum-failure-percentage

http://docs.ansible.com/ansible/intro\_configuration.html#retry-files-enabled

http://docs.ansible.com/ansible/playbooks\_startnstep.html#start-at-task

# Answer
> 2 votes
In 2.5+ (well after the question), there is the debugger which covers most of this: https://docs.ansible.com/ansible/latest/user\_guide/playbooks\_debugger.html

As for one at a time, using "--forks 1" only connects to one system at a time if you want to do it ad-hoc and not every time.

---
Tags: ansible
---