How do I add Pulumi to my GitHub Codespaces / VSCode .NET devcontainer? - visual-studio-code

I want to develop and deploy IaC with Pulumi .NET / C# from a VS Code .devcontainer. How can I add this capability to the environment?

I included the build container steps from https://github.com/pulumi/pulumi-docker-containers/blob/main/docker/dotnet/Dockerfile into .devcontainer/Dockerfile:
ARG DOTNET_VARIANT="3.1"
ARG PULUMI_VERSION=latest
ARG INSTALL_NODE="true"
ARG NODE_VERSION="lts/*"
# --------------------------------------------------------------------------------
FROM debian:11-slim AS builder
RUN apt-get update -y && \
apt-get upgrade -y && \
apt-get install -y \
curl \
build-essential \
git
RUN if [ "$PULUMI_VERSION" = "latest" ]; then \
curl -fsSL https://get.pulumi.com/ | bash; \
else \
curl -fsSL https://get.pulumi.com/ | bash -s -- --version $PULUMI_VERSION ; \
fi
# --------------------------------------------------------------------------------
FROM mcr.microsoft.com/vscode/devcontainers/dotnetcore:0-${DOTNET_VARIANT}
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
COPY --from=builder /root/.pulumi/bin/pulumi /pulumi/bin/pulumi
COPY --from=builder /root/.pulumi/bin/*-dotnet* /pulumi/bin/
ENV PATH "/pulumi/bin:${PATH}"
and I control the process with this .devcontainer/devcontainer.json:
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.203.0/containers/alpine
{
"name": "C# (.NET)",
"build": {
"dockerfile": "Dockerfile",
"args": {
"DOTNET_VARIANT": "3.1",
"PULUMI_VERSION": "latest",
"INSTALL_NODE": "true",
"NODE_VERSION": "lts/*"
}
},
"features": {
"azure-cli": "latest"
},
// Set *default* container specific settings.json values on container create.
"settings": {},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-dotnettools.csharp"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Replace when using a ptrace-based debugger like C++, Go, and Rust
// "runArgs": [ "--init", "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],
"runArgs": [
"--init"
],
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
be aware that the Rebuild will take a while and that you probably have to reload the devcontainer once it indicates success in the GitHub Codespaces: Details.
After that pulumi login and e.g. pulumi new azure-csharp should work on the container.

You can spin up a codespace, and configure the devcontainer from within the codespace.
I did it just now,
Access the Command Palette (Shift + Command + P / Ctrl + Shift + P), then >start typing "dev container". Select Codespaces: Add Development Container >Configuration Files....
just follow this guide
from within following this guide - https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-project-for-codespaces
I was inspired by the builder container approach for DOTNET mentioned in this thread, and here is how I added pulumi to my GO codespace dockerfile.
Dockerfile
ARG GO_VARIANT="1"
ARG PULUMI_VERSION=latest
FROM debian:11-slim AS builder
RUN apt-get update -y && \
apt-get upgrade -y && \
apt-get install -y \
curl \
build-essential \
git
RUN if [ "$PULUMI_VERSION" = "latest" ]; then \
curl -fsSL https://get.pulumi.com/ | bash; \
else \
curl -fsSL https://get.pulumi.com/ | bash -s -- --version $PULUMI_VERSION ; \
fi
FROM mcr.microsoft.com/vscode/devcontainers/go:0-${GO_VARIANT}
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
ARG NODE_VERSION="none"
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
COPY --from=builder /root/.pulumi/bin/pulumi /pulumi/bin/pulumi
COPY --from=builder /root/.pulumi/bin/*-go* /pulumi/bin/
ENV PATH "/pulumi/bin:${PATH}"
ENV GOOS "linux"
ENV GOARCH "amd64"
Snippit of code from devcontainer.json
"args": {
... //redacted for clarity
"GO_VARIANT": "1.18",
}
)
I can login with azure, pulumi and pulumi up is also working.
Full example here
https://github.com/DevOpsJava/solution-using-secret
I fixed an issue with pulumi up, which turned out to be a resource problem regarding memory. Switched codespace from 2 to 4 cores, which also doubled the memory to 8GB.

Related

Deploying Jenkins using skaffold via GitHub Action Runner

I am deploying Jenkins Using GitHub Action Runner using Skaffold.
While the Skaffold is installed over the default image of GitHub Runner
The pod is restarting due to crash loop back off error and causing it to restart.
I am not sure why it is happening.
When I am deploying runner over Google Kubernetes Engine my runner is failing because of following error:
'''A runner exists with the same name
√ Successfully replaced the runner
√ Runner connection is good
# Runner settings
√ Settings Saved.
√ Connected to GitHub
Current runner version: '2.294.0'
2022-12-01 06:03:57Z: Listening for Jobs
Runner update in progress, do not shutdown runner.
Downloading 2.299.1 runner
Waiting for current job finish running.
Generate and execute update script.
Runner will exit shortly for update, should be back online within 10 seconds.
Runner update process finished.
Runner listener exit because of updating, re-launch runner in 5 seconds
Restarting runner...
/home/docker/actions-runner/run-helper.sh: line 20: /home/docker/actions-runner/bin/Runner.Listener: No such file or directory
Exiting with unknown error code: 127
Exiting runner...
'''
Following is the Dockerfile used for runner :
'''FROM ubuntu:22.04
#instalIng skaffold
RUN apt-get update -y && apt-get upgrade -y sudo
RUN apt-get install -y curl
RUN curl -LO https://storage.googleapis.com/skaffold/releases/v2.0.2/skaffold-linux-amd64 \
&& sudo chmod +x skaffold-linux-amd64 \
&& sudo mv skaffold-linux-amd64 /usr/local/bin/skaffold
#install
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y && apt-get upgrade -y && useradd -m docker
RUN apt-get install -y curl jq build-essential libssl-dev libffi-dev python3 python3-venv python3-dev ca-certificates gnupg2 iputils-ping software-properties-common apt-transport-https lsb-release git zip unzip postgresql-client python3-pip npm
RUN ln -sf /usr/bin/python3 /usr/bin/python
# set the github runner version
ARG RUNNER_VERSION="2.294.0"
# cd into the user directory, download and unzip the github actions runner
RUN cd /home/docker && mkdir actions-runner && cd actions-runner \
&& curl -O -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
&& tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
# install some additional dependencies
RUN chown -R docker ~docker && /home/docker/actions-runner/bin/installdependencies.sh
#Docker
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" && \
apt-get update && \
apt-get -y install docker-ce
# Downloading gcloud package
RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz
# Installing the package
RUN mkdir -p /usr/local/gcloud \
&& tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
&& /usr/local/gcloud/google-cloud-sdk/install.sh
# Adding the package path to local
ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin
#Install Kubectl
RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl" \
&& chmod +x ./kubectl \
&& mv ./kubectl /usr/local/bin/kubectl
# copy over the start.sh script
COPY start.sh start.sh
# make the script executable
RUN chmod +x start.sh && mv start.sh /home/docker
# since the config and run script for actions are not allowed to be run by root,
# set the user to "docker" so all subsequent commands are run as the docker user
USER docker
# set the entrypoint to the start.sh script
ENTRYPOINT ["/home/docker/start.sh"] '''
Below is the startup script :
#!/bin/bash
SNAPTIME=`date '+%Y%m%d%H%M%S'`
echo "Started $SNAPTIME"
ORGANIZATION=$ORGANIZATION
ACCESS_TOKEN=`cat /etc/pat/pat`
GH_PROJECT=$GH_PROJECT
RUNNER_NAME="${RUNNER_NAME:-RUN$SNAPTIME}"
RUNNER_LABELS="${RUNNER_LABELS:-simple}"
REG_TOKEN=$(curl -sX POST -H "Authorization: token ${ACCESS_TOKEN}" https://api.github.com/repos/${ORGANIZATION}/$GH_PROJECT/actions/runners/registration-token | jq .token --raw-output)
# gcloud auth activate-service-account --key-file=${GOOGLE_APPLICATION_CREDENTIALS}
cd /home/docker/actions-runner
./config.sh --name $RUNNER_NAME --labels ${RUNNER_LABELS} --url https://github.com/${ORGANIZATION}/${GH_PROJECT} --unattended --replace --token ${REG_TOKEN}
cleanup() {
echo "Removing runner..."
./config.sh remove --unattended --token ${REG_TOKEN}
}
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM
./run.sh & wait $!
The pod is restarting whenever the load is coming into it:
runner-automation-dev-docker-595f48c7dc-k2wbz 1/2 CrashLoopBackOff 7 (67s ago) 18m
I am not sure what exactly is causing this issue.

Prepare coursier artifact for offline use inside container

I have an sbt project producing my artifact xyz.
I would like to put it along with all its dependencies in the docker container so it can be used using
coursier launch --mode offline xyz
The important part is that preparation should take use of local cursier cache from host.
I tried
executing sbt publishLocal,
then resolving my artifact dependencies (cursier resolve xyz),
then preparing to directories - local & cache - by copying resolved artifact into them
then copying those directories into docker container (as coursier cache and ivy local respectively).
This didn't work because coursier doesn't list .pom and .xml files in its output. I tried copying whole directories (abc/1.0.0 instead of abc/1.0.0/some.jar) but AFAIK there is no reliable way to know how many folders up one has to go because maven and ivy have different dir structures.
while my usecase is not quite identical to yours -- I figure I'd write up my findings and maybe my solution works for you as well!
here's my sample dockerfile, I used this to install scalafmt in an offline-compatible way
FROM ubuntu:jammy
RUN : \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* # */ stackoverflow highlighting bug
ARG CS=v2.1.0-RC4
ARG CS_SHA256=176e92e08ab292531aa0c4993dbc9f2c99dec79578752f3b9285f54f306db572
ARG JDK_SHA256=aef49cc7aa606de2044302e757fa94c8e144818e93487081c4fd319ca858134b
ENV PATH=/opt/coursier/bin:$PATH
RUN : \
&& curl --location --silent --output /tmp/cs.gz "https://github.com/coursier/coursier/releases/download/${CS}/cs-x86_64-pc-linux.gz" \
&& echo "${CS_SHA256} /tmp/cs.gz" | sha256sum --check \
&& curl --location --silent --output /tmp/jdk.tgz "https://download.java.net/openjdk/jdk17/ri/openjdk-17+35_linux-x64_bin.tar.gz" \
&& echo "${JDK_SHA256} /tmp/jdk.tgz" | sha256sum --check \
&& mkdir -p /opt/coursier \
&& tar --strip-components=1 -C /opt/coursier -xf /tmp/jdk.tgz \
&& gunzip /tmp/cs.gz \
&& mv /tmp/cs /opt/coursier/bin \
&& chmod +x /opt/coursier/bin/cs \
&& rm /tmp/jdk.tgz
ENV COURSIER_CACHE=/opt/.cs-cache
RUN : \
&& cs fetch scalafmt:3.6.1 \
&& cs install scalafmt:3.6.1 --dir /opt/wd/bin
the key to offline execution for me was to use cs fetch and set COURSIER_CACHE
here's the offline execution succeeding:
$ docker run --net=none --rm -ti cs /opt/wd/bin/scalafmt --version
scalafmt 3.6.1

