Skip to content
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

Use github.com/tinkerbell/dhcp library: #337

Merged
merged 23 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d3379b6
Use github.com/tinkerbell/dhcp library:
jacobweinstock Aug 5, 2023
b100f5b
Update cli help usage:
jacobweinstock Aug 5, 2023
61687d0
Update linter to latest
jacobweinstock Aug 5, 2023
c2d4408
Fix GitHub issue of "no space left on device":
jacobweinstock Aug 5, 2023
9b6e1f3
Move backend package to main:
jacobweinstock Aug 6, 2023
a7b9b9c
Only start the HTTP server if there are handlers:
jacobweinstock Aug 7, 2023
b57ad48
Sort flags in usage function:
jacobweinstock Aug 7, 2023
0b13efb
Update README:
jacobweinstock Aug 7, 2023
e34caa7
Update cli flag usage output:
jacobweinstock Aug 7, 2023
72d5985
Add code comments, other small clean up:
jacobweinstock Aug 14, 2023
e25fbe1
Rename make target, remove _packet reference:
jacobweinstock Aug 14, 2023
b6a5c90
Fix typo
jacobweinstock Aug 15, 2023
8d72e19
Rename package bhttp -> http:
jacobweinstock Aug 16, 2023
9259b29
Get rid of tools.go and clean up makefile:
jacobweinstock Aug 16, 2023
7a018b1
Rename cli.go -> flag.go:
jacobweinstock Aug 16, 2023
f2b1ac1
Simplify goimports in ci-checks.sh:
jacobweinstock Aug 16, 2023
002f4c0
Move main back into cmd/boots package:
jacobweinstock Aug 16, 2023
b1f22e9
Remove deprecated golangci linters
jacobweinstock Aug 16, 2023
3ac1445
Move http ipxe script backend into ipxe pkg:
jacobweinstock Aug 16, 2023
9a9ee52
Panic when more than one backend is enabled:
jacobweinstock Aug 16, 2023
d911b31
Make the flag usage descriptions be more uniform:
jacobweinstock Aug 16, 2023
0d80274
Remove commented lines from .golangci.yml
jacobweinstock Aug 16, 2023
59b6e4e
Don't make errors out of plain string in panic func:
jacobweinstock Aug 16, 2023
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
3 changes: 2 additions & 1 deletion .github/workflows/ci-checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ if ! nixfmt shell.nix; then
failed=1
fi

if ! git ls-files '*.go' | xargs -I% sh -c 'sed "/^import (/,/^)/ { /^\s*$/ d }" % >%.tmp && goimports -w %.tmp && (if cmp -s % %.tmp; then rm %.tmp; else mv %.tmp %; fi)'; then
if [[ -n $(go run golang.org/x/tools/cmd/goimports@latest -d -e -l .) ]]; then
go run golang.org/x/tools/cmd/goimports@latest -w .
failed=1
fi

Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ jobs:

- name: Checkout code
uses: actions/checkout@v3
with:
lfs: true

- name: Install nix
uses: cachix/install-nix-action@v18
with:
nix_path: nixpkgs=channel:nixpkgs-unstable

- name: Fetch Deps
run: nix-shell --run 'go get -t ./... && go mod tidy'
run: |
# fixes "write /run/user/1001/355792648: no space left on device" error
sudo mount -o remount,size=3G /run/user/1001 || true
nix-shell --run 'go get -t ./... && go mod tidy'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
Expand Down
16 changes: 10 additions & 6 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ linters-settings:
- name: waitgroup-by-value

staticcheck:
go: "1.17"
go: "1.20"

unused:
go: "1.17"
go: "1.20"

output:
sort-results: true
Expand All @@ -106,7 +106,8 @@ linters:
- asciicheck
- bodyclose
- cyclop
- deadcode
# deprecated
# - deadcode
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to just delete these? I don't think there's a reason to leave them in given we don't intend to reenable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yes, fixed.

- dogsled
- dupl
- durationcheck
Expand All @@ -128,7 +129,8 @@ linters:
- goprintffuncname
- gosimple
- govet
- ifshort
# deprecated
# - ifshort
- importas
- ineffassign
- makezero
Expand All @@ -145,15 +147,17 @@ linters:
- rowserrcheck
- sqlclosecheck
- staticcheck
- structcheck
# deprecated
# - structcheck
- stylecheck
- thelper
- tparallel
- typecheck
- unconvert
- unparam
- unused
- varcheck
# deprecated
# - varcheck
- wastedassign
- whitespace

