Merge branch 'trigger-nixos-rebuild-from-deploymentagent' into 'poc-integration'
Trigger nixos rebuild from deploymentagent See merge request infektweb/glv5/hetzner-cloud-environment!1
This commit is contained in:
commit
3a336c2101
31
.gitlab-ci.yml
Normal file
31
.gitlab-ci.yml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- release
|
||||||
|
|
||||||
|
variables:
|
||||||
|
BUILD_IMAGE: registry.gitlab.com/infektweb/glv5/hetzner-cloud-environment/deploymentagent:$CI_COMMIT_REF_NAME
|
||||||
|
RELEASE_IMAGE: registry.gitlab.com/infektweb/glv5/hetzner-cloud-environment/deploymentagent:latest
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
tags: [shell]
|
||||||
|
script:
|
||||||
|
- cd deploymentagent/src/deploymentagent && docker build --build-arg CI_JOB_TOKEN=$CI_JOB_TOKEN --pull -t $BUILD_IMAGE .
|
||||||
|
- docker push $BUILD_IMAGE
|
||||||
|
|
||||||
|
release:
|
||||||
|
stage: release
|
||||||
|
tags: [shell]
|
||||||
|
script:
|
||||||
|
- docker pull $BUILD_IMAGE
|
||||||
|
- docker tag $BUILD_IMAGE $RELEASE_IMAGE
|
||||||
|
- docker push $RELEASE_IMAGE
|
||||||
|
only:
|
||||||
|
- master
|
@ -4,17 +4,21 @@ WORKDIR /go/src/app
|
|||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN apk add --no-cache openssh git && \
|
RUN apk add --no-cache openssh git
|
||||||
git config --global url."git@gitlab.com:".insteadOf "https://gitlab.com/" && \
|
|
||||||
mkdir /root/.ssh && \
|
|
||||||
ssh-keyscan gitlab.com >> /root/.ssh/known_hosts
|
|
||||||
|
|
||||||
ARG SSH_KEY
|
ARG SSH_KEY
|
||||||
ENV SSH_KEY=${SSH_KEY}
|
ENV SSH_KEY=${SSH_KEY}
|
||||||
|
ARG CI_JOB_TOKEN
|
||||||
|
ENV CI_JOB_TOKEN=${CI_JOB_TOKEN}
|
||||||
|
|
||||||
RUN printf "$SSH_KEY" | base64 -d > /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa && \
|
RUN test -n "$SSH_KEY" && \
|
||||||
go build -o deploymentagent && \
|
{ mkdir /root/.ssh && ssh-keyscan gitlab.com >> /root/.ssh/known_hosts && printf "$SSH_KEY" | base64 -d > /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa && git config --global url."git@gitlab.com:".insteadOf "https://gitlab.com/"; } || true
|
||||||
rm /root/.ssh/id_rsa
|
|
||||||
|
RUN test -n "$CI_JOB_TOKEN" && \
|
||||||
|
{ printf "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc; } || true
|
||||||
|
|
||||||
|
RUN go build -o deploymentagent && \
|
||||||
|
rm -f /root/.ssh/id_rsa
|
||||||
|
|
||||||
FROM alpine:3.12
|
FROM alpine:3.12
|
||||||
|
|
||||||
|
@ -5,17 +5,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
inputQueue *DeploymentQueue // queued
|
|
||||||
processQueue *DeploymentQueue // deploying, failed, deployed
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
server := newDeploymentAgentServer()
|
server := newDeploymentAgentServer()
|
||||||
|
|
||||||
inputQueue = new(DeploymentQueue)
|
|
||||||
processQueue = new(DeploymentQueue)
|
|
||||||
|
|
||||||
go processDeploymentSpecs(&podmanClient{}, &http.Client{Transport: socketHttpTransport}, "http://podman/v1.0.0/libpod")
|
go processDeploymentSpecs(&podmanClient{}, &http.Client{Transport: socketHttpTransport}, "http://podman/v1.0.0/libpod")
|
||||||
|
|
||||||
if err := http.ListenAndServe(":5000", server); err != nil {
|
if err := http.ListenAndServe(":5000", server); err != nil {
|
||||||
|
@ -3,7 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
@ -16,15 +18,23 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
basicAuthUsername string
|
basicAuthUsername string
|
||||||
basicAuthPassword string
|
basicAuthPassword string
|
||||||
deploymentStateFile string
|
deploymentStateFile string
|
||||||
|
nixosRebuildSocketUrl string
|
||||||
|
inputQueue *DeploymentQueue // queued
|
||||||
|
processQueue *DeploymentQueue // deploying, failed, deployed
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
basicAuthUsername = settings.GetSetting("BASIC_AUTH_USERNAME", "default")
|
basicAuthUsername = settings.GetSetting("BASIC_AUTH_USERNAME", "default")
|
||||||
basicAuthPassword = settings.GetSetting("BASIC_AUTH_PASSWORD", "default")
|
basicAuthPassword = settings.GetSetting("BASIC_AUTH_PASSWORD", "default")
|
||||||
deploymentStateFile = settings.GetSetting("DEPLOYMENT_STATE_FILE", "./guidelines.json")
|
deploymentStateFile = settings.GetSetting("DEPLOYMENT_STATE_FILE", "./guidelines.json")
|
||||||
|
nixosRebuildSocketUrl = settings.GetSetting("NIXOS_REBUILD_SOCKET_URL", "localhost:4444")
|
||||||
|
|
||||||
|
inputQueue = new(DeploymentQueue)
|
||||||
|
processQueue = new(DeploymentQueue)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeploymentAgentServer struct {
|
type DeploymentAgentServer struct {
|
||||||
@ -181,19 +191,28 @@ func processDeploymentSpecs(pc *podmanClient, hc *http.Client, url string) {
|
|||||||
for {
|
for {
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
if len(inputQueue.GetAll()) > 0 {
|
if len(inputQueue.GetAll()) > 0 {
|
||||||
|
var err error
|
||||||
|
|
||||||
dequequedDeploymentSpec := inputQueue.Dequeue()
|
dequequedDeploymentSpec := inputQueue.Dequeue()
|
||||||
processQueue.Enqueue(dequequedDeploymentSpec.Id, "deploying", "Deployment in progress", dequequedDeploymentSpec.DeploymentSpec)
|
processQueue.Enqueue(dequequedDeploymentSpec.Id, "deploying", "Deployment in progress", dequequedDeploymentSpec.DeploymentSpec)
|
||||||
err := pc.pullImages(dequequedDeploymentSpec.DeploymentSpec, hc, url)
|
|
||||||
|
err = pc.pullImages(dequequedDeploymentSpec.DeploymentSpec, hc, url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processQueue.updateStatus(dequequedDeploymentSpec.Id, "failed", err.Error(), nil)
|
processQueue.updateStatus(dequequedDeploymentSpec.Id, "failed", ("When pulling images with Podman: " + err.Error()), getDeploymentState())
|
||||||
} else {
|
} else {
|
||||||
err := mergeDeploymentState(dequequedDeploymentSpec.DeploymentSpec)
|
err := mergeDeploymentState(dequequedDeploymentSpec.DeploymentSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
processQueue.updateStatus(dequequedDeploymentSpec.Id, "failed", err.Error(), getDeploymentState())
|
processQueue.updateStatus(dequequedDeploymentSpec.Id, "failed", ("When updating the deploymentstate file" + err.Error()), getDeploymentState())
|
||||||
} else {
|
} else {
|
||||||
processQueue.updateStatus(dequequedDeploymentSpec.Id, "deployed", "Deployment successful", getDeploymentState())
|
err = triggerNixosRebuild()
|
||||||
|
if err != nil {
|
||||||
|
processQueue.updateStatus(dequequedDeploymentSpec.Id, "failed", ("When triggering nixos-rebuild with Systemd: " + err.Error()), getDeploymentState())
|
||||||
|
} else {
|
||||||
|
processQueue.updateStatus(dequequedDeploymentSpec.Id, "deployed", "Deployment successful", getDeploymentState())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(processQueue.GetAll())
|
fmt.Println(processQueue.GetAll())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,3 +249,27 @@ func mergeDeploymentState(deploymentSpec DeploymentSpec) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// triggerNixosRebuild connects to the activation socket of a
|
||||||
|
// systemd unit which will trigger the nixos-rebuild unit.
|
||||||
|
// The connection will be kept open and closed as soon as the
|
||||||
|
// build has been completed, however, there is no way of
|
||||||
|
// knowing whether there has been an error in the build phase
|
||||||
|
// and thus the switch has not been applied.
|
||||||
|
func triggerNixosRebuild() error {
|
||||||
|
data := make([]byte, 1)
|
||||||
|
|
||||||
|
c, err := net.Dial("tcp", nixosRebuildSocketUrl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := c.Read(data); err == io.EOF {
|
||||||
|
fmt.Println("nixos-rebuild switch has finished")
|
||||||
|
c.Close()
|
||||||
|
} else {
|
||||||
|
c.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -23,9 +23,29 @@
|
|||||||
# `systemctl start nixos-rebuild` := `nixos-rebuild switch`
|
# `systemctl start nixos-rebuild` := `nixos-rebuild switch`
|
||||||
systemd.services.nixos-rebuild = {
|
systemd.services.nixos-rebuild = {
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
|
postStart = "systemctl stop socket-nixos-rebuild-trigger.service && systemctl restart socket-nixos-rebuild-trigger.socket";
|
||||||
script = ''
|
script = ''
|
||||||
/run/current-system/sw/bin/nixos-rebuild switch -I nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs -I nixos-config=/etc/nixos/configuration.nix
|
/run/current-system/sw/bin/nixos-rebuild switch -I nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs -I nixos-config=/etc/nixos/configuration.nix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.socket-nixos-rebuild-trigger = {
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = "yes";
|
||||||
|
};
|
||||||
|
after = [ "socket-nixos-rebuild-trigger.socket" ];
|
||||||
|
requires = [ "socket-nixos-rebuild-trigger.socket" ];
|
||||||
|
script = ''
|
||||||
|
systemctl start nixos-rebuild
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.sockets.socket-nixos-rebuild-trigger = {
|
||||||
|
listenStreams = [ "0.0.0.0:4444" ];
|
||||||
|
partOf = [ "socket-nixos-rebuild-trigger.service" ];
|
||||||
|
wantedBy = [ "sockets.target" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
users.extraUsers.operator = {
|
users.extraUsers.operator = {
|
||||||
|
Loading…
Reference in New Issue
Block a user