How do I add the experimental language server to a devcontainer for vscode?

I'm doing a pretty basic devcontainer for terraform work in VSCode on Windows. Every time I start it up or rebuild the container for use, it prompts me to install the experimental language server where I end up picking the latest tag for it (v0.0.9).
I have the following setting configured in my default settings.json file
{
"terraform.languageServer.enabled": true
}
and my .devcontainer/devcontainer.json is taken and minimized from the Azure terraform container.
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/docker-existing-dockerfile
{
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
"name": "DevOps Projects IaC With Terraform",
"context": "..",
"dockerFile": "Dockerfile",
"runArgs": [
"-v", "${env:USERPROFILE}/.ssh:/root/.ssh-localhost:ro",
"-v", "${env:USERPROFILE}/.aws:/root/.aws:ro"
],
"postCreateCommand": "mkdir -p ~/.ssh && cp -r ~/.ssh-localhost/* ~/.ssh && chmod 700 ~/.ssh && chmod 600 ~/.ssh/*",
// Add the IDs of any extensions you want installed in the array below.
"extensions": ["mauve.terraform"]
}
How do I include the experimental language server into my build/devcontainer config?
I've been trying to figure out the answer to this for a while, for my own purposes. I decided today that I was going to figure it out and I believe I have it working (installing terraform, the LSP and the AWS provider) using
# Terraform, LSP and AWS Provider
ENV TERRAFORM_VERSION=0.12.24
ENV TERRAFORM_LSP_VERSION=0.0.10
ENV TERRAFORM_AWS_PROVIDER_VERSION=2.59.0
RUN wget -c https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
&& unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
&& mv terraform /usr/local/bin \
&& wget -c https://releases.hashicorp.com/terraform-provider-aws/${TERRAFORM_AWS_PROVIDER_VERSION}/terraform-provider-aws_${TERRAFORM_AWS_PROVIDER_VERSION}_linux_amd64.zip \
&& unzip terraform-provider-aws_${TERRAFORM_AWS_PROVIDER_VERSION}_linux_amd64.zip \
&& mv terraform-provider-aws_v${TERRAFORM_AWS_PROVIDER_VERSION}* /usr/local/bin \
&& echo "provider \"aws\" {}" >> /usr/local/bin/providers.tf \
&& wget -c https://github.com/juliosueiras/terraform-lsp/releases/download/v${TERRAFORM_LSP_VERSION}/terraform-lsp_${TERRAFORM_LSP_VERSION}_linux_amd64.tar.gz -O - | tar -zx \
&& mv terraform-lsp /usr/local/bin \
&& rm terraform*.zip
because I'm installing this to /usr/local/bin and I'm creating a containerUser which wouldn't have access to install these components, I needed to add the following to the settings section of my devcontainer.json
"terraform.indexing": {
"enabled": false
},
"terraform.languageServer": {
"enabled": true,
"installCommonProviders": false,
"pathToBinary": "/usr/local/bin"
},
Obviously you need to make adjustments if you want other providers, or to install it elsewhere, or different versions of terraform, the LSP or the AWS provider, but they all should be simple changes.
The latest releases can be found at the following links:
Terraform
Terraform LSP
AWS Provider
Other Providers