Expand Down
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ To build Boots, run:
nix-shell

# build all ipxe files, embed them, and build the Go binary
# Built binary can be found here ./cmd/boots/boots
# Built binary can be found in the top level directory.
make boots

```
Expand Down Expand Up @@ -176,7 +176,7 @@ make vet
# FACILITY_CODE is needed for ?
export FACILITY_CODE=onprem
export DATA_MODEL_VERSION=1
# API_AUTH_TOKEN, API_CONSUMER_TOKEN are needed to by pass panicking in cmd/boots/main.go main func
# API_AUTH_TOKEN, API_CONSUMER_TOKEN are needed to by pass panicking in main.go main func
export API_AUTH_TOKEN=none
export API_CONSUMER_TOKEN=none
```
Expand All @@ -185,14 +185,14 @@ make vet

```bash
# Run the compiled boots
sudo ./cmd/boots/boots -http-addr 192.168.2.225:80 -tftp-addr 192.168.2.225:69 -dhcp-addr 192.168.2.225:67
sudo ./boots -http-addr 192.168.2.225:80 -tftp-addr 192.168.2.225:69 -dhcp-addr 192.168.2.225:67
```

4. Faster iterating via `go run`

```bash
# after the ipxe binaries have been compiled you can use `go run` to iterate a little more quickly than building the binary every time
sudo go run ./cmd/boots -http-addr 192.168.2.225:80 -tftp-addr 192.168.2.225:69 -dhcp-addr 192.168.2.225:67
sudo go run ./boots -http-addr 192.168.2.225:80 -tftp-addr 192.168.2.225:69 -dhcp-addr 192.168.2.225:67
```

## Pull Requests
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# run `make image` to build the binary + container
# if you're using `make boots` this Dockerfile will not find the binary
# and you probably want `make cmd/boots/boots-linux-amd64`
# and you probably want `make boots-linux-amd64`
FROM alpine:3.13

ARG TARGETARCH
Expand All @@ -9,5 +9,5 @@ ARG TARGETVARIANT
ENTRYPOINT ["/usr/bin/boots"]
EXPOSE 67 69 80

RUN apk add --update --upgrade --no-cache ca-certificates socat
RUN apk add --update --upgrade --no-cache ca-certificates
COPY cmd/boots/boots-linux-${TARGETARCH:-amd64}${TARGETVARIANT} /usr/bin/boots
16 changes: 7 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,29 @@ all: help
-include lint.mk
-include rules.mk

boots: cmd/boots/boots ## Compile boots for host OS and Architecture
build: cmd/boots/boots ## Compile boots for host OS and Architecture

crosscompile: $(crossbinaries) ## Compile boots for all architectures

gen: $(generated_go_files) mocks ## Generate go generate'd files

tools: $(toolsBins) ## Builds cli tools defined in tools.go
gen: $(generated_go_files) ## Generate go generate'd files

IMAGE_TAG ?= boots:latest
image: cmd/boots/boots-linux-amd64 ## Build docker image
image: cmd/boots/boots-linux-amd64 ## Build docker image
docker build -t $(IMAGE_TAG) .

test: gen ## Run go test
CGO_ENABLED=1 go test -race -coverprofile=coverage.txt -covermode=atomic ${TEST_ARGS} ./...
CGO_ENABLED=1 go test -race -coverprofile=coverage.txt -covermode=atomic -v ${TEST_ARGS} ./...

coverage: test ## Show test coverage
go tool cover -func=coverage.txt

vet: ## Run go vet
go vet ./...

goimports: bin/goimports gen ## Run goimports
goimports -w .
goimports: gen ## Run goimports
$(GOIMPORTS) -w .

ci-checks: bin/goimports .github/workflows/ci-checks.sh shell.nix gen
ci-checks: .github/workflows/ci-checks.sh shell.nix gen
./.github/workflows/ci-checks.sh

ci: ci-checks coverage goimports lint vet ## Runs all the same validations and tests that run in CI
Expand Down
116 changes: 77 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,39 @@

