Skip to content

Go rewrite #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Build

on:
push:
branches:
- golang

jobs:
docker:
runs-on: ubuntu-20.04

env:
PLATFORMS: linux/amd64,linux/386,linux/arm64,linux/arm/v7

steps:
- uses: actions/checkout@v2

- name: Set up QEMU
uses: docker/setup-qemu-action@v1

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1

- name: Install script dependencies
run: pip3 install -r scripts/requirements.txt

- id: vars
name: Generate build vars
run: |
SHA="${{ github.sha }}"
echo "::set-output name=tag::"${SHA:0:8}-$(date +%s)Z""

- name: Build
run: make PLUGIN_TAG=${{ steps.vars.outputs.tag }} multiarch

- name: Push
env:
REGISTRY_USERNAME: ${{ github.actor }}
REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
run: make PLUGIN_TAG=${{ steps.vars.outputs.tag }} push-multiarch
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/bin/*
!/bin/.gitkeep
/plugin/
__pycache__/
/multiarch/

.vscode/
25 changes: 16 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
FROM python:3-alpine
FROM golang:1.16-alpine3.13 AS builder

COPY requirements.txt /opt/
RUN apk --no-cache add gcc musl-dev && \
pip install -r /opt/requirements.txt && \
apk --no-cache del gcc musl-dev
WORKDIR /usr/local/src/docker-net-dhcp
COPY go.* ./
RUN go mod download

RUN mkdir -p /opt/plugin /run/docker/plugins /var/run/docker/netns
COPY net-dhcp/ /opt/plugin/net_dhcp
COPY cmd/ ./cmd/
COPY pkg/ ./pkg/
RUN mkdir bin/ && go build -o bin/ ./cmd/...

WORKDIR /opt/plugin
ENTRYPOINT ["python", "-m", "net_dhcp"]

FROM alpine:3.13

RUN mkdir -p /run/docker/plugins

COPY --from=builder /usr/local/src/docker-net-dhcp/bin/net-dhcp /usr/sbin/
COPY --from=builder /usr/local/src/docker-net-dhcp/bin/udhcpc-handler /usr/lib/net-dhcp/udhcpc-handler

ENTRYPOINT ["/usr/sbin/net-dhcp"]
89 changes: 52 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,40 +1,55 @@
PLUGIN_NAME = devplayer0/net-dhcp
PLUGIN_TAG ?= latest
PLUGIN_NAME = ghcr.io/devplayer0/docker-net-dhcp
PLUGIN_TAG ?= golang
PLATFORMS ?= linux/amd64,linux/arm64

all: clean build rootfs create enable
SOURCES = $(shell find pkg/ cmd/ -name '*.go')
BINARY = bin/net-dhcp

.PHONY: all debug build create enable disable pdebug push clean

all: create enable

bin/%: $(SOURCES)
go build -o $@ ./cmd/$(shell basename $@)

debug: $(BINARY)
sudo $< -log debug

build: $(SOURCES)
docker build -t $(PLUGIN_NAME):rootfs .

plugin/rootfs: build
mkdir -p plugin/rootfs
docker create --name tmp $(PLUGIN_NAME):rootfs
docker export tmp | tar xC plugin/rootfs
docker rm -vf tmp

plugin: plugin/rootfs config.json
cp config.json $@/

create: plugin
docker plugin rm -f $(PLUGIN_NAME):$(PLUGIN_TAG) || true
docker plugin create $(PLUGIN_NAME):$(PLUGIN_TAG) $<
docker plugin set $(PLUGIN_NAME):$(PLUGIN_TAG) LOG_LEVEL=trace

enable: plugin
docker plugin enable $(PLUGIN_NAME):$(PLUGIN_TAG)
disable:
docker plugin disable $(PLUGIN_NAME):$(PLUGIN_TAG)

pdebug: create enable
sudo sh -c 'tail -f /var/lib/docker/plugins/*/rootfs/var/log/net-dhcp.log'

push: create
docker plugin push $(PLUGIN_NAME):$(PLUGIN_TAG)

multiarch: $(SOURCES)
docker buildx build --platform=$(PLATFORMS) -o type=local,dest=$@ .

push-multiarch: multiarch config.json
scripts/push_multiarch_plugin.py -p $(PLATFORMS) config.json multiarch $(PLUGIN_NAME):$(PLUGIN_TAG)

clean:
@echo "### rm ./plugin"
@rm -rf ./plugin

build:
@echo "### docker build: rootfs image with net-dhcp"
@docker build -t ${PLUGIN_NAME}:rootfs .

rootfs:
@echo "### create rootfs directory in ./plugin/rootfs"
@mkdir -p ./plugin/rootfs
@docker create --name tmp ${PLUGIN_NAME}:rootfs
@docker export tmp | tar -x -C ./plugin/rootfs
@echo "### copy config.json to ./plugin/"
@cp config.json ./plugin/
@docker rm -vf tmp

create:
@echo "### remove existing plugin ${PLUGIN_NAME}:${PLUGIN_TAG} if exists"
@docker plugin rm -f ${PLUGIN_NAME}:${PLUGIN_TAG} || true
@echo "### create new plugin ${PLUGIN_NAME}:${PLUGIN_TAG} from ./plugin"
@docker plugin create ${PLUGIN_NAME}:${PLUGIN_TAG} ./plugin

