Rewrite in Zig
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
5028f127da
commit
fa62c57585
@ -1,102 +0,0 @@
|
|||||||
# options for analysis running
|
|
||||||
run:
|
|
||||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
|
||||||
timeout: 1m
|
|
||||||
|
|
||||||
# exit code when at least one issue was found, default is 1
|
|
||||||
issues-exit-code: 0
|
|
||||||
|
|
||||||
# include test files or not, default is true
|
|
||||||
tests: false
|
|
||||||
|
|
||||||
# which dirs to skip: issues from them won't be reported;
|
|
||||||
# can use regexp here: generated.*, regexp is applied on full path;
|
|
||||||
# default value is empty list, but default dirs are skipped independently
|
|
||||||
# from this option's value (see skip-dirs-use-default).
|
|
||||||
# "/" will be replaced by current OS file path separator to properly work
|
|
||||||
# on Windows.
|
|
||||||
skip-dirs:
|
|
||||||
- wasm
|
|
||||||
- static
|
|
||||||
- node_modules
|
|
||||||
- documents
|
|
||||||
- docker
|
|
||||||
- bind-*
|
|
||||||
|
|
||||||
# default is true. Enables skipping of directories:
|
|
||||||
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
|
|
||||||
skip-dirs-use-default: true
|
|
||||||
|
|
||||||
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
|
|
||||||
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
|
||||||
# automatic updating of go.mod described above. Instead, it fails when any changes
|
|
||||||
# to go.mod are needed. This setting is most useful to check that go.mod does
|
|
||||||
# not need updates, such as in a continuous integration and testing system.
|
|
||||||
# If invoked with -mod=vendor, the go command assumes that the vendor
|
|
||||||
# directory holds the correct copies of dependencies and ignores
|
|
||||||
# the dependency descriptions in go.mod.
|
|
||||||
modules-download-mode: mod
|
|
||||||
|
|
||||||
# Allow multiple parallel golangci-lint instances running.
|
|
||||||
# If false (default) - golangci-lint acquires file lock on start.
|
|
||||||
allow-parallel-runners: true
|
|
||||||
|
|
||||||
|
|
||||||
# output configuration options
|
|
||||||
output:
|
|
||||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
|
|
||||||
# default is "colored-line-number"
|
|
||||||
format: colored-line-number
|
|
||||||
|
|
||||||
# print lines of code with issue, default is true
|
|
||||||
print-issued-lines: true
|
|
||||||
|
|
||||||
# print linter name in the end of issue text, default is true
|
|
||||||
print-linter-name: true
|
|
||||||
|
|
||||||
# make issues output unique by line, default is true
|
|
||||||
uniq-by-line: true
|
|
||||||
|
|
||||||
# add a prefix to the output file references; default is no prefix
|
|
||||||
path-prefix: ""
|
|
||||||
|
|
||||||
# sorts results by: filepath, line and column
|
|
||||||
sort-results: false
|
|
||||||
|
|
||||||
|
|
||||||
# all available settings of specific linters
|
|
||||||
linters-settings:
|
|
||||||
gofmt:
|
|
||||||
# simplify code: gofmt with `-s` option, true by default
|
|
||||||
simplify: true
|
|
||||||
staticcheck:
|
|
||||||
# Select the Go version to target. The default is '1.13'.
|
|
||||||
go: "1.19"
|
|
||||||
# https://staticcheck.io/docs/options#checks
|
|
||||||
checks: ["all"]
|
|
||||||
stylecheck:
|
|
||||||
# Select the Go version to target. The default is '1.13'.
|
|
||||||
go: "1.19"
|
|
||||||
# https://staticcheck.io/docs/options#checks
|
|
||||||
checks: ["all"]
|
|
||||||
errcheck:
|
|
||||||
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
|
|
||||||
# default is false: such cases aren't reported by default.
|
|
||||||
check-blank: true
|
|
||||||
|
|
||||||
linters:
|
|
||||||
enable:
|
|
||||||
# go install github.com/kisielk/errcheck@latest
|
|
||||||
# go install github.com/gordonklaus/ineffassign@latest
|
|
||||||
# go install honnef.co/go/tools/cmd/staticcheck@latest
|
|
||||||
# go install gitlab.com/opennota/check/cmd/varcheck@latest
|
|
||||||
# go install github.com/go-critic/go-critic/cmd/gocritic@latest
|
|
||||||
- errcheck
|
|
||||||
- staticcheck
|
|
||||||
- stylecheck
|
|
||||||
- ineffassign
|
|
||||||
- varcheck
|
|
||||||
- gofmt
|
|
||||||
- gocritic
|
|
||||||
- wsl
|
|
||||||
fast: false
|
|
@ -1,18 +1,13 @@
|
|||||||
FROM golang:1.19-bullseye
|
FROM docker.io/alpine:3.18 AS builder
|
||||||
LABEL author="Thomas Bellembois"
|
|
||||||
|
|
||||||
# Copying sources.
|
RUN apk add --no-cache zig --repository=https://dl-cdn.alpinelinux.org/alpine/edge/testing
|
||||||
WORKDIR /go/src/codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerproxy-clientdrone/v2/
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Installing.
|
WORKDIR /work
|
||||||
RUN go install -v ./...
|
COPY src src
|
||||||
RUN chmod +x /go/bin/codefirst-dockerproxy-clientdrone
|
COPY build.zig build.zig
|
||||||
|
|
||||||
# Copying entrypoint.
|
RUN zig build -Doptimize=ReleaseSafe
|
||||||
COPY entrypoint.sh /
|
|
||||||
RUN chmod +x /entrypoint.sh
|
|
||||||
|
|
||||||
USER root
|
FROM scratch AS runner
|
||||||
EXPOSE 8081
|
COPY --from=builder /work/zig-out/bin/codefirst-dockerproxy-clientdrone /
|
||||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
ENTRYPOINT [ "/codefirst-dockerproxy-clientdrone" ]
|
||||||
|
@ -1,27 +1,18 @@
|
|||||||
sur le proxy:
|
# codefirst-dockerproxy-clientdrone
|
||||||
```
|
|
||||||
docker network create cicd_net
|
|
||||||
./zig-out/bin/codefirst-dockerproxy -d
|
|
||||||
```
|
|
||||||
|
|
||||||
sur le client web:
|
|
||||||
```
|
|
||||||
# Ajuster la constante proxyUrl et proxyPath puis compiler.
|
|
||||||
docker run --rm -it --volume $(pwd):/app sandrokeil/typescript tsc /app/src/index.ts
|
|
||||||
mv src/index.js build/src/index.js
|
|
||||||
|
|
||||||
# Build l'image.
|
Usage:
|
||||||
docker build -t hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientweb .
|
|
||||||
|
|
||||||
# Run le container.
|
```yaml
|
||||||
docker run -p 8081:80 hub.codefirst.iut.uca.fr/thomas.bellembois/codefirst-dockerproxy-clientweb
|
- name: deploy-container
|
||||||
|
image: hub.codefirst.iut.uca.fr/clement.freville2/codefirst-dockerproxy-clientdrone:latest
|
||||||
|
settings:
|
||||||
|
image: hub.codefirst.iut.uca.fr/my.login/my_repository:latest
|
||||||
|
container: my_container_name
|
||||||
|
command: create
|
||||||
|
overwrite: true
|
||||||
```
|
```
|
||||||
|
|
||||||
-> http://localhost:8081/dockerrunner/
|
## Changes from upstream
|
||||||
|
|
||||||
sur le client cd:
|
- Removed the shell script to handle spaces in arguments.
|
||||||
```
|
- Used Drone settings instead of environment variables.
|
||||||
go run . -proxyhost localhost:8080 -devel -command create -imagename nginx -containername nginx1 -admins john.doe,mickey.mouse
|
|
||||||
go run . -proxyhost localhost:8080 -devel -command create -imagename nginx -containername nginx2
|
|
||||||
go run . -proxyhost localhost:8080 -devel -command create -imagename nginx -containername nginx3
|
|
||||||
```
|
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Although this function looks imperative, note that its job is to
|
||||||
|
// declaratively construct a build graph that will be executed by an external
|
||||||
|
// runner.
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard optimization options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||||
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "codefirst-dockerproxy-clientdrone",
|
||||||
|
// In this case the main source file is merely a path, however, in more
|
||||||
|
// complicated build scripts, this could be a generated file.
|
||||||
|
.root_source_file = .{ .path = "src/main.zig" },
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
exe.strip = true;
|
||||||
|
|
||||||
|
// This declares intent for the executable to be installed into the
|
||||||
|
// standard location when the user invokes the "install" step (the default
|
||||||
|
// step when running `zig build`).
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
// This *creates* a Run step in the build graph, to be executed when another
|
||||||
|
// step is evaluated that depends on it. The next line below will establish
|
||||||
|
// such a dependency.
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
|
// By making the run step depend on the install step, it will be run from the
|
||||||
|
// installation directory rather than directly from within the cache directory.
|
||||||
|
// This is not necessary, however, if the application depends on other installed
|
||||||
|
// files, this ensures they will be present and in the expected location.
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
// This allows the user to pass arguments to the application in the build
|
||||||
|
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||||
|
// and can be selected like this: `zig build run`
|
||||||
|
// This will evaluate the `run` step rather than the default, which is "install".
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
@ -1,88 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
ProxyScheme=""
|
|
||||||
ProxyHost=""
|
|
||||||
ProxyPath=""
|
|
||||||
|
|
||||||
ImageName=""
|
|
||||||
ContainerName=""
|
|
||||||
Overwrite=""
|
|
||||||
Private=""
|
|
||||||
Env=""
|
|
||||||
Command=""
|
|
||||||
Admins=""
|
|
||||||
|
|
||||||
if [ ! -z "$PROXYSCHEME" ]
|
|
||||||
then
|
|
||||||
ProxyScheme="-proxyscheme $PROXYSCHEME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$PROXYHOST" ]
|
|
||||||
then
|
|
||||||
ProxyHost="-proxyhost $PROXYHOST"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$PROXYPATH" ]
|
|
||||||
then
|
|
||||||
ProxyPath="-proxypath $PROXYPATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$IMAGENAME" ]
|
|
||||||
then
|
|
||||||
ImageName="-imagename $IMAGENAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$CONTAINERNAME" ]
|
|
||||||
then
|
|
||||||
ContainerName="-containername $CONTAINERNAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$COMMAND" ]
|
|
||||||
then
|
|
||||||
Command="-command $COMMAND"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$ADMINS" ]
|
|
||||||
then
|
|
||||||
Admins="-admins $ADMINS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [ ! -z "$PRIVATE" ]
|
|
||||||
then
|
|
||||||
Private="-private"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -z "$OVERWRITE" ]
|
|
||||||
then
|
|
||||||
Overwrite="-overwrite"
|
|
||||||
fi
|
|
||||||
|
|
||||||
prefix="CODEFIRST_CLIENTDRONE_ENV_"
|
|
||||||
ENVS=$(env | awk -F "=" '{print $1}' | grep ".*$prefix.*")
|
|
||||||
|
|
||||||
if [ ! -z "$ENVS" ]
|
|
||||||
then
|
|
||||||
Env=""
|
|
||||||
arrayEnv=($ENVS)
|
|
||||||
|
|
||||||
for i in "${arrayEnv[@]}"
|
|
||||||
do
|
|
||||||
envVarName=${i#"$prefix"}
|
|
||||||
Env=$Env" -env $envVarName=${!i}"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $ProxyScheme
|
|
||||||
echo $ProxyHost
|
|
||||||
echo $ProxyPath
|
|
||||||
|
|
||||||
echo $ImageName
|
|
||||||
echo $ContainerName
|
|
||||||
echo $Overwrite
|
|
||||||
echo $Private
|
|
||||||
echo $Admins
|
|
||||||
echo $Env
|
|
||||||
echo $Command
|
|
||||||
|
|
||||||
#/go/bin
|
|
||||||
sh -c "/go/bin/codefirst-dockerproxy-clientdrone $ProxyScheme $ProxyHost $ProxyPath $ImageName $ContainerName $Private $Admins $Overwrite $Env $Command"
|
|
@ -1,7 +0,0 @@
|
|||||||
module codefirst.iut.uca.fr/git/thomas.bellembois/codefirst-dockerproxy-clientdrone
|
|
||||||
|
|
||||||
go 1.19
|
|
||||||
|
|
||||||
require github.com/go-resty/resty/v2 v2.7.0
|
|
||||||
|
|
||||||
require golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
|
|
@ -1,9 +0,0 @@
|
|||||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
|
||||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
|
||||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb h1:pirldcYWx7rx7kE5r+9WsOXPXK0+WH5+uZ7uPmJ44uM=
|
|
||||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
@ -1,267 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CodeFirstContainer struct {
|
|
||||||
ID string `json:"Id"`
|
|
||||||
Image string `json:"Image"`
|
|
||||||
Env []string `json:"Env,omitempty"`
|
|
||||||
Admins string `json:"Admins,omitempty"`
|
|
||||||
Private bool `json:"Private,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type StringSliceFlag struct {
|
|
||||||
value []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StringSliceFlag) String() string {
|
|
||||||
return fmt.Sprintf("%s", *s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StringSliceFlag) Set(v string) error {
|
|
||||||
s.value = append(s.value, v)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
authUser string
|
|
||||||
|
|
||||||
command string
|
|
||||||
proxyScheme, proxyHost, proxyPath string
|
|
||||||
imageName, containerName, admins string
|
|
||||||
|
|
||||||
private, overwrite, devel bool
|
|
||||||
|
|
||||||
env StringSliceFlag
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
env = StringSliceFlag{}
|
|
||||||
|
|
||||||
flag.StringVar(&command, "command", "list", "list|logs|create|delete|start")
|
|
||||||
flag.BoolVar(&devel, "devel", false, "use fake x-forwarded-user")
|
|
||||||
|
|
||||||
flag.StringVar(&proxyScheme, "proxyscheme", "http", "proxy scheme")
|
|
||||||
flag.StringVar(&proxyHost, "proxyhost", "dockerproxy:8080", "proxy host")
|
|
||||||
flag.StringVar(&proxyPath, "proxypath", "/", "proxy path")
|
|
||||||
|
|
||||||
flag.StringVar(&imageName, "imagename", "", "image name")
|
|
||||||
flag.StringVar(&containerName, "containername", "", "container name")
|
|
||||||
flag.StringVar(&admins, "admins", "", "admins (comma separated list)")
|
|
||||||
flag.BoolVar(&private, "private", false, "private container")
|
|
||||||
flag.BoolVar(&overwrite, "overwrite", false, "overwrite existing container")
|
|
||||||
flag.Var(&env, "env", "environment variables (separated by spaces)")
|
|
||||||
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
fmt.Println("flags:")
|
|
||||||
fmt.Printf("-imagename: %s\n", imageName)
|
|
||||||
fmt.Printf("-containername: %s\n", containerName)
|
|
||||||
fmt.Printf("-private: %t\n", private)
|
|
||||||
fmt.Printf("-admins: %s\n", admins)
|
|
||||||
fmt.Printf("-overwrite: %t\n", overwrite)
|
|
||||||
fmt.Printf("-env: %s\n", env)
|
|
||||||
|
|
||||||
if command != "list" && containerName == "" {
|
|
||||||
fmt.Println("Missing containername parameter.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if command == "create" && imageName == "" {
|
|
||||||
fmt.Println("Missing imagename parameter.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if devel {
|
|
||||||
authUser = "thomas.bellembois"
|
|
||||||
} else {
|
|
||||||
authUser = os.Getenv("DRONE_REPO_OWNER")
|
|
||||||
}
|
|
||||||
|
|
||||||
containerName = authUser + "-" + containerName
|
|
||||||
containerName = strings.ReplaceAll(containerName, ".", "")
|
|
||||||
|
|
||||||
fmt.Printf("authUser: %s\n", authUser)
|
|
||||||
fmt.Printf("new containerName: %s\n", containerName)
|
|
||||||
|
|
||||||
if len(authUser) == 0 {
|
|
||||||
fmt.Println("Not authenticated.")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch command {
|
|
||||||
case "list":
|
|
||||||
list()
|
|
||||||
case "logs":
|
|
||||||
logs()
|
|
||||||
case "create":
|
|
||||||
if overwrite {
|
|
||||||
delete(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !exist() {
|
|
||||||
createImage()
|
|
||||||
create()
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
case "start":
|
|
||||||
start()
|
|
||||||
case "delete":
|
|
||||||
delete(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func exist() bool {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
Get(fmt.Sprintf("%s://%s/containers/%s/json", proxyScheme, proxyHost, containerName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
return resp.IsSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
func list() {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
Get(fmt.Sprintf("%s://%s/containers/json", proxyScheme, proxyHost))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logs() {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
Get(fmt.Sprintf("%s://%s/containers/%s/logs", proxyScheme, proxyHost, containerName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
container := CodeFirstContainer{
|
|
||||||
Image: imageName,
|
|
||||||
Env: env.value,
|
|
||||||
Private: private,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
SetBody(container).
|
|
||||||
Post(fmt.Sprintf("%s://%s/containers/%s/start", proxyScheme, proxyHost, containerName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func create() {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
container := CodeFirstContainer{
|
|
||||||
Image: imageName,
|
|
||||||
Env: env.value,
|
|
||||||
Private: private,
|
|
||||||
Admins: admins,
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
SetBody(container).
|
|
||||||
Post(fmt.Sprintf("%s://%s/containers/create/%s", proxyScheme, proxyHost, containerName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func delete(bypassError bool) {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
Delete(fmt.Sprintf("%s://%s/containers/%s", proxyScheme, proxyHost, containerName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if !bypassError && resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createImage() {
|
|
||||||
client := resty.New()
|
|
||||||
|
|
||||||
resp, err := client.R().
|
|
||||||
SetHeader("x-forwarded-user", authUser).
|
|
||||||
Post(fmt.Sprintf("%s://%s/images/create?fromImage=%s", proxyScheme, proxyHost, imageName))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp.Body()))
|
|
||||||
|
|
||||||
if resp.IsError() {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,164 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const allocator = std.heap.page_allocator;
|
||||||
|
var client: std.http.Client = .{ .allocator = allocator };
|
||||||
|
const Command = enum { list, logs, create, delete, start };
|
||||||
|
|
||||||
|
const ForwardedUser = "X-Forwarded-User";
|
||||||
|
|
||||||
|
const PluginError = error{
|
||||||
|
InvalidUser,
|
||||||
|
InvalidCommand,
|
||||||
|
NoContainerName,
|
||||||
|
InvalidImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const CodefirstAuth = struct {
|
||||||
|
proxyScheme: []const u8,
|
||||||
|
proxyHost: []const u8,
|
||||||
|
user: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const CodefirstContainer = struct {
|
||||||
|
Id: []const u8,
|
||||||
|
Image: []const u8,
|
||||||
|
Admins: []const u8,
|
||||||
|
Env: [][]const u8,
|
||||||
|
Private: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn sendRequest(method: std.http.Method, auth: CodefirstAuth, path: []const u8, body: []const u8) !std.http.Status {
|
||||||
|
const uri = std.Uri.parse(path) catch unreachable;
|
||||||
|
var headers = std.http.Headers{ .allocator = allocator };
|
||||||
|
defer headers.deinit();
|
||||||
|
try headers.append(ForwardedUser, auth.user);
|
||||||
|
if (body.len > 0) {
|
||||||
|
try headers.append("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
var req = try client.request(method, uri, headers, .{});
|
||||||
|
defer req.deinit();
|
||||||
|
req.transfer_encoding = std.http.Client.RequestTransfer{ .content_length = body.len };
|
||||||
|
try req.start();
|
||||||
|
try req.writeAll(body);
|
||||||
|
try req.finish();
|
||||||
|
try req.wait();
|
||||||
|
const responseBody = req.reader().readAllAlloc(allocator, 8192) catch unreachable;
|
||||||
|
defer allocator.free(responseBody);
|
||||||
|
std.log.info("{s}", .{responseBody});
|
||||||
|
return req.response.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists(auth: CodefirstAuth, containerName: []const u8) !bool {
|
||||||
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}/json", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
||||||
|
defer allocator.free(path);
|
||||||
|
var status = try sendRequest(.GET, auth, path, "");
|
||||||
|
return status == .ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createImage(auth: CodefirstAuth, imageName: []const u8) !void {
|
||||||
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/images/create?fromImage={s}", .{ auth.proxyScheme, auth.proxyHost, imageName });
|
||||||
|
defer allocator.free(path);
|
||||||
|
_ = try sendRequest(.POST, auth, path, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create(auth: CodefirstAuth, container: CodefirstContainer, containerName: []const u8) !void {
|
||||||
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/create/{s}", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
||||||
|
defer allocator.free(path);
|
||||||
|
var json = std.ArrayList(u8).init(allocator);
|
||||||
|
defer json.deinit();
|
||||||
|
try std.json.stringify(container, .{}, json.writer());
|
||||||
|
_ = try sendRequest(.POST, auth, path, json.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start(auth: CodefirstAuth, imageName: []const u8, containerName: []const u8, env: [][]const u8, private: bool) !void {
|
||||||
|
const ContainerStart = struct {
|
||||||
|
Id: []const u8,
|
||||||
|
Image: []const u8,
|
||||||
|
Env: [][]const u8,
|
||||||
|
Private: bool,
|
||||||
|
};
|
||||||
|
const command = ContainerStart{
|
||||||
|
.Id = "",
|
||||||
|
.Image = imageName,
|
||||||
|
.Env = env,
|
||||||
|
.Private = private,
|
||||||
|
};
|
||||||
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}/start", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
||||||
|
defer allocator.free(path);
|
||||||
|
var json = std.ArrayList(u8).init(allocator);
|
||||||
|
defer json.deinit();
|
||||||
|
try std.json.stringify(command, .{}, json.writer());
|
||||||
|
_ = try sendRequest(.POST, auth, path, json.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete(auth: CodefirstAuth, containerName: []const u8) !void {
|
||||||
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
||||||
|
defer allocator.free(path);
|
||||||
|
_ = try sendRequest(.DELETE, auth, path, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run() !void {
|
||||||
|
const command_name = std.os.getenv("PLUGIN_COMMAND") orelse return PluginError.InvalidCommand;
|
||||||
|
const command = std.meta.stringToEnum(Command, command_name) orelse return PluginError.InvalidCommand;
|
||||||
|
const auth = CodefirstAuth{
|
||||||
|
.proxyScheme = std.os.getenv("PROXYSCHEME") orelse "http",
|
||||||
|
.proxyHost = std.os.getenv("PROXYHOST") orelse "dockerproxy:8080",
|
||||||
|
.user = std.os.getenv("DRONE_REPO_OWNER") orelse return PluginError.InvalidUser,
|
||||||
|
};
|
||||||
|
const containerName = std.os.getenv("PLUGIN_CONTAINER") orelse return PluginError.NoContainerName;
|
||||||
|
|
||||||
|
var envs = std.ArrayList([]const u8).init(allocator);
|
||||||
|
defer envs.deinit();
|
||||||
|
for (std.os.environ) |env| {
|
||||||
|
if (std.mem.startsWith(u8, std.mem.span(env), "CODEFIRST_CLIENTDRONE_ENV_")) {
|
||||||
|
try envs.append(std.mem.span(env)["CODEFIRST_CLIENTDRONE_ENV_".len..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
.create => {
|
||||||
|
const imageName = std.os.getenv("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
||||||
|
const private = std.mem.eql(u8, std.os.getenv("PLUGIN_PRIVATE") orelse "false", "true");
|
||||||
|
const overwrite = std.mem.eql(u8, std.os.getenv("PLUGIN_OVERWRITE") orelse "false", "true");
|
||||||
|
const admins = std.os.getenv("PLUGIN_ADMINS") orelse auth.user;
|
||||||
|
|
||||||
|
const container = CodefirstContainer{
|
||||||
|
.Id = "",
|
||||||
|
.Image = imageName,
|
||||||
|
.Admins = admins,
|
||||||
|
.Env = envs.items,
|
||||||
|
.Private = private,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (overwrite) {
|
||||||
|
try delete(auth, containerName);
|
||||||
|
}
|
||||||
|
if (!try exists(auth, containerName)) {
|
||||||
|
try createImage(auth, imageName);
|
||||||
|
try create(auth, container, containerName);
|
||||||
|
try start(auth, imageName, containerName, envs.items, private);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.start => {
|
||||||
|
const imageName = std.os.getenv("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
||||||
|
const private = std.mem.eql(u8, std.os.getenv("PLUGIN_PRIVATE") orelse "false", "true");
|
||||||
|
try start(auth, imageName, containerName, envs.items, private);
|
||||||
|
},
|
||||||
|
.delete => {
|
||||||
|
try delete(auth, containerName);
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
run() catch |err| {
|
||||||
|
switch (err) {
|
||||||
|
PluginError.InvalidCommand => std.log.err("Invalid command (possible values: list|logs|create|delete|start)", .{}),
|
||||||
|
PluginError.InvalidUser => std.log.err("Invalid user", .{}),
|
||||||
|
PluginError.NoContainerName => std.log.err("No container name", .{}),
|
||||||
|
PluginError.InvalidImage => std.log.err("Invalid image", .{}),
|
||||||
|
else => std.log.err("{}", .{err}),
|
||||||
|
}
|
||||||
|
std.os.exit(1);
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in new issue