[![Build Status](https://github.com/tinkerbell/boots/workflows/For%20each%20commit%20and%20PR/badge.svg)](https://github.com/tinkerbell/boots/actions?query=workflow%3A%22For+each+commit+and+PR%22+branch%3Amain)

This service handles DHCP, PXE, tftp, and iPXE for provisions in the Tinkerbell project.
For more information about the Tinkerbell project, see: [tinkerbell.org](https://tinkerbell.org).
Boots is the network boot service in the [Tinkerbell stack](https://tinkerbell.org). It is comprised of the following services.

- DHCP server
- host reservations only
- mac address based lookups
- netboot options support
- backend support
- Kubernetes
- file based
- TFTP server
- serving iPXE binaries
- HTTP server
- serving iPXE binaries and iPXE scripts
- iPXE script serving uses IP authentication
- backend support
- Kubernetes
- file based
- Syslog server
- receives syslog messages and logs them

## Running Boots

As boots runs a DHCP server, it's often asked if it is safe to run without any network isolation; the answer is yes. While boots does run a DHCP server, it only allocates an IP address when it recognizes the mac address of the requesting device.
The DHCP server of Boots serves explicit host reservations only. This means that only hosts that are configured will be served an IP address and network boot details.

## Interoperability with other DHCP servers

It is not recommended, but it is possible for Boots to be run in networks with another DHCP server(s). To get the intended behavior from Boots one of the following must be true.

1. All DHCP servers are configured to serve the same IPAM info as Boots and Boots is the only DHCP server to provide network boot info.

1. All DHCP servers besides Boots are configured to ignore the MAC addresses that Boots is configured to serve.

1. All DHCP servers are configured to serve the same IP address and network boot details as Boots. In this scenario the DHCP functionality of Boots is redundant. It would most likely be recommended to run Boots with the DHCP server functionality disabled (`-dhcp=false`). See the doc on using your existing DHCP service for more details.

### Local Setup

Expand All @@ -23,67 +50,78 @@ Build/Run Boots
```bash
# make the binary
make boots
# run boots
./cmd/boots/boots -h
# run Boots
./boots -h

USAGE
Run Boots server for provisioning

FLAGS
-dhcp-addr IP and port to listen on for DHCP. (default "172.17.0.3:67")
-http-addr local IP and port to listen on for the serving iPXE binaries and files via HTTP. (default "172.17.0.3:80")
-ipxe-enable-http enable serving iPXE binaries via HTTP. (default "true")
-ipxe-enable-tftp enable serving iPXE binaries via TFTP. (default "true")
-ipxe-remote-http-addr remote IP and port where iPXE binaries are served via HTTP. Overrides -http-addr for iPXE binaries only.
-ipxe-remote-tftp-addr remote IP where iPXE binaries are served via TFTP. Overrides -tftp-addr.
-ipxe-tftp-addr local IP and port to listen on for serving iPXE binaries via TFTP (port must be 69). (default "0.0.0.0:69")
-ipxe-tftp-timeout local iPXE TFTP server requests timeout. (default "5s")
-log-level log level. (default "info")
-syslog-addr IP and port to listen on for syslog messages. (default "172.17.0.3:514")
-log-level log level (debug, info) (default "info")
-backend-file-enabled [backend] enable the file backend for DHCP and the HTTP iPXE script (default "false")
-backend-file-path [backend] the hardware yaml file path for the file backend
-backend-kube-api [backend] the Kubernetes API URL, used for in-cluster client construction, kube backend only
-backend-kube-config [backend] the Kubernetes config file location, kube backend only
-backend-kube-enabled [backend] enable the kubernetes backend for DHCP and the HTTP iPXE script (default "true")
-backend-kube-namespace [backend] an optional Kubernetes namespace override to query hardware data from, kube backend only
-dhcp-addr [dhcp] local IP and port to listen on for DHCP requests (default "0.0.0.0:67")
-dhcp-enabled [dhcp] enable DHCP server (default "true")
-dhcp-http-ipxe-binary-ip [dhcp] http ipxe binary server IP address to use in DHCP packets (default "http://172.17.0.2:8080/ipxe/")
-dhcp-http-ipxe-script-url [dhcp] http ipxe script server URL to use in DHCP packets (default "http://172.17.0.2/auto.ipxe")
-dhcp-ip-for-packet [dhcp] ip address to use in DHCP packets (opt 54, etc) (default "172.17.0.2")
-dhcp-syslog-ip [dhcp] syslog server IP address to use in DHCP packets (opt 7) (default "172.17.0.2")
-dhcp-tftp-ip [dhcp] tftp server IP address to use in DHCP packets (opt 66, etc) (default "172.17.0.2:69")
-extra-kernel-args [http] extra set of kernel args (k=v k=v) that are appended to the kernel cmdline iPXE script
-http-addr [http] local IP and port to listen on for iPXE http script requests (default "172.17.0.2:80")
-http-ipxe-binary-enabled [http] enable iPXE http binary server (default "true")
-http-ipxe-script-enabled [http] enable iPXE http script server) (default "true")
-osie-url [http] url where OSIE(Hook) images are located
-tink-server [http] ip:port for the Tink server
-tink-server-tls [http] use TLS for Tink server (default "false")
-trusted-proxies [http] comma separated list of trusted proxies
-syslog-addr [syslog] local IP and port to listen on for syslog messages (default "172.17.0.2:514")
-syslog-enabled [syslog] enable syslog server(receiver) (default "true")
-ipxe-script-patch [tftp/http] iPXE script fragment to patch into served iPXE binaries served via TFTP or HTTP
-tftp-addr [tftp] local IP and port to listen on for iPXE tftp binary requests (default "172.17.0.2:69")
-tftp-enabled [tftp] enable iPXE tftp binary server) (default "true")
-tftp-timeout [tftp] iPXE tftp binary server requests timeout (default "5s")
```

You can use NixOS shell, which will have Go and others
You can use NixOS shell, which will have Go and other dependencies.

`nix-shell`

### Developing with Standalone Mode
### Developing using the file backend

The quickest way to get started is `docker-compose up`. This will start boots in
standalone mode using the example JSON in the `test/` directory. It also starts
a client container that runs some tests.
The quickest way to get started is `docker-compose up`. This will start Boots using the file backend. This uses the example Yaml file (hardware.yaml) in the `test/` directory. It also starts a client container that runs some tests.

```sh
docker-compose build # build containers
docker-compose up # start the network & services
docker-compose up --build # build images and start the network & services
# it's fine to hit control-C twice for fast shutdown
docker-compose down # stop the network & clean up Docker processes
docker-compose down # stop the network & containers
```

Alternatively you can run boots standalone manually. It requires a few
environment variables for configuration.
Alternatively you can manually run Boots by itself. It requires a few
flags or environment variables for configuration.

`test/standalone-hardware.json` should be safe enough for most developers to
`test/hardware.yaml` should be safe enough for most developers to
use on the command line locally without getting a call from your network
administrator. That said, you might want to contact them before running a DHCP
server on their network. Best to isolate it in Docker or a VM if you're not
sure.

```sh
export DATA_MODEL_VERSION=standalone
export API_CONSUMER_TOKEN=none
export API_AUTH_TOKEN=none
export BOOTS_STANDALONE_JSON=./test/standalone-hardware.json

# to run on your laptop as a regular user
# DHCP won't work but useful for smoke testing and iterating on http/tftp/syslog
./cmd/boots/boots \
-http-addr 127.0.0.1:9000 \
-syslog-addr 127.0.0.1:9001 \
-tftp-addr 127.0.0.01:9002 \
-dhcp-addr 127.0.0.1:9003
export BOOTS_OSIE_URL=<http url to the OSIE (Operating System Installation Environment) artifacts>
# For more info on the default OSUE (Hook) artifacts, please see https://github.com/tinkerbell/hook
export BOOTS_BACKEND_FILE_ENABLED=true
export BOOTS_BACKEND_FILE_PATH=./test/hardware.yaml
export BOOTS_EXTRA_KERNEL_ARGS="tink_worker_image=quay.io/tinkerbell/tink-worker:latest"

# By default, Boots needs to bind to low ports (67, 69, 80, 514) so it needs root.
sudo -E ./boots

# or run it in a container
# NOTE: not sure the NET_ADMIN cap is necessary
docker run -ti --cap-add=NET_ADMIN --volume $(pwd):/boots alpine:3.14
/boots/cmd/boots -dhcp-addr 0.0.0.0:67
/boots -dhcp-addr 0.0.0.0:67
```
2 changes: 1 addition & 1 deletion Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ docker_build(
'quay.io/tinkerbell/boots',
'.',
dockerfile='Dockerfile',
only=['./cmd/boots']
only=['.']
)
k8s_yaml(kustomize('./manifests/kustomize/overlays/kind'))
Loading
Loading