How to mount devcontainer to $HOME

I'm trying to setup a devcontainer which mounts the workspace in VSCode to /home/node and puts everything in the project into $HOME in docker.
the reason why I want to do this is so when the project mounts into docker I have everything contained in the individual projects I'm working on.
I get an error, when running with this configuration.
anyone have suggestions on how to achieve this?
this is my devcontainer.json
// For format details, see https://aka.ms/vscode-remote/devcontainer.json or the definition README at
// https://github.com/microsoft/vscode-dev-containers/tree/master/containers/typescript-node-lts
{
"name": "Node.js (latest LTS) & TypeScript",
"dockerFile": "Dockerfile",
// Use 'settings' to set *default* container specific settings.json values on container create.
// You can edit these settings after create using File > Preferences > Settings > Remote.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
// Uncomment the next line if you want to publish any ports.
"appPort": [3000, 8000, 6006],
// Uncomment the next line to run commands after the container is created.
"postCreateCommand": "mkdir ~/.ssh && cp .ssh/* ~/.ssh && chmod 600 ~/.ssh/id_rsa",
// Uncomment the next line to use a non-root user. On Linux, this will prevent
// new files getting created as root, but you may need to update the USER_UID
// and USER_GID in .devcontainer/Dockerfile to match your user if not 1000.
"runArgs": ["-u", "node"],
// Add the IDs of extensions you want installed when the container is created in the array below.
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"Orta.vscode-jest"
],
"workspaceMount": "src=/home/node,dst=/home/node,type=volume,volume-driver=local",
"workspaceFolder": "/home/node"
}
and my Dockerfile
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
FROM node:lts
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
# The node image comes with a base non-root 'node' user which this Dockerfile
# gives sudo access. However, for Linux, this user's GID/UID must match your local
# user UID/GID to avoid permission issues with bind mounts. Update USER_UID / USER_GID
# if yours is not 1000. See https://aka.ms/vscode-remote/containers/non-root-user.
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Configure apt and install packages
RUN apt-get update \
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
#
# Verify git and needed tools are installed
&& apt-get -y install git iproute2 procps \
#
# Remove outdated yarn from /opt and install via package
# so it can be easily updated via apt-get upgrade yarn
&& rm -rf /opt/yarn-* \
&& rm -f /usr/local/bin/yarn \
&& rm -f /usr/local/bin/yarnpkg \
&& apt-get install -y curl apt-transport-https lsb-release \
&& curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \
&& echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends yarn \
#
# Install tools globally
&& npm install -g jest prettier eslint typescript localtunnel \
#
# [Optional] Update a non-root user to match UID/GID - see https://aka.ms/vscode-remote/containers/non-root-user.
&& if [ "$USER_GID" != "1000" ]; then groupmod node --gid $USER_GID; fi \
&& if [ "$USER_UID" != "1000" ]; then usermod --uid $USER_UID node; fi \
# [Optional] Add add sudo support for non-root user
&& apt-get install -y sudo \
&& echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/node \
&& chmod 0440 /etc/sudoers.d/node \
#
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# Switch back to dialog for any ad-hoc use of apt-get
ENV DEBIAN_FRONTEND=
not 100% sure, as you did not share the error you encoutered, but
it might be because you use:
"workspaceMount": "src=/home/node,dst=/home/node,type=volume,volume-driver=local",
when it's not a 'volume' in your case. The type should be 'bind' here.
see here for more information.

