# Question
Title: How to mark a step as failed or unstable on timeout, instead of aborting build?
I have a stage in my Jenkins declarative pipeline that looks like:

```
stage('Step Tests') {
  steps {
    dir('test') {
      catchError(catchInterruptions: true, buildResult: 'FAILURE') {
        timeout(time: 5, unit: 'MINUTES', activity: true) {
          sh "yarn step-tests"
        }
      }
    }
  }
}

```

The timeout activates if my tests don't output anything to the console for 5 minutes, and subsequent stages still execute, which is what I want. However, the build is still marked as aborted instead of failed, which I thought the `buildResult` parameter was for.

How do I catch a timeout and mark the build as unstable or failed, instead of aborted?

# Answer
> 4 votes
I've done something similar to this in the past:

```
stage('Step Tests') {
  steps {
    dir('test') {
      script {
        try {
          timeout(time: 5, unit: 'MINUTES', activity: true) {
            sh "yarn step-tests"
          }
        } catch (Exception e) {
          currentBuild.result = 'FAILURE'
        }
      }
    }
  }
}

```

I haven't tested this code exactly as I wrote it here, so think of this more as a kind of rough sketch rather than polished final product.

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


# Question
Title: What docker command could be issued to check whether a certain local docker image resides in a docker registry?
The docker help was consulted:

```
Usage:  docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

Options:
      --config string      Location of client config files (default "/home/ben/.docker")
  -c, --context string     Name of the context to use to connect to the daemon (overrides DOCKER_HOST env var and default context set with "docker context use")
  -D, --debug              Enable debug mode
  -H, --host list          Daemon socket(s) to connect to
  -l, --log-level string   Set the logging level ("debug"|"info"|"warn"|"error"|"fatal") (default "info")
      --tls                Use TLS; implied by --tlsverify
      --tlscacert string   Trust certs signed only by this CA (default "/home/ben/.docker/ca.pem")
      --tlscert string     Path to TLS certificate file (default "/home/ben/.docker/cert.pem")
      --tlskey string      Path to TLS key file (default "/home/ben/.docker/key.pem")
      --tlsverify          Use TLS and verify the remote
  -v, --version            Print version information and quit

Management Commands:
  builder     Manage builds
  config      Manage Docker configs
  container   Manage containers
  context     Manage contexts
  engine      Manage the docker engine
  image       Manage images
  network     Manage networks
  node        Manage Swarm nodes
  plugin      Manage plugins
  secret      Manage Docker secrets
  service     Manage services
  stack       Manage Docker stacks
  swarm       Manage Swarm
  system      Manage Docker
  trust       Manage trust on Docker images
  volume      Manage volumes

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  build       Build an image from a Dockerfile
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  events      Get real time events from the server
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  history     Show the history of an image
  images      List images
  import      Import the contents from a tarball to create a filesystem image
  info        Display system-wide information
  inspect     Return low-level information on Docker objects
  kill        Kill one or more running containers
  load        Load an image from a tar archive or STDIN
  login       Log in to a Docker registry
  logout      Log out from a Docker registry
  logs        Fetch the logs of a container
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  ps          List containers
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  rmi         Remove one or more images
  run         Run a command in a new container
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  search      Search the Docker Hub for images
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  version     Show the Docker version information
  wait        Block until one or more containers stop, then print their exit codes

Run 'docker COMMAND --help' for more information on a command.

```

The assumption was that there should be a kind of `compare` command. How could one compare a local image with one in a private registry? For example, if nginx:1.17.5 has been pulled locally and resides in a private docker registry then a command should indicated that:

```
docker compare nginx:1.17.5 quay.io/some-org/nginx:1.17.5

```

the command should return:

```
exit 1, the docker image already resides in the docker private registry

```

# Answer
A related Q&A was already created on StackOverflow back in the day.

Several answers simply do a `docker pull image-to-be-checked`. If exit 0, the image exists in a certain registry. If not then the image seems to be omitted. However, if an image is large, e.g. X\>1GB or the (office) internet is slow (due to proxies), this could take a while.

The best option to mitigate this is to use `docker manifest inspect docker-image` as suggested by @morty in conjunction with `DOCKER_CLI_EXPERIMENTAL=enabled` as suggested in a comment by @ChrisDeacy

Although this command works for dockerhub images, it fails if images have to be checked on quay.io:

```
unsupported manifest media type and no default available:
application/vnd.docker.distribution.manifest.v1+prettyjws

```

Therefor I decided to stick to the `docker pull` approach to make the check docker-registry agnostic.

Today I released version 1.0.0 of Docker Image Patrol (DIP). This tool is able to check whether an image exists in a docker-registry. One could check the existence by running:

```
./dip -image nginx -registry quay.io/some.org/ -debug
DEBU[0000] debug: true; image: nginx; registry: quay.io/some.org/
DEBU[0002] Command: docker pull quay.io/some.org/nginx; Output: Using
default tag: latest
Error response from daemon: unauthorized: access to the requested resource
is not authorized
DEBU[0002] 1
Is image: 'nginx' absent in registry: 'quay.io/some.org/'? -> true

```
> 2 votes

---
Tags: docker, docker-registry, dip
---


# Question
Title: JAVA_HOME error in Sonar Scanner for MSBuild
I have set up a sonar scanner MSBuild in Jenkins, but suddenly I'm getting below error.

```
ERROR: JAVA_HOME exists but does not point to a valid Java home
       folder. No "\bin\java.exe" file can be found there.

```

Below is Environment variable for Java Jdk

```
JAVA_HOME=C:\Program Files\Java\jdk-12.0.2

```

How to solve this Issue?

# Answer
I have added **"C:\Program Files\Java\jdk-12.0.2"** as value of **JAVA\_HOME** environment Variable and its working. I don't know exactly this is the correct solution OR Not, but when I have checked **sonar-scanner.bat** file then it's taking %JAVA\_HOME%/bin/java.exe location of Java.
> 1 votes

# Answer
Check if there is a file at C:\Program Files\Java\jdk-12.0.2\bin\java.exe.

If yes then I'd wager there is quoting issue in the SonarQube or the MSBuild task that does not like the space in the path.
Install your java in a path without a space that will likely help

If No, well... you just found your problem !
> 0 votes

---
Tags: jenkins, sonarqube
---


title: AWS CodePipeline frozen on Source

text:
# Question
Title: AWS CodePipeline frozen on Source
I have created a very simple pipeline. I have a git repo in CodeCommit, and the pipeline, when triggered, simply copies the files to an existing S3 folder which is set up to serve a static website. Once I finished creating the pipeline, it started an execution. That execution is sitting on the first step, Source. Its been 50 minutes now and it's still stuck on the Source phase.

Any thoughts as to why this might be happening? I don't see a way to cancel the execution. Are there logs somewhere I can look at to see if there were any errors?

Thanks!

# Answer
There should be a log group available in CloudWatch that you can refer to for information on the error. Also, there is an Execution History tab available on the left hand side that will let you see any errors that are not logged to CloudWatch.

From the sounds of it there may be a problem with the source repo you have selected. It should only take a few seconds to read the repo. Very generally with AWS, many of the problems can be traced to IAM permissions.

You can cancel the execution by selecting 'edit' while it is running.
> 1 votes

---
Tags: amazon-web-services, aws-codepipeline
---


title: Does every docker container has a a OS?

text:
# Question
Title: Does every docker container has a a OS?
Does every container have an OS?

For example, the base docker python image has a default OS in it? I couldn't find any info on Google.

I am in doubt because there are some images made with Python that use the Alpine OS.

# Answer
The python image is based on Debian, Alpine, or Windows Core depending on which tag you select. E.g. if you click on the tag for one of the buster images, you see the Dockerfile with a `FROM buildpack-deps:buster` entry. Going to that repo on Docker Hub you can track it back to `FROM buildpack-deps:buster-scm`, then `FROM buildpack-deps:buster-curl`, and finally `FROM debian:buster`.

It's important to note that these are not really operating systems, they are Linux distributions that have their filesystems packaged into a container filesystem. You are not managing devices or even running the kernel of that operating system, only using their tools (e.g. `apt-get`, `yum`, or `apk`) to manage the contents of the container.

It is possible to have a container without any Linux distribution as it's base. Every image eventually goes back to `FROM scratch` which is a meta image name that indicates an empty filesystem. It's the same as the filesystem after `rm -rf /` or `format c:`, completely empty, no files, no shell to run, no libraries. If you have a statically linked application without any dependencies on the rest of the filesystem, it's possible to deploy with this in a container since the host Linux kernel is what's actually running the application (docker is just a way to applications on the host with isolation (namespaces) and limits (cgroups) preconfigured). An example of this can be found with the Docker doodles. And building on scratch is Google's distroless images which include various prereqs that many need when running in a container without a distribution included.
> 2 votes

# Answer
Your docker image could be without an OS, that's called **distroless** image.

https://docs.docker.com/develop/develop-images/baseimages/

https://github.com/GoogleContainerTools/distroless
> 2 votes

# Answer
By default there is some sort of OS driving almost every container. If you look at the tags tab on the docker python image you asked about you can see the OS that the image uses.

Alpine has become a very popular base for docker containers as it is extremely small. On the same tags tab compare the 3.5 tagged image at 344.58 MB to the 27.34 MB Alpine image.
> 0 votes

---
Tags: docker, containers
---


# Question
Title: Jenkinsfile: Pull image from registry endpoint A, push built image to registry endpoint B
I have two endpoints for my registry (Nexus OSS):

Endpoint 10500 to pull images from.

And Endpoint 10501 to push images to.

(I can go into detail what the idea is and why we think Nexus requires this if need be. I might have Nexus configured wrongly after all. But I am currently thinking it's correct.)

Jenkinsfile has:

```
docker.withRegistry(myRegistry:10501, 'nexus_jenkins_user') {
    docker.build(imageToBuild.getName(), '-f ' + imageToBuild.tag + '.Dockerfile .').push();
}

```

Dockerfile has

```
FROM myRegistry:10500/myNamespace/core:latest
...

```

Jenkins execution reports the following error:

```
docker build -t myNamespace/php:php.7.2 -f php.7.2.Dockerfile .

Sending build context to Docker daemon   80.9kB

...

Step 1/7 : FROM myRegistry:10500/myNamespace/core:latest

Get https://myRegistry:10500/v2/myNamespace/core/manifests/latest: no basic auth credentials

script returned exit code 1

```

This seems obvious as the "withRegistry" directive above has the 10501 endpoint, so there would be no authentication for the 10500 endpoint here.

The challenge: I need to be able to pull the core image (through 10500) but push the finished image to 10501.

What would my Jenkinsfile need to look like to achieve this?

This should theoretically be a common problem for companies utilizing Nexus OSS as they will have two endpoints as well. (Assuming I am correct about Nexus requiring two endpoints if a hosted repo and a proxy repo are being used).

**edit** To provide some help for understanding: If I specify

```
FROM myRegistry:10501/myNamespace/core:latest

```

in my Dockerfile, authentication will work as "withRegistry" and the Dockerfile's FROM directive are set to the same endpoint.

But I want all pulling actions to go through 10500. If, for example, I would use an image from Docker Hub, 10500 would pull it from Hub, cache it and deliver it back to me, where 10501 would not. So 10500 needs to be used for all pulling.

# Answer
Try to chain `withRegistry` like this:

```
docker.withRegistry('https://registry:10500', 'credentials-id') {
    docker.withRegistry('https://registry:10501', 'credentials-id') {
        docker.build(imageToBuild.getName(), '-f ' + imageToBuild.tag + '.Dockerfile .').push();
    }
}

```
> 1 votes

---
Tags: jenkins, jenkinsfile, nexus, docker-registry
---


# Question
Title: OpenVPN - routing public domain over tunnel?
I have an OpenVPN server running in an AWS VPC and I can ping my servers over the tunnel via their private IP, so from that perspective it's working.

Some of our servers have public DNS names `server.example.io` and I'd like OpenVPN clients to be able to reach the servers using their DNS names over the tunnels. For example, one of our servers has a UI and rather than typing the private IP of the server in the browser, they should be able to reach the server over the tunnel using the public domain name.

Is this possible? We are using the OpenVPN Access Server AMI.

# Answer
> 1 votes
Yes, this is possible.

You can create a private DNS zone for `example.io` using AWS route53 in the AWS VPC where your openvpn server is running. Then you can point `server.example.io` to the private IP of the instance. By default in AWS VPC, if a private DNS zone is present, it gets the preference. If the DNS record is not present, then it goes out of VPC for DNS resolution.

So, when your users are connected to the VPN, they all will be in the same network of AWS VPC. Hitting `server.example.io` will resolve to private IP and requests will be routed internally within VPN tunnel.

NOTE: If you are using multiple VPC or your `server.example.io` is in another VPC, you may need to add routes for that in your VPN configuration.

# Answer
> 0 votes
Try to add your public IP to OpenVPN routing/network, if your DNS name is using a static public IP. So OpenVPN will add a route to the client. But you need to add another route that routes from OpenVPN instance to the `server.example.io` to go through internal network.

# Answer
> 0 votes
I think you should use split tunnel in order to let client resolve to the public DNS. Or add the recode on the hosts file of OpenVPN server to let it resolve the record.

---
Tags: vpn
---


# Question
Title: A name for testing software migrated to a new environment against original application
This is more of an english language question - we have various types of tests - unit tests, A/B tests, etc...

Suppose I need to migrate code to a different language, machine, or any other different environment specification, with the definition that it reproduces the original application exactly (bugs included!). I am looking for a name for such a test.

Currently I am using functional testing, but I feel that's to general and am looking for something better. It is also somewhat misleading since the "function" is not the implemented algorithm but reproducing behavior of another application.

@Bruce suggested regression tests, which are a good option we considered, but dropped it since we (and I think most people) use those for actual changes in the original code base (in this question's setting) that may add features, fix bugs etc... Perhaps this is too nit-picky.

# Answer
As mentioned in the question, there is a subtle difference between Regression testing and the situation described here.

To paraphrase Wikipedia:

> Regression testing ... is re-running functional and non-functional tests to ensure that previously developed and tested software still performs after a change. If not, that would be called a regression.

However, a situation is described here where the *functionality* of the code is the same -- since no new features or functionality is added, this is technically not regression testing.

However, what does need to be asserted is the **behaviour** of the code. If run in the same way after the re-implementation, does the code still behave in the same way, beyond still giving the same results (which would be covered in unit testing and functional test).

In "The Practical Test Pyramid", Martin Fowler describes the various types of testing which a well-maintained application could have. Near the apex are "Acceptance Tests", *i.e*

> Do Your Features Work Correctly?

After a re-write, I believe **Acceptance Tests** would be the answer here.

Note - Acceptance tests also include **Operational Acceptance Tests**, described by Wikipedia as:

> Operational acceptance test (OAT) criteria (regardless if using agile, iterative or sequential development) are defined in terms of functional and non-functional requirements; covering key quality attributes of functional stability, portability and reliability.
> 2 votes

---
Tags: terminology, testing
---


# Question
Title: Is there an elegant way to use a Dockerfile argument to tag an image?
I use and argument (`ARG`) in my Dockerfile to download a particular version of an application. I would like to tag my image with that version number. I end up writing something like that:

```
sh$ PHPBB_VERSION=3.2.4 &&
    sudo docker build --build-arg PHPBB_VERSION=${PHPBB_VERSION} \
                      --tag phpbb:${PHPBB_VERSION} - < dockerfiles/bootstrap

```

But I don't find that very elegant since you have to type the *word* `PHPBB_VERSION` no less than four times in this command, with all the possible errors introduced by a typo.

**So, is there a more elegant solution to tag an image with the value of a Dockerfile argument?**

---

FWIW, here is the relevant part of my Dockerfile:

```
sh$ cat dockerfiles/bootstrap
FROM php:7.2-cli

ARG PHPBB_VERSION
RUN echo "You are building phpBB version ${PHPBB_VERSION:?undefined}"
...
RUN wget -nv -O- \
      https://github.com/phpbb/phpbb/archive/release-${PHPBB_VERSION}.tar.gz | \
    tar xzf - --strip-components=1

```

# Answer
> 2 votes
You can use a `Makefile` for this:

```
PHPBB_VERSION := 3.2.4

build:
    docker build \
        --build-arg PHPBB_VERSION=${PHPBB_VERSION} \
        --tag phpbb:${PHPBB_VERSION} - < Dockerfile

```

`Dockerfile`:

```
FROM php:7.2-cli

ARG PHPBB_VERSION

RUN wget -nv -O- https://github.com/phpbb/phpbb/archive/release-${PHPBB_VERSION}.tar.gz | \
    tar xzf - --strip-components=1

```

Then, in a shell: `make build`.

# Answer
> 0 votes
Why would you want to pass ARG as docker tag? Obviously it will at least be two times, first time with --build-arg and second time with --tag. So what you can do is that run this command inside a shell script so that you don't type this command again and again and just change value of $PHPBB\_VETSION and run shell script.

---
Tags: automation, dockerfile
---


# Question
Title: How to enable tag immutability in quay.io?
Elastic Container Registry (ECR) for example supports Tag Immutability (TI). TI implies that docker tags cannot be overwritten if they exist in a docker-registry.

The settings of the organization and the ones from a repository were inspected, but no TI setting was found.

**Questions**

* Does quay support TI?
* If true, how to enable it
* If false, how do you or does your organization prevent that tag overwrite takes place?

# Answer
> 3 votes
At first glance, it seems that tag immutability is not a feature provided by Quay. You can enable "Trust and Signing" in the "settings" of the repo:

> Please note that this will not prevent users from overwriting signed tags without updating signatures. This means that:
>
> * Any tag operations in the UI or client can cause inconsistency
> * Builds should not push to signed tags
>
> We recommend you maintain a strict separation between signed and unsigned tags to avoid any issues with garbage collection.

So, you can sign tags, but you can't prevent them from being updated.

---
Tags: docker, docker-registry, quay.io, dip
---


# Question
Title: Given a blank slate, tool recommendations?
so I have 8 months of DevOps experience previously working as a desktop engineer for two and a half years.Starting a new role in the education sector, recently they brought their IT department which previously worked in different projects/faculties and now they have all been brought together.So this is where I come in to help dictate the application development process by designing and maintaining the infrastructure to build an efficient route to live regardless of the project. So this is essentially a blank slate.

As a very high level overview

So my ideal setup would be creating a production environment for whatever project, replicating the stack and using that as UAT. This would be done through Terraform and Ansible. The Dev estate I am not too sure how this is going to be setup yet but I was thinking about learning docker and k8s to bring up a dev estate.

The way I would look into setting up a CI/CD pipeline using Jenknnis and actioned through Azure DevOps as this is what they use, I would ensure code pushed from the DEV branch is deployed to UAT and tested then deployed to replicate production servers and once tested DNS is switched over to the new servers and the old ones are brought down.

The way how the code is deployed is through building the codebase on the same server Jenkins would be setup on, sending a tar'd file of the code to AWS CodeDeploy to be taken to the next environment.

Through caveats include no changes or access will be allowed on production or UAT servers, any requested changes will be done through terraform and ansible to keep things consistent.

Personally with my limited experience I have used Terraform and ansible and I have felt this provides alot of the work to have that infrastructure as code system in place. At the same time I understand there are tools like chef, puppet and salt which would probably make the job easier but that is where my question is what would you guys want and how would you want to implement it. I should finally mention we seem to be using Azure DevOps as the main tool to setup and manage the pipelines.

# Answer
> 5 votes
This question runs two risks:

1. of being marked as "primarily opinion-based", and
2. its answers might age poorly.

However, I think it's useful to express an opinion, if only for posterity; if and when things change, there may be better answers -- but there will always be blank slates.

I would split the problem up into four sections:

1. Infrastructure
2. Application Building, testing and integration
3. Deployment
4. Monitoring, logging and analytics

Furthermore, let's make this cloud-independent (so, this toolkit should be valid for any or all of AWS, GCE, Azure *etc*, as well as on-prem OpenStack, bare metal cloud (e.g. Packet, etc).

## Infrastructure

Infrastructure components consist of

1. Your environments (pre, prod, integration, testing, etc - however you define them). These should be built with Terraform modules.

1. Each module in its own repo
    2. Consider carefully separation of state, so that you can easily create and destroy components and keep costs down
2. "DevOps" infrastructure. This includes:

1. code repos
    2. CI/CD instances (controller, agent pools, *etc*) - *e.g.* Jenkins master with cloud agent pools.
    3. Deployment runners (see later).
    4. Monitoring, logging and analytics. Again, build these with terraform modules. As a example, have a Terraform module for each type of application or component.
3. Team, messaging and support infrastructure. This is often overlooked, but choosing the right tool for the job on Day 2 is hard. It's better to communicate to the stakeholders how issues and change requests should be made. I would venture a combination of GitHub issues and Slack at the very least.
4. secrets management. You will need to pass around a lot of secrets, if you want to foster collaboration. In order to do this securely, you will need a place to manage them and delegate access to and usage of them.

## Building, testing, integration.

These happen in Jenkins. Each application should contain a subdirectory `.pipeline` with the parts necessary to build it. The part which concerns us here is everything before prod.

I would suggest a pipeline as code approach with a `Jenkinsfile` in the repo declaring the steps for

1. building the application:
2. Testing the application
    1. Unit tests
    2. Functional tests
    3. Integration tests
    4. (Regression tests)
3. Building artifacts
    1. building and signing artifacts
    2. Shipping them to the artifactory, with new version info and other metadata
4. Building instance images (if your application is "installed" in an environment, and not serverless).
5. Enforcing changes to the Infrastructure (terraform plan/apply)
6. Enforcing changes to the deployment configuration (capacity, *etc*)

At the end of this stage, you'll have a properly configured environment (say, pre or prod), an artifact, and an image which you can deploy. If need be, you can run performance tests (with Taurus) or acceptance tests (with cucumber) on them with a job in Jenkins.

## Deployment

I would vote for a hard separation between the previous phase and this one. Deployment should be done with a different tool and the right tool for the job is in my opinion Spinnaker. The configuration for the deployment should be kept in the same repo as the application (so that developers can serve themselves). Deployments should be done on every change to the codebase, declaratively -- Spinnaker has a JSON syntax for this, making it easy to check consistency and correctness of the deployment scenario.

## Monitoring, logging and analytics

As mentioned before, Day 1 is a blank slate, but it is quickly dirtied. The DevOps doesn't stop on Day 2 (ie, when apps are deployed), and it would be wise to plan ahead.

The SRE book gives good advice for instrumenting and monitoring the applications you will be deploying, but this space is very crowded with services and tools claiming solve your monitoring and alerting needs. Again going with the principle that we should be able to deploy anywhere, I would go with a Prometheus for indicator and metric extraction and Grafana for displaying setup. However, you should definitely consider this part wisely.

---

So - the toolkit looks like:

1. Vault for secrets
2. GitHub for code, projects, tasks and issues
3. Slack for communication
4. Terraform for infrastructure
5. Ansible for configuration management
6. Packer for image baking
7. Quay for (docker) image registry
8. Inspec for compliance and correctness of state
9. Cucumber for Acceptance Testing
10. Jenkins for pipeline execution
11. Spinnaker for Deployment
12. Prometheus for metrics Grafana for visualisation and dashboards
13. Taurus (Blazetool) for performance testing

Is this a lot of tools? Yes.

Will you be able to deploy anywhere? Also yes.

Will you need **all** of them? probably not. Also, I've chosen tools which are mostly free to use and open source.

**Also note:** in this scenario, the entire state of all applications can and should be represented as code, and can thus have semantic versioning (or other kind of versioning which makes sense to you). Any changes to that state can be represented by changes to the code, and can thus have good source code management principles applied to it, such as code review, automated testing, *etc*.

# Answer
> 1 votes
I am a big fan of saltstack, mainly because it provides a comprehensive solution regarding the whole server life cycle, unlike ansible which need another tool (such as terraform) to provision vms.

salt + salt-cloud is one very good suite from my opinion.

I do not see any differences regarding the amount of work required by either tool (chef, puppet, ansible, salt) to get a working IAC system in place, this is, of course, according to your language preference. If you're in python then go for salt or ansible, otherwise go check puppet or chef. Do not forget to plug your iac code base to a VCS.

---
Tags: amazon-web-services, ansible, terraform, azure-devops
---


title: Combining CD and GitFlow

text:
# Question
Title: Combining CD and GitFlow
Firstly, I apologize if the title is not descriptive enough or does not describe my problem well enough. I'm struggling to figure out how to describe my issue in brief! It really seems like this should be a problem that has been solved already, but I'm struggling to find the answer. I might be missing something glaringly obvious!!

So - we currently have a Git workflow on GitLab using 3 core branches (master, preprod and develop). We branch features off from develop, then back into develop for initial testing. Merging into develop triggers a pipeline that tests, builds and deploys to a dev server, so that Project Owners can review code in progress. Once signed off, the develop branch gets merged to preprod, which also triggers a pipeline to deploy to our UAT environment for... UAT. Once signed off, preprop gets merged to master which has a manually triggered pipeline to deploy to live.

Bunch of issues with this approach, but the biggest is the bottle neck. If we have a feature in preprod that we don't want to release yet, but another feature is coming up behind it, it's tricky to bypass the feature we don't yet want. So we are considering moving to a different branching strategy such as GitFlow.

Now on to the bit I can't figure out! Currently, in order to deploy a feature to an environment where it can be viewed and tested, we have pipelines triggered by a merge to specific branches. However, I would like to do away with this approach when testing features and hotfixes. Essentially, I need a way to be able to run a pipeline that will run automated tests, build and deploy any branch at any time. So if I am working on FeatureA, I can push that branch to GitLab and deploy it somewhere so that it can be reviewed in isolation from FeatureB that is being worked on by a colleague. Does that make sense? Almost like a dynamic pipeline with a dynamic environment that spins up when needed and gets destroyed again when no longer needed.

If anyone can point me in the right direction here, it would be appreciated!

Should also add that we are starting to use docker on our local machines for development, so a solution that uses docker for spinning up dynamic test environments is not out of the question.

Thanks in advance...

# Answer
**Conflating** *deployment environments* and *branches* often leads to problems like you describe. It does seem like a natural fit though and easily maps to mental model of an ideal solution but, real life is anything but ideal.

Basically, git is not a deployment tool, one should not *clone* to deploy a version but fetch a package (a tarball, zip file, docker container, NPM package etc).

In practice these two concepts are orthogonal. Branching strategies (whichever it may be, gitflow, trunk based etc) is a means to assist developers isolating and sharing their work. It ties naturally to the versioning strategy and is what forms the CI half of your CI/CD system. Here you must force yourself to keep CI (continuous integration) separate from CD (continuous deployment) as you will see if you read-on.

**Deployment** however *consumes* the outcome of *versions* that were created and integrates various parts of the system and makes a whole that is usable, testable.

So if you view your branches and the code therein as a means to assemble a version which the build system will build and package and then store it somewhere. Can be as simple as a network share or FTP site or it could tie in to an existing package manager with a appropriate back end, whatever suits your team best really. This choice will depends greatly on the technology stack you are using and the underlying platforms you will be deploying to (static environments, docker, kubernetes, standalone copy-and-run etc).

Then another set of tasks can pull in any of these versions and assemble a working deployment. Here this works best if your deployment environment are dynamic but it can be made to work with static environments as well. This will form the CD part of your continuous system.

Once decoupled you can spin up an environment that would contain *any* versions that has been previously built.

In term you could even have *multiple* production environments with slight variations of a user interface tweaks and pit them against each-other with techniques like A/B testing and clever load balancing / distribution to end-users.

Going back to your particular situation it will simplify your gitflow back to a more traditional master/develop permanent branches and a set of features/hotfix and release branches.

Using semver you can keep official versions strictly for master merges (from release branches or hotfix branches) and pre-release versions for all other branches. for your pre-release branches simply add a -SOMETHING where something is the name of the branch for example and possibly a timestamp to differentiate successive deployments.

for example,

* release branches would get the x.y.0-RCi (i th release candidate). x.y is the version that will be released where the -RC is simply dropped when merged in master. 0 as the patch because release branches are used for new features and product evolution
* hotfix branch follow the same principle as the release branch except the patch number is set to a non-zero value.
* development branch could get x.y.z-dev.timestamp
* feature branch x.y.z-JiraID-timestamp. Where JiraID is the ticket number of the system you use to track new features (like Jira, Bugzilla, etc)

I propose semantic versioning here because I am familiar with it but the same broad principle of segregating branches through versioning can be applied with pretty much any versioning scheme.

Nowhere in the source control do you see anything that relates to deployment environment. Only your versioning strategy is what links them, they are otherwise completely isolated and independent.

Your devs will feel more comfortable in this new environment and your deployments will feel less constrained and awkward.

Hope this helps
> 3 votes

---
Tags: docker, gitlab, continuous-deployment, cicd
---


# Question
Title: GCP - Can't create a tpu on europe-west1
I'my trying to create a tpu for my vm instance from this tutorial but get this error message:

```
ERROR: (gcloud.compute.tpus.create) PERMISSION_DENIED: Location europe-west1-b is not found or access is unauthorized.

```

I have enabled all of the access the vm can have but i still have this error.

# Answer
> 2 votes
According to "TPU types and zones" TPUs are only available in a very limited set of regions, namely:

* **Europe, Middle East and Africa**
    + europe-west4-a (Eemshaven, Netherlands)
* **Americas**
    + us-central1-a, b, c and f (Council Bluffs, Iowa, USA)
* **Asia-Pacific**
    + asia-east1-c (Changhua County, Taiwan)

*Note: not every SKU is available in each region, so double check the above page when planning your deployments.*

In addition to specifying a valid zone, you will need to make sure the TPU API is enabled, and your account has the relevant IAM permissions: Cloud TPU\TPU Admin.

At the moment TPUs are predominantly designed for centralised data processing rather than close-to-edge processing. Hence the somewhat limited number of locations TPUs are available within.

---
Tags: google-cloud-platform, gcp, google-compute-engine
---


# Question
Title: How to recreate GCP Preemptible VMs behind LB before they expire?
I created preemptible instances in a managed instance group behind LB, I specified the preemptible option in the instance template.

Because GCP Compute Engine always terminates preemptible instances after they run for 24 hours, I need a way to launch new preemptible VMs before they goes down.

Is GCP Compute Engine launch new preemptible VMs before the current ones goes down when target size specified by the autoscaler ?

Maybe need to replace the Preemptible VMs several hours before they going down,

I am not sure what is the best way to do it, maybe with termination notices.

Basically what I need is always to keep on Preemptible VMs behind the LB.

What is the best way to implement this?

# Answer
Strictly you can't do this with a single preemptable virtual machine as you only get a 30 second grace period. While the majority of calls to the Google Compute Engine API would create a new device within 30 seconds, there are cases when this would fail due to network latency or temporary outage.

What you can do is create an Instance Group of Preemptible Virtual Machines with a minimum of two instances, the probability of GCE killing both at precisely the same time is quite low, and once GCE destroys one a new one will be created to bring the IG instance count back up to two.
> 1 votes

---
Tags: gcp
---


# Question
Title: How to pass variables between build/deploy tasks in a TaskGroup in VSTS 16.131.28601.4
I have a multi-configuration web application I'm using parallel deployments, leveraging Task Groups for reusing my deployment code.

I've been using Powershell tasks and the `##vso[task.setvariable variable]` but those only are readable by other tasks (particularly non-PowerShell tasks) if they correspond to top-level variables at the Build/Release level. Variables that are only local to the task-group.

Basically, the behavior described in Issue #3116

Does anybody have a better workaround for this issue besides binding all your variables right to the root with identical names?

# Answer
I'm not sure my approach is any "better". However, what I have done in the past was to use Table Storage or Cosmos DB to store the key-value pairs that needed to be persisted between each stage.

The general schema was:

* **Key**: *buildNum-variableName*
* **Value**: *variableValue*

I then created various wrappers for the SDK to access from PowerShell and MSBuild, this also enabled chaining multiple builds together to create a CI/CD pipeline.
> 1 votes

---
Tags: azure-pipelines, powershell
---


# Question
Title: Service for hosting native JavaScript ES modules
We will be serving static javascript ES modules and looking for an all-in-one hosting platform that is easy to use.

* It must provide CORS headers (ES modules enable CORS by default)
* HTTP/2 support is mandatory
* Ability to set very long caching headers (content never changes)
* Mirrored all across the world for fast transfers with low latency.
* Pushing a new version should be a simple oneliner.

# Answer
> 1 votes
Have you considered CDNjs.com:

* It supports CORS headers, it is dedicated to JavaScript after all.
* It supports HTTP/2 as well as SPDY.
* The cache duration is 355 days, which is probably plenty long enough.
* Cloudflare is used as the CDN, they provide it to cdnjs.org for free.

Adding your library is a bit more than a one-liner unfortunately as you need to submit a pull request to their GitHub repository. You will also need to have a certain popularity requirement:

> For the new library request issue, please make sure it's not a personal project, we have a basic requirement for the popularity, like 200 stars on GitHub or 800 downloads/month on npm registry.

---
Tags: http, cdn, cors
---


# Question
Title: What are the best practices for anti-virus / anti-malware when using containers?
One of the SOC 2 controls is apparently around ensuring antivirus/anti-spam/anti-malware is running on production servers. I've been googling to see if there are any recommendation/best practices for this in the container world. I'm not sure if it's a good practice to run AV on the host OS? Some materials I found in my Googling seem to indicate that if you do something like that, you would need to exclude the files used by the container to avoid locking up the container. Which sounds like it would defeat the purpose.

In our particular case, we're running on GKE using Google's pre-made container OS. Anyone have experience with this?

# Answer
This is an area where you will need to talk directly to and potentially help educate your auditors. What you have to remember is they are responsible for ensuring that **adequate controls** are applied, not specifically that "Production Servers have Endpoint Protection"; Anti-virus and Anti-malware are among some of the most basic controls applied to technology.

As a bit of a starter for ten, you could consider the following:

* **Secure Software Development Lifecycle (S-SDLC)**: In traditional environments, developer and administrator workstations would have Anti-virus and Anti-malware products installed, therefore any code that a developer creates and an administrator deploys will have been subject to routine automatic scans. It's easy to forget that the same controls need to be applied to our automated pipelines, one option would be to scan both source code and artefacts with ClamAV or a commercial antivirus product.
    + Trivy \- not anti-virus but does offer vulnerability scanning so controls against malware entering via an upstream 3rd party.
    + Anchore
    + Clair
* One of the best practices for container development is **reducing the attack surface area** by maintaining a hardened and minimal base image. For example, removing any non-essential components such as shells, network utilities, and text editors. Utilising a pre-hardened image such as the CIS Images and applying
* If you manage your own Kubernetes masters and nodes then you should consider the attack vectors against that host **use endpoint protection to mitigate**, although if you use Hosted Kubernetes, i.e. Google Kubernetes Engine or Azure Kubernetes Service, you need to jump through some hoops to get it working. As you've probably already seen there is some basic advice on what to avoid, and you need to understand the limitations of the scanning engine - namely it can't see *into* containers.
* Equally, masters and nodes should be **leveraging SELinux** as a Mandatory Access Control security mechanism and generally have the relevant CIS or STIG benchmarks applied to them.
* There are a small but growing number of "hot" **container endpoint protection tools**, it's fairly nascent so explore your options carefully:
* **Integrity Checking** is very important as whilst it isn't anti-malware per se, it is a component part of most anti-malware packages so might just give you the signal you need to know that something is wrong:
* Finally, remember "Infrastructure as Code" if you can destroy all of your infrastructures and rebuild it from scratch automatically it makes it **significantly easier** to recover from a compromise. This is a tough sell with an auditor.

If you implement everything above, you will quickly find you run into information overload - this is where a Security Information and Event Management (SIEM) tool can help bring everything together in a single pane of glass.
> 12 votes

---
Tags: kubernetes, containers, security
---


# Question
Title: Provide customers with access to Azure Container Registry
I'm using Azure Container Registry for private Docker images. I want to let around 500 customers pull images and use the Docker V2 HTTP API to read metadata.

Service Principals are one way to go about this. My plan is to create a single Service Principal, and grant it the `AcrPull` role on the Azure Container Registry. I'd then create a time-limited password credential for each customer.

The customer flow would be something like:

1. Authenticate using the Service Principal client secret, to get an Azure AD Access Token
2. Hit the Azure Container Registry OAuth token endpoint, swapping the AAD Access Token for an ACR Access Token and Refresh Token
3. You can now use `docker login` using the ACR Refresh Token as the password
4. You can also access the ACR HTTP API using the ACR token

These steps are not carried out manually, but by automatic scripts running on customer's servers.

After much research (Microsoft's docs here are not great), this approach seems to work as expected.

Is using a Service Principal the "idiomatic" way to approach this? Are there any benefits to creating an individual Service Principal for each customer?

# Answer
> 1 votes
There is a balancing act here between the simplicity and maintainability of your solution, and how auditable creating separate service principals or users for each of your external customers. I suspect only you can actually decide which is the best practice in your specific legal and regulatory situation.

On the **side of having a single Service Principal** with multiple passwords, there is a minimal amount of configuration required and other than perhaps limitations imposed by Microsoft on the number of authentications per second or the number of passwords that can be created for a Service Principal it should work quite nicely. The downside is your resource logs won't give you any information about who pulls images, you will have some logs about issuing a short-lived password, but you can't prove that's related to a `docker login`.

On the side of **creating a Service Principal per client** means your resource logs will tell you who pulls images. However, you will need to automate the creation and maintenance of those Service Principals to account for clients joining and leaving.

***Why*** does it matter? it may not for you, however if one of your customer's machines was compromised and the images leaked onto the internet you may want to hold one of the customers to account.

---
Tags: azure, security, architecture, permissions
---


# Question
Title: GKE - GPU nvidia - cuda drivers dont work
I have setup a kubernetes node with a Nvidia Tesla k80 and followed this tutorial to try to run a pytorch docker image with Nvidia drivers and CUDA drivers working.

I have managed to install the nvidia daemonsets and I can now see the following pods:

```
nvidia-driver-installer-gmvgt
nvidia-gpu-device-plugin-lmj84

```

The problem is that even while using the recommended image `nvidia/cuda:10.0-runtime-ubuntu18.04` I still can't find the Nvidia drivers inside my pod:

```
root@pod-name-5f6f776c77-87qgq:/app# ls /usr/local/
bin  cuda  cuda-10.0  etc  games  include  lib  man  sbin  share  src

```

But the tutorial mentions:

> CUDA libraries and debug utilities are made available inside the container at `/usr/local/nvidia/lib64` and `/usr/local/nvidia/bin`, respectively.

I have also tried to test if CUDA was working through `torch.cuda.is_available()` but I get False as a return value.

Many thanks in advance for your help.

# Answer
> 1 votes
Ok so i finally made it work.

It is mandatory set a ressource limit to access the nvidia driver, which is weird considering either way my pod was on the right node with the nvidia drivers installed..

---
Tags: kubernetes, google-cloud-platform, google-compute-engine
---


# Question
Title: Terraform creating single SG but multiple CIDR blocks
I am trying to use Terraform to create a single security group that will allow traffic for mongo on port `27017` from all my private subnets that are stored in a variable. My issue is I am unsure how this would work since I only want one SG but the foreach creates multiple - at least it did before with subnets

my variable

```
variable "subnet_numbers_private" {
  description = "Useless info"
  default     = {
    "us-east-1a" = 1
    "us-east-1b" = 2
    "us-east-1c" = 3
  }
}

```

my security group resource

```
resource "aws_security_group" "mongo" {
  for_each = var.subnet_numbers_private
  name        = "Mongo"
  description = "Allow mongo traffic"
  vpc_id      = aws_vpc.Main_VPC.id

  ingress {
    from_port   = 27017
    to_port     = 27017
    protocol    = "tcp"
    cidr_blocks = [cidrsubnet(aws_vpc.Main_VPC.cidr_block, 8, each.value)]
  }

  tags = {
    Name = "Mongo-${each.key}"
  }
}

```

Currently this just provides an error that doesn't mean much to me as I don't know TF 0.12 well enough

```
Because aws_security_group.mongo has "for_each" set, its attributes must be
accessed on specific instances.

For example, to correlate with indices of a referring resource, use:
    aws_security_group.mongo[each.key]

```

# Answer
Figured out the answer, fourtinately for me I had missed the example in the blog post about terraform 0.12 linked below

Here is my final (working how I want) security group

```
resource "aws_security_group" "mongo" {
  name        = "Mongo"
  description = "Allow mongo traffic"
  vpc_id      = aws_vpc.Main_VPC.id

  ingress {
    from_port   = 27017
    to_port     = 27017
    protocol    = "tcp"
    cidr_blocks = [
      for num in var.private_subnet_numbers:
      cidrsubnet(aws_vpc.Main_VPC.cidr_block, 8, num)
    ]
  }

  tags = {
    Name = "Mongo"
  }
}

```

Link to blog post about foreach - https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each/
> 1 votes

---
Tags: amazon-web-services, terraform
---


# Question
Title: Should I implement Devops on a small project. Is it too big for it?
Just like the headline suggested, is it too big to implement devOps on a private application I'm solely developing. I mean creating the pipelines, continuous testing and continuous deployment.

And if I must do it for learning purpose which is the main intent. Is it fun to carry out? How's the learning curve and won't I waste too much of my development time? I'm curious enough to go down the rabbit hole.

# Answer
> 3 votes
The question you need to answer is "would I find it entertaining to set up a CI/CD environment if not to learn from it then just for the fun of it?". You *may* not *need* it at this point in your project or it *may* benefit you. That I can't tell from the limited information. Linux started as a personal project, too. I set up something similar for my own pet project and I've gotta admit I feel a little bit proud every time I compile and deploy with a single click.

Should you implement it? That's for you to decide.

---
Tags: continuous-integration, continuous-deployment, continuous-delivery
---


title: Jenkins upgrading and plugins ordering

text:
# Question
Title: Jenkins upgrading and plugins ordering
I have Jenkins `2.89` installed with many outdated plugins as well. What is the best path for upgrading both the plugins and Jenkins itself? Should one proceed the other?

I am leaning toward upgrading the plugins first and in batches to limit the risk. The system is being backed up in its entirety in case things go sideways. I would like to avoid that if at all possible though.

Update: I was able to upgrade to 2.138 without it breaking anything.

# Answer
> 2 votes
I can only speak from personal experience rather than best practices, but in our company we'll **make a duplicate jenkins instance, then upgrade that**. We do main upgrade first, then plugins second, then run testing to make sure our core jobs still work. If all is good, we'll **then upgrade the real jenkins during off-hours**.

We have 90+ jobs so testing them all is unrealistic - we made an effort to identify 8-10 jobs that span 90% of our use cases and run those on the standup jenkins to affirm everything is healthy first.

I'd highly advise doing something similar if you're using your jenkins in production scenarios. You never know what might break - we had one upgrade where a bug spun up 150+ aws ec2 instances in ~10mins instead of the 3 jenkins actually needed... another time all our unit and e2e testing of our code base broke because it turned out one of the output parser plugins had upgraded to become incompatible with our output format. We've even had our Bitbucket integration go sour and stop kicking off jobs on every push.

Sometimes upgrading all plugins at once can cause confusion - we had one scenario where something broke and finding the cause was difficult because it could have come from one of two different plugins. We ended up spinning up two additional jenkins and upgrading either plugin to identify which was the cause. In general though, upgrading everything at once will pretty quickly show its flaws with a little testing.

No matter what you decide, take a backup first!

# Answer
> 2 votes
Not to take away from @vaporwave\_sailor or @Alex, answers, but to add to..

The basic answer is **you MUST upgrade all the compatible plugins you can, then the war, then the newer plugins.** All plugins depend on a minimum Jenkins version and the Update Centre will give you different information back.

**A further clarification, especially if migrating from \< 2.263.4 to \> 2.277.1 and many breaking UI changes and tables-divs-regaression (Dashboard):** You should ensure your plugins are at the latest version, compatible with the existing Jenkins core version before starting. So, it's plugins, war, plugins.

If you don't upgrade often, use the LTS version. **READ the Upgrade Guide. READ the Changelog. Re-READ the Upgrade Guide**. Do the same for all your **core plugins**. There are **significant changes**, especially around security which may require modifications on your part. Many previously bundled are no longer bundled. Long unsupported plugins may have better alternatives or contain security issues you should be aware of. Behaviors and settings may change.

---

The following are NOT exact steps, rather things to do in the process. Descriptive, not prescriptive.

Consider installing the Jenkins Configuration as Code (JCasC) plugin to your existing installation first. That will generally let you export almost your entire configuration and simply reload into a new instance. Much easier, but does not handle plugins. For now rip a solution from docker/install\_plugins.sh for local use; see Preinstalling Plugins.

Take a backup of your existing Jenkins and install install a "Dev" location. Validate your upgrade there before applying to Prod. ALWAYS. (Also, regularly backup your Prod anyway).

Split the backup in two parts, the system configuration and the jobs. Jobs are in ${JENKINS\_HOME}/jobs. The system configuration includes (in `${JENKINS_HOME}`), `./*.xml ./secret.key* ./secrets ./security-tokens ./nodes` , possibly others.

Back to the plugins for a minute. I agree w/adding them in segments:

* Authentication plugins
* Presentation plugins (eg:Active-directory, credentials)
* SCM plugins (eg: Git)
* Adminstrative plugins (eg: greenballs, windows-slaves)
* Tools plugins (eg: ant, maven-plugin)
* Pipeline plugins (eg: workflow-aggregator, Blue-Ocean, K8s)

All the above are "Global plugins, with Configurations"

* Finally, job step plugins; these are job specific.

If using the install\_plugins.sh approach, you only need worry about the highest level plugin as it will pull the dependencies. If you install blueocean, it installs some 25 plugins. Just specify the first and you get the rest. Bear in mind, install\_plugins.sh is dynamic, in that it gets the available dependencies at the time. So, we decide on the top list, manage that, run once to get the complete list, then read the validated explicit list into the Prod instance (manage the short one, use the complete one, save both). We manage 55 top-level plugins, but there are 160 installed including all dependencies in the full list.

This groovy script will get you your existing plugins:

```
Jenkins.instance.pluginManager.plugins.sort(false) { a, b -> a.getShortName().toLowerCase() <=> b.getShortName().toLowerCase()}.each { plugin ->
   println "${plugin.getShortName()}:${plugin.getVersion()} | ${plugin.getDisplayName()} "
}
   // the following may also be useful
   // println "+++ ${plugin.getDependants()}"
   // println "... ${plugin.getDependencies()"

```

In the Dev instance, install the war, install the plugins, create a file `${JENKINS_HOME}/init.groovy`, add the line: `Hudson.instance.doQuietDown();`. That lets your system start without letting any jobs start. That way you can examine the system logs w/o panicking or getting confused. Look at everything before `INFO: Jenkins is fully up and running`.

Now, you can install the system configurations, but not the `./jobs` and not the `./nodes`. Start it up and **check the logs** for information, warning alerts and errors.

You might even want to start with your existing war version and existing plugins and basic config, fire that up and save the logs as references. Then, using the UI, upgrade the war, then restart, then the plugins using the UI, then restart, then check and save the logs as references.

If using JCasC, you may go w/a slim install of the configurations,then import your JCasC configurations. JCasC usage here.

\*NB: You will notice one major change is more plugins are moving to their own xml configuration instead of adding to the master config.xml. There are many plugins especially that say this configuration is NOT backward compatible. You would have to restore the old config when "downgrading" (correct language - start again from step 1)

Only once your core system starts fine, then I would add the jobs (with `QuietDown()` in place ), no nodes and in QuiteDown. Start up again, examine logs for errors, upgrade warnings, etc. Deal w/those. Many plugins will change their data format, hence the many warnings you see, and the "Manage Old Data". IF you're truly paranoid, you may even write a little groovy script that finds all your jobs and re-saves them. While Jenkins knows of the configuration changes, it does not actually change and update the plugin references in the jobs until the job is run or saved (if you need a script, ask a separate question).

Shutdown, delete the jobs directory (this is your DEV instance, so you are OK).

Startup up again and create a small set of validation jobs. These validate all the steps of your real jobs but without impacting them. They are the "test cases" @Alex refers to. We use "sampleApps" of different flavors we have and jobs that cover all the steps. We have test jobs that just get on a node, dump the environment, jobs that clone a repo and build (in the flavors), one that does the whole cycle: clone, build analyze, test, deploy, as well as pipeline jobs (phased). You can now add the nodes configuration and startup and execute those. **They are your validation**. If they work, then you are as prepared as you can be. You can now export the JCasC configuration as well.

Now, delete the entire Dev instance and **REDO** using only your finalized configuration and steps as you documented. Did everything work as expected? Run JCasC again, did they match?

Now you can apply the same finalized configuration to your Prod. Shutdown Production and TAKE ANOTHER BACKUP. I'd add the `QuietDown()` first to Prod.

Finally, consider taking advantage of some new "System Properties". You can now set locations outside of ${JENKINS\_HOME} for `jenkins.model.Jenkins.buildsDir` (ps: sym-links in builds are now optional) and `jenkins.model.Jenkins.workspacesDir`, removing useless data from the ${JENKINS\_HOME}. Your backups will be smaller and simpler and your system performacne may improve! You'll also want to set `jenkins.install.runSetupWizard` to false.

Remember, this is descriptive, not preservative. Tailor to your own needs and risk tolerance.

# Answer
> 1 votes
I've gained some experience from f-n up Jenkins a lot of times, here is order I kept sticking to and it saved me a lot of time:

1. Upgrade Jenkins itself (if needed)
2. Upgrade Auth plugins (i.e. Github org auth)
3. Upgrade plugins related to most important pipelines/projects (ssh-agents, ansible, k8s, docker, whatever you guys are using)
4. Upgrade currently used but not mission-critical plugins (blue-ocean etc.)
5. Upgrade the rest of plugins

I had 'after-upgrade' pipeline that would start build of few most important projects, it was running after each step.

What helped me a lot as well is taking snapshots in between of upgrades so I could do rollback easily and do not start from the beginning which could be time consuming. Obviously I do not recommend doing in-place upgrades, I always go for 1:1 copy and working on copy and then I just change DNS record.

---
Tags: jenkins, jenkins-plugins, upgrade
---


# Question
Title: Jenkins does not seem to be running inside a container
I am getting an error while running the Jenkins file tp build and push the docker image into docker hub .

you can reveiw my code github : https://github.com/iakshaykr/webapp.git (using jenkins\_pipe branch not master branch )

Jenkinsfile :

```
pipeline {
    environment {
        registry= "iakshaykr/webapp"
        registryCredential= 'dockerhub'
    }

    agent { dockerfile true }

    stages {
        stage('Bilding image') {
            steps {
             script {
                 docker.build registry + ":$BUILD_NUMBER"
              }
            }
        }
    }
}

```

---

Below solution valid on Error code 127.If you are getting any other error code let me know .

After doing R&D finally got the solution.

1st test your code in Jenkins using shell command which is in build option :

cmd : docker build . -t newimage

2nd test : use the docker plugin (Plugin name :CloudBees Docker Build and Publish)

3rd test : use the build option : pipeline scm

code : https://github.com/iakshaykr/webapp.git Use : jenkins\_pipe branch

Please test the thing ,in case any error please reply back .

Note : First setup/add the credentials for dockerhub in your jenkins for authentication .

# Answer
> 1 votes
If you simply google "jenkins does not seem to be running inside a container", you will see that it's only an informational message. Surely, it could be worded better, but it's pretty much harmless.

---
Tags: docker, jenkins, jenkins-pipeline, dockerfile, jenkinsfile
---


# Question
Title: How do I enter a multi line variable in Terraform?
It's for the public key variable for testing lab enviroments in my variables.tf file I tried

`<<EOF
the string
EOF`

but terraform dosn't seem to like that

# Answer
Terraform variable type constraints separate "primitive" types from "complex" types. These primitive types include strings:

> A primitive type is a simple type that isn't made from any other types. All primitive types in Terraform are represented by a type keyword. The available primitive types are:
>
> * string: a sequence of Unicode characters representing some text, such as "hello".
> * number: a numeric value. The number type can represent both whole numbers like 15 and fractional values such as 6.283185.
> * bool: either true or false. bool values can be used in conditional logic.

So, simply declaring the variable as a string, with the linebreaks in it would suffice.
> 2 votes

---
Tags: terraform
---


# Question
Title: Jenkins Deployment Issue - Unrecognized SSL Message, Plaintext Connection?
I've been attempting to **build** and **deploy** a local copy of a repository, whilst still providing the remote depository to Jenkins, to a Tomcat version 9 server.

I have both Jenkins and Tomcat running on different ports.

I did get a handful of successful builds and deployments but I found that when I would visit my successful deployments via the Tomcat server, any page other than the home page of the build had a 404 error.

I thought it was because the dependencies were absent because it was using Jenkins workspace instead of the local repository on my device, so after switching directories, I relieved the following error:

```
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  10.906 s
[INFO] Finished at: 2019-11-07T14:11:59-05:00
[INFO] ------------------------------------------------------------------------
[DeployPublisher][INFO] Attempting to deploy 1 war file(s)
[DeployPublisher][INFO] Deploying C:\Users\(myusername)\Projects\ier_ui\target\derui.war to container Tomcat 9.x Remote with context derui
ERROR: Build step failed with exception
org.codehaus.cargo.container.ContainerException: Failed to redeploy [C:\Users\(myusername)\Projects\ier_ui\target\derui.war]
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:188)
    at hudson.plugins.deploy.CargoContainerAdapter.deploy(CargoContainerAdapter.java:81)
    at hudson.plugins.deploy.CargoContainerAdapter$DeployCallable.invoke(CargoContainerAdapter.java:167)
    at hudson.plugins.deploy.CargoContainerAdapter$DeployCallable.invoke(CargoContainerAdapter.java:136)
    at hudson.FilePath.act(FilePath.java:1078)
    at hudson.FilePath.act(FilePath.java:1061)
    at hudson.plugins.deploy.CargoContainerAdapter.redeployFile(CargoContainerAdapter.java:133)
    at hudson.plugins.deploy.PasswordProtectedAdapterCargo.redeployFile(PasswordProtectedAdapterCargo.java:95)
    at hudson.plugins.deploy.DeployPublisher.perform(DeployPublisher.java:113)
    at hudson.tasks.BuildStepCompatibilityLayer.perform(BuildStepCompatibilityLayer.java:79)
    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:45)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:741)
    at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:690)
    at hudson.model.Build$BuildExecution.post2(Build.java:186)
    at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:635)
    at hudson.model.Run.execute(Run.java:1840)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:429)
Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at sun.security.ssl.InputRecord.handleUnknownRecord(Unknown Source)
    at sun.security.ssl.InputRecord.read(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:567)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.list(TomcatManager.java:882)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.getStatus(TomcatManager.java:895)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:169)
    ... 18 more
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
    at sun.security.ssl.InputRecord.handleUnknownRecord(Unknown Source)
    at sun.security.ssl.InputRecord.read(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(Unknown Source)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:567)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.list(TomcatManager.java:882)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.getStatus(TomcatManager.java:895)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:169)
    at hudson.plugins.deploy.CargoContainerAdapter.deploy(CargoContainerAdapter.java:81)
    at hudson.plugins.deploy.CargoContainerAdapter$DeployCallable.invoke(CargoContainerAdapter.java:167)
    at hudson.plugins.deploy.CargoContainerAdapter$DeployCallable.invoke(CargoContainerAdapter.java:136)
    at hudson.FilePath.act(FilePath.java:1078)
    at hudson.FilePath.act(FilePath.java:1061)
    at hudson.plugins.deploy.CargoContainerAdapter.redeployFile(CargoContainerAdapter.java:133)
    at hudson.plugins.deploy.PasswordProtectedAdapterCargo.redeployFile(PasswordProtectedAdapterCargo.java:95)
    at hudson.plugins.deploy.DeployPublisher.perform(DeployPublisher.java:113)
    at hudson.tasks.BuildStepCompatibilityLayer.perform(BuildStepCompatibilityLayer.java:79)
    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:45)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:741)
    at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:690)
    at hudson.model.Build$BuildExecution.post2(Build.java:186)
    at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:635)
    at hudson.model.Run.execute(Run.java:1840)
    at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:429)
Build step 'Deploy war/ear to a container' marked build as failure
Finished: FAILURE

```

After struggling with this error for a couple days, I decided to completely delete and reinstall Jenkins and started from scratch. The reason I did this is because I wanted to get a successful build and start working from Jenkins Worksapce directory again, instead of my local repo, but even after the reinstall I have been getting the error which I thought was unique to me changing the workspace location.

Any ideas what this might be due to? Perhaps access issues to the apache-tomcat folder? But even then, it was working before. Your insights would be highly appreciated.

Just to be clear, I do provide the correct credentials for Tomcat and my git repository platform. This include `manager-gui` and `manager-script` roles.

# Answer
I realize it's because the link for tomcat I was deploying to was: `https://localhost:portNo`, instead of simply, `http://localhost:portNo`
> 1 votes

---
Tags: jenkins, git, deployment, ssl, tomcat
---


# Question
Title: How to enforce policies for manifests in Kubernetes?
I have built a self-service platform based on Kubernetes, where we create namespaces for each team and allow them to 'do whatever they want within the namespace' (we set resource limits so no one can kill the whole cluster).

However, now I want to implement some kind of standard across the organization. For example, I want every PodSpec to define its own resource limits, and I want every resource to have a label that specifies what application it belongs to.

Is there a mechanism that will allow the API server to check the manifests being applied against a set of rules, and if it fails the check the manifest is rejected.

For example, the following manifest would be rejected because it has neither a label nor are resource limits set.

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

```

But the following manifest would succeed because it satisfies all the rules:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  **labels:**
    **app: foobar**
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        **resources:**
          **limits:**
            **cpu: "1"**
          **requests:**
            **cpu: "0.5"**

```

# Answer
> 1 votes
I would be inclined to implement the Open Policy Agent as this will give you the ability to define a policy similar to this:

```
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sContainerLimits
metadata:
  name: container-must-have-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    cpu: "200m"
    memory: "1Gi"

```

OPA will enforce any policy you defined via an Admission Controller, beware though it's very powerful and I have bricked clusters by not thinking through the options carefully.

---
Tags: kubernetes
---


# Question
Title: Issue installing NPM packages on Jenkins
I have a Jenkins build I am using for a Vue.js application. I am trying to install all dependancies as part of the pipeline and am running into some issues. I've included the below output as well as the npm install part of my pipeline.

It looks like a python issue to me however I don't think I'm using python unless vue uses it under the hood

error from below build step

```
+ npm install
> node-sass@4.12.0 install /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass
> node scripts/install.js

Downloading binary from https://github.com/sass/node-sass/releases/download/v4.12.0/linux-x64-79_binding.node
Cannot download "https://github.com/sass/node-sass/releases/download/v4.12.0/linux-x64-79_binding.node":

HTTP error 404 Not Found

Hint: If github.com is not accessible in your location
      try setting a proxy via HTTP_PROXY, e.g.

      export HTTP_PROXY=http://example.com:1234

or configure npm proxy via

      npm config set proxy http://example.com:8080

> node-sass@4.12.0 postinstall /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass
> node scripts/build.js

Building: /var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/UI/bin/node /var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library=
gyp info it worked if it ends with ok
gyp verb cli [
gyp verb cli   '/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/UI/bin/node',
gyp verb cli   '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/bin/node-gyp.js',
gyp verb cli   'rebuild',
gyp verb cli   '--verbose',
gyp verb cli   '--libsass_ext=',
gyp verb cli   '--libsass_cflags=',
gyp verb cli   '--libsass_ldflags=',
gyp verb cli   '--libsass_library='
gyp verb cli ]
gyp info using node-gyp@3.8.0
gyp info using node@13.1.0 | linux | x64
gyp verb command rebuild []
gyp verb command clean []
gyp verb clean removing "build" directory
gyp verb command configure []
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb `which` failed Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:158:21)
gyp verb `which` failed  python2 Error: not found: python2
gyp verb `which` failed     at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:158:21) {
gyp verb `which` failed   stack: 'Error: not found: python2\n' +
gyp verb `which` failed     '    at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)\n' +
gyp verb `which` failed     '    at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)\n' +
gyp verb `which` failed     '    at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5\n' +
gyp verb `which` failed     '    at FSReqCallback.oncomplete (fs.js:158:21)',
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp verb check python checking for Python executable "python" in the PATH
gyp verb `which` failed Error: not found: python
gyp verb `which` failed     at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:158:21)
gyp verb `which` failed  python Error: not found: python
gyp verb `which` failed     at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)
gyp verb `which` failed     at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)
gyp verb `which` failed     at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5
gyp verb `which` failed     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5
gyp verb `which` failed     at FSReqCallback.oncomplete (fs.js:158:21) {
gyp verb `which` failed   stack: 'Error: not found: python\n' +
gyp verb `which` failed     '    at getNotFoundError (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:13:12)\n' +
gyp verb `which` failed     '    at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:19)\n' +
gyp verb `which` failed     '    at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5\n' +
gyp verb `which` failed     '    at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5\n' +
gyp verb `which` failed     '    at FSReqCallback.oncomplete (fs.js:158:21)',
gyp verb `which` failed   code: 'ENOENT'
gyp verb `which` failed }
gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
gyp ERR! stack     at PythonFinder.failNoPython (/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/lib/configure.js:484:19)
gyp ERR! stack     at PythonFinder.<anonymous> (/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/lib/configure.js:406:16)
gyp ERR! stack     at F (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:68:16)
gyp ERR! stack     at E (/var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:80:29)
gyp ERR! stack     at /var/lib/jenkins/workspace/Deploy UI/node_modules/which/which.js:89:16
gyp ERR! stack     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/index.js:42:5
gyp ERR! stack     at /var/lib/jenkins/workspace/Deploy UI/node_modules/isexe/mode.js:8:5
gyp ERR! stack     at FSReqCallback.oncomplete (fs.js:158:21)
gyp ERR! System Linux 4.15.0-1052-aws
gyp ERR! command "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/UI/bin/node" "/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass
gyp ERR! node -v v13.1.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
Build failed with error code: 1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.12.0 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the node-sass@4.12.0 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /var/lib/jenkins/workspace/Deploy UI/.npm/_logs/2019-11-12T02_15_01_035Z-debug.log

```

package.json

```
"dependencies": {
    "@agametov/vueditor": "^0.4.1",
    "@chenfengyuan/vue-countdown": "^1.1.2",
    "apexcharts": "^3.8.3",
    "axios": "^0.19.0",
    "bootstrap": "^4.3.1",
    "bootstrap-social": "^5.1.1",
    "bootstrap-vue": "^2.0.0-rc.27",
    "chart.js": "^2.8.0",
    "flag-icon-css": "^3.3.0",
    "ionicons": "^4.6.2",
    "moment": "^2.24.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.1.0",
    "simple-line-icons": "^2.4.1",
    "v-autocomplete": "^1.8.2",
    "vue": "^2.6.10",
    "vue-apexcharts": "^1.4.0",
    "vue-bootstrap-datetimepicker": "^5.0.1",
    "vue-chartjs": "^3.4.2",
    "vue-custom-scrollbar": "^1.1.0",
    "vue-event-calendar": "^1.5.2",
    "vue-full-calendar": "^2.7.0",
    "vue-good-table": "^2.17.4",
    "vue-hljs": "^1.1.2",
    "vue-input-tag": "^2.0.6",
    "vue-ins-progress-bar": "^1.0.0",
    "vue-maskedinput": "^0.1.3",
    "vue-moment": "^4.0.0",
    "vue-notification": "^1.3.16",
    "vue-nvd3": "^1.0.0",
    "vue-pop-colorpicker": "^1.0.2",
    "vue-router": "^3.0.7",
    "vue-select": "^3.1.0",
    "vue-slider-component": "^3.0.33",
    "vue-sparklines": "^0.1.9",
    "vue-stripe-elements-plus": "^0.3.2",
    "vue-sweetalert2": "^2.1.1",
    "vue2-google-maps": "^0.10.7",
    "vuejs-datepicker": "^1.6.2"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.9.2",
    "@vue/cli-plugin-eslint": "^3.9.2",
    "@vue/cli-service": "^3.9.3",
    "vue-template-compiler": "^2.6.10"
  },

```

my pipeline code

```
stage('Build') {
        steps {
            nodejs(nodeJSInstallationName: 'UI') {
               sh "npm install && npm install --only=dev && npm run build --${params.buildenv}"
            }
        }
    }

```

EDIT \** installed python via the apt repo and ran into a bigger (longer) error message. I can't include here as too long (tried already)

A bunch of lines about node openssl like the below

`gyp verb extracted file from tarball include/node/openssl/aes.h`

```
gyp verb tarball done parsing tarball
gyp verb check download content checksum, need to download `SHASUMS256.txt`...
gyp verb checksum url https://nodejs.org/download/release/v13.1.0/SHASUMS256.txt
gyp http GET https://nodejs.org/download/release/v13.1.0/SHASUMS256.txt
gyp http 200 https://nodejs.org/download/release/v13.1.0/SHASUMS256.txt
gyp verb checksum data {"node-v13.1.0-aix-ppc64.tar.gz":"5faec026afe9052f277402500236dd9ec4d58e0e8de93f66989fc337c65e33c8","node-v13.1.0-darwin-x64.tar.gz":"6501c1bcf2babb5b9c81dcff8b52021f726da8f6ee28df1637acade1a16c7d39","node-v13.1.0-darwin-x64.tar.xz":"b918bdc6ca5726084a737c926744cdaecde624ba39ac8aaed889f296007a5094","node-v13.1.0-headers.tar.gz":"577785216f5a4097a9108fd05f3117556f0954f0a03a26cfbfd1ce7af94587d4","node-v13.1.0-headers.tar.xz":"73ec6759903137d3e22806e745777cb7cda3150f0d81c5ba13e7599c2be03d32","node-v13.1.0-linux-arm64.tar.gz":"dd36c7846f7713b6e55baf0b6ab7882c18b129d83a3d0f7ef62790d181461d22","node-v13.1.0-linux-arm64.tar.xz":"646d597e6b0dc400429e46b703a5135c77bd71e653ea4c8254d0b60c17b6ec1d","node-v13.1.0-linux-armv7l.tar.gz":"88450bc38dac0be15c9bd09bfccf4ce79f1911930f37658c730c151b26c5aa97","node-v13.1.0-linux-armv7l.tar.xz":"e15601106fbd9ed75a4642eab91bb3f3ddab8b5821e886bdb070c014d9ab9af2","node-v13.1.0-linux-ppc64le.tar.gz":"0c804f0671bcdada9be66e4ca844c08f897357fbf2426be8cc326d20e6362833","node-v13.1.0-linux-ppc64le.tar.xz":"561dbaa36db7dcb4fff378e110b4ddd29d918754e73449208899fbfb9f3ce1ae","node-v13.1.0-linux-s390x.tar.gz":"24c29e917230d9cc510ba764ff6ef57bcc816520c146b47dce3ed4aeb3f7d333","node-v13.1.0-linux-s390x.tar.xz":"a3229a795ee8bda15396701badd31d695d9a6f487a730c73022305c98522767a","node-v13.1.0-linux-x64.tar.gz":"490e998198e152450e79bb65178813ce0c81708954697f91cfd82537acfcb588","node-v13.1.0-linux-x64.tar.xz":"2eecb5a4b7975c3b406bee36b12c9a29e8bedf9553c88cad310b8f076db00881","node-v13.1.0.pkg":"3b6abd2a5f7a5778bbe5363ea222910b19674648eb2b3d734d9ee751ec29da71","node-v13.1.0-sunos-x64.tar.gz":"8e17a613950018e27f34f7268e01cbb385777189961ccf386f7d0d05883687b3","node-v13.1.0-sunos-x64.tar.xz":"e9dd61b7f537b98a6656c0e03766997aa712bf3d40e7cb08ba4019e942846739","node-v13.1.0.tar.gz":"df640a2f151f788d02dc25c91d80fffe06b4c3c72fbdee07ab9abd7c6879d6cd","node-v13.1.0.tar.xz":"d42c056cbd33b35836b0f5cfb2c56712b965ea76e188ef79af492614cf14cb68","node-v13.1.0-win-x64.7z":"8f242259fa929f759f06bb1cf399df3b81061eb1ce5ccaa9d206dc157fcf93fc","node-v13.1.0-win-x64.zip":"d735e97bdeb7b74551b9d165c708a3fdea4dbb3801a65e70f6d6ae3539d48a03","node-v13.1.0-win-x86.7z":"c4ecf16dd147956c9335b547fdfb1b0eb1c333c1a1722843b45ba04b9fee17fe","node-v13.1.0-win-x86.zip":"81af54ba9e852073ac975aa0955da1efb4b2ea6ef213eb3ce90f3b22a82555d8","node-v13.1.0-x64.msi":"22ec0be47b0f3f5f163f82e18c01df456921f39b756ee4a828534264b06d0fe6","node-v13.1.0-x86.msi":"7f56fa7350eaf0da6d33b24578a281e8d759a9344e5c8ea851ea541eaebb94fe","win-x64/node.exe":"5c3b0006330a08743363ebf26ccdf1618ab0269f50756088b6e5257d7a32c5a1","win-x64/node.lib":"aa183bbe6f7a2b63395ff83ac6f687274bafbc1e64be2e6e5bb600dc1e5c7bea","win-x64/node_pdb.7z":"7e4bc02444eea52b90d15d1985789aa10efa5b058a6550aac389db3eba42a4b7","win-x64/node_pdb.zip":"ae389590498393e57379d462b3d8d6c2639afcf04d6c279f99b8e2122b98b94e","win-x86/node.exe":"20fb3aa33b88628c533e59fec344db02683434cfbd91d70a36e3a0c3f865ed03","win-x86/node.lib":"caa896eb2249fdf32ed3dda1c7bdb8250b8dbdf6f5498b10a4dec91f541d2d11","win-x86/node_pdb.7z":"e2301d3ae38b01fecceb8111955568a741183de87d05c88a6499abfca1e913b1","win-x86/node_pdb.zip":"5d9cc82ef9f2165f08ad4057b23c90154bf6a334ed7f9d3b5757003f70f49108"}
gyp verb download contents checksum {"node-v13.1.0-headers.tar.gz":"577785216f5a4097a9108fd05f3117556f0954f0a03a26cfbfd1ce7af94587d4"}
gyp verb validating download checksum for node-v13.1.0-headers.tar.gz (577785216f5a4097a9108fd05f3117556f0954f0a03a26cfbfd1ce7af94587d4 == 577785216f5a4097a9108fd05f3117556f0954f0a03a26cfbfd1ce7af94587d4)
gyp verb get node dir target node version installed: 13.1.0
gyp verb build dir attempting to create "build" dir: /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build
gyp verb build dir "build" dir needed to be created? /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build
gyp verb build/config.gypi creating config file
gyp verb build/config.gypi writing out config file: /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build/config.gypi
gyp verb config.gypi checking for gypi file: /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/config.gypi
gyp verb common.gypi checking for gypi file: /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/common.gypi
gyp verb gyp gyp format was not specified; forcing "make"
gyp info spawn /usr/bin/python2
gyp info spawn args [
gyp info spawn args   '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0',
gyp info spawn args   '-Dnode_gyp_dir=/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/<(target_arch)/node.lib',
gyp info spawn args   '-Dmodule_root_dir=/var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass',
gyp info spawn args   '-Dnode_engine=v8',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.'
gyp info spawn args ]
gyp verb command build []
gyp verb build type Release
gyp verb architecture x64
gyp verb node dev dir /var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0
gyp verb `which` succeeded for `make` /usr/bin/make
gyp info spawn make
gyp info spawn args [ 'V=1', 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build'
  g++ '-DNODE_GYP_MODULE_NAME=libsass' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DLIBSASS_VERSION="3.5.4"' -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/include/node -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/src -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/deps/openssl/config -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/deps/openssl/openssl/include -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/deps/uv/include -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/deps/zlib -I/var/lib/jenkins/workspace/Deploy UI/.node-gyp/13.1.0/deps/v8/include -I../src/libsass/include  -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -std=gnu++1y -std=c++0x -fexceptions -frtti -MMD -MF ./Release/.deps/Release/obj.target/libsass/src/libsass/src/ast.o.d.raw   -c -o Release/obj.target/libsass/src/libsass/src/ast.o ../src/libsass/src/ast.cpp
g++: error: UI/.node-gyp/13.1.0/include/node: No such file or directory
g++: error: UI/.node-gyp/13.1.0/src: No such file or directory
g++: error: UI/.node-gyp/13.1.0/deps/openssl/config: No such file or directory
g++: error: UI/.node-gyp/13.1.0/deps/openssl/openssl/include: No such file or directory
g++: error: UI/.node-gyp/13.1.0/deps/uv/include: No such file or directory
g++: error: UI/.node-gyp/13.1.0/deps/zlib: No such file or directory
g++: error: UI/.node-gyp/13.1.0/deps/v8/include: No such file or directory
src/libsass.target.mk:158: recipe for target 'Release/obj.target/libsass/src/libsass/src/ast.o' failed
make: *** [Release/obj.target/libsass/src/libsass/src/ast.o] Error 1
make: Leaving directory '/var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/lib/build.js:262:23)
gyp ERR! stack     at ChildProcess.emit (events.js:210:5)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:272:12)
gyp ERR! System Linux 4.15.0-1052-aws
gyp ERR! command "/var/lib/jenkins/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/UI/bin/node" "/var/lib/jenkins/workspace/Deploy UI/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /var/lib/jenkins/workspace/Deploy UI/node_modules/node-sass
gyp ERR! node -v v13.1.0
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
Build failed with error code: 1
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.12.0 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the node-sass@4.12.0 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above

```

# Answer
> 1 votes
There are likely a multitude of issues that could be the root cause, as a starter for ten I would look at the following:

1. Is the ownership and permissions on the `node_modules` directory correct, i.e. does your Jenkins user have the permission to write to all of the files and directories in the folder. This is a common problem if you have multiple users involved in the build process - less common on a dedicated build server.
2. Do you have all of the dependencies for building the packages, for example:

* you have a dependency on `"node-sass": "^4.12.0"`
        + which has a dependency on node-gyp
            - which has dependencies on Python, `make` and a C/C++ toolchain like `gcc`

There is a much longer troubleshooting guide on the node-sass GitHub which may be of help, although you may well find that even if you get node-sass to work you will ened up with another package failing because of missing dependencies.

---
Tags: jenkins, npm
---


# Question
Title: How to authenticate, with azure devops services, using SAML via on premise standalone java application?
We have a network where azure DevOps services can be used by logging in via SAML. There is an independent java application in that same network.

Can anyone please point out a way that this java application can get authenticated to Azure DevOps services via SAML, without any manual intervention?

PS: I've explored a lot of blogs but I couldn't find what I need specifically. Closest I got, was to register my java application as a AD tenant, but in our use case this can't be done.

Is there any other alternative? Please suggest.

# Answer
There is a fairly sizable range of authentication options, based upon what you have said you are looking for a non-interactive login which rules out some options, and leaves the following:

* Device Profile \- probably not ideal for you given you would need to find a way to this in Java as the examples are few and far between and mostly written in C#.
* TFS Application \- again not ideal given you would need to either find someone who has written a 3rd party client library for Java or write one yourself.
* Azure DevOps Extension - while you could write an Azure DevOps extension, and use that to access Azure DevOps it's a lot of work and potentially would expose security issues.

Given that we have probably ruled out non-interactive login to Azure DevOps you could also explore one of the two following options:

* **Interactive Logins** \- is there an option in your environment from forcing the user to authenticate with Azure DevOps using OAuth then capture the token for non-interactive use? This is quite a common pattern with GitHub, GitLab and Bitbucket.
* **Personal Access Tokens** \- mostly this would be abusing a feature of Azure DevOps as these are designed for users not applications, although it could work in your constrained environment.
* **Non-interactive Login using your Identity Provider** \- you haven't detailed who your Identity Provider is, but it is possible it supports authentication using Client Certificates, Shared Secrets, etc. which would give you a SAML token which could be exchanged for an Azure DevOps Access token.

Hope those help.
> 0 votes

---
Tags: azure-devops, azure, tfs
---