debug:
@docker run --rm -ti --cap-add CAP_SYS_ADMIN --network host --volume /run/docker/plugins:/run/docker/plugins \
--volume /run/docker.sock:/run/docker.sock --volume /var/run/docker/netns:/var/run/docker/netns \
${PLUGIN_NAME}:rootfs

enable:
@echo "### enable plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
@docker plugin enable ${PLUGIN_NAME}:${PLUGIN_TAG}

push:
@echo "### push plugin ${PLUGIN_NAME}:${PLUGIN_TAG}"
@docker plugin push ${PLUGIN_NAME}:${PLUGIN_TAG}
-rm -rf multiarch/
-rm -rf plugin/
-rm bin/*
Empty file added bin/.gitkeep
Empty file.
65 changes: 65 additions & 0 deletions cmd/net-dhcp/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package main

import (
"flag"
"os"
"os/signal"

log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"

"github.com/devplayer0/docker-net-dhcp/pkg/plugin"
)

var (
logLevel = flag.String("log", "", "log level")
logFile = flag.String("logfile", "", "log file")
bindSock = flag.String("sock", "/run/docker/plugins/net-dhcp.sock", "bind unix socket")
)

func main() {
flag.Parse()

if *logLevel == "" {
if *logLevel = os.Getenv("LOG_LEVEL"); *logLevel == "" {
*logLevel = "info"
}
}

level, err := log.ParseLevel(*logLevel)
if err != nil {
log.WithError(err).Fatal("Failed to parse log level")
}
log.SetLevel(level)

if *logFile != "" {
f, err := os.OpenFile(*logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.WithError(err).Fatal("Failed to open log file for writing")
}
defer f.Close()

log.StandardLogger().Out = f
}

p, err := plugin.NewPlugin()
if err != nil {
log.WithError(err).Fatal("Failed to create plugin")
}

sigs := make(chan os.Signal, 1)
signal.Notify(sigs, unix.SIGINT, unix.SIGTERM)

go func() {
log.Info("Starting server...")
if err := p.Listen(*bindSock); err != nil {
log.WithError(err).Fatal("Failed to start plugin")
}
}()

<-sigs
log.Info("Shutting down...")
if err := p.Close(); err != nil {
log.WithError(err).Fatal("Failed to stop plugin")
}
}
48 changes: 48 additions & 0 deletions cmd/udhcpc-handler/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"encoding/json"
"net"
"os"

log "github.com/sirupsen/logrus"

"github.com/devplayer0/docker-net-dhcp/pkg/udhcpc"
)

func main() {
if len(os.Args) != 2 {
log.Fatalf("Usage: %v <event type>", os.Args[0])
return
}

event := udhcpc.Event{
Type: os.Args[1],
}

switch event.Type {
case "bound", "renew":
if v6, ok := os.LookupEnv("ipv6"); ok {
// Clean up the IP (udhcpc6 emits a _lot_ of zeros)
_, netV6, err := net.ParseCIDR(v6 + "/128")
if err != nil {
log.WithError(err).Warn("Failed to parse IPv6 address")
}

event.Data.IP = netV6.String()
} else {
event.Data.IP = os.Getenv("ip") + "/" + os.Getenv("mask")
event.Data.Gateway = os.Getenv("router")
event.Data.Domain = os.Getenv("domain")
}
case "deconfig", "leasefail", "nak":
default:
log.Warnf("Ignoring unknown event type `%v`", event.Type)
return
}

if err := json.NewEncoder(os.Stdout).Encode(event); err != nil {
log.Fatalf("Failed to encode udhcpc event: %w", err)
return
}
}
27 changes: 21 additions & 6 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,18 @@
"docker.networkdriver/1.0"
]
},
"entrypoint": [ "python", "-m", "net_dhcp" ],
"workdir": "/opt/plugin",
"entrypoint": ["/usr/sbin/net-dhcp", "-logfile", "/var/log/net-dhcp.log"],
"env": [
{
"description": "Log level",
"name": "LOG_LEVEL",
"value": "info",
"settable": [
"value"
]
}
],
"workdir": "/",
"network": {
"type": "host"
},
Expand All @@ -19,15 +29,20 @@
"options": [
"bind"
]
},
{
"source": "/var/run/docker",
"destination": "/run/docker",
"type": "bind",
"options": [
"bind"
]
}
],
"pidhost": true,
"linux": {
"capabilities": [
"CAP_NET_ADMIN",
"CAP_SYS_ADMIN",
"CAP_SYS_PTRACE",
"CAP_SYS_RESOURCE"
"CAP_SYS_ADMIN"
]
}
}
23 changes: 23 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module github.com/devplayer0/docker-net-dhcp

go 1.16

require (
github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/containerd/containerd v1.5.2 // indirect
github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0 // indirect
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0 // indirect
github.com/mitchellh/mapstructure v1.4.1
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0 // indirect
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
google.golang.org/grpc v1.38.0 // indirect
)
Loading