Can I use pg_dumpall withtout installing postgresQL?

I tried in my docker container(from alpine3.6) to run command to install pg_dumpall I've seen in the web:
apk update && apk upgrade
and then
apk add --no-cache postgresql-client-common
and finally
apk add --no-cache postgresql-client
Only the last of the two installs I tried worked (the one without common) but I still won't have pg_dump or pg_dumpall in my binaries.
Try to
apk add postgresql-client
You can see all included binaries of this package in this link. This package has a pg_dumpall
https://pkgs.alpinelinux.org/contents?file=&path=&name=postgresql-client&branch=v3.8&repo=main&arch=aarch64
Each alpine version has different postgresql-client. For myself I wrote those logic:
ARG PSQL_VERSION=0
RUN if [ "$PSQL_VERSION" = "13" ]; then \
echo "http://dl-cdn.alpinelinux.org/alpine/v3.14/main" >> /etc/apk/repositories; \
elif [ "$PSQL_VERSION" = "12" ]; then \
echo "http://dl-cdn.alpinelinux.org/alpine/v3.12/main" >> /etc/apk/repositories; \
elif [ "$PSQL_VERSION" = "11" ]; then \
echo "http://dl-cdn.alpinelinux.org/alpine/v3.10/main" >> /etc/apk/repositories; \
elif [ "$PSQL_VERSION" = "10" ]; then \
echo "http://dl-cdn.alpinelinux.org/alpine/v3.8/main" >> /etc/apk/repositories; \
fi
RUN apk update
RUN apk --no-cache add postgresql-client
And now you can pass needed client version:
docker build -t backuper --build-arg PSQL_VERSION=12 .