From 7a978731bb3f6ee6925f0b97682016d17dba0f9d Mon Sep 17 00:00:00 2001 From: Oscar Hermoso Date: Sat, 7 Sep 2024 17:00:24 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A5=89=20k3s=20example=20working=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP commit - helm example * 🥉 k3s working! --- CONTRIBUTING.md | 8 ++- README.md | 40 +++++++++--- examples/basic/main.tf | 2 +- examples/k3s/.gitignore | 3 + examples/k3s/README.md | 1 + examples/k3s/k3s-agent-join.sh | 3 + examples/k3s/k3s-server-install.sh | 5 +- examples/k3s/main.tf | 57 ++++++++++++++--- examples/k3s/nginx.tf | 64 +++++++++++++++++++ examples/k3s/providers.tf | 18 ++++++ examples/ssh/main.tf | 12 ++-- examples/vpc/main.tf | 8 +-- internal/provider/server_data_source.go | 77 ++++++++++++++++------- internal/provider/server_resource.go | 29 ++++++--- internal/provider/server_resource_test.go | 2 + internal/provider/ssh_key_resource.go | 15 ++--- 16 files changed, 272 insertions(+), 72 deletions(-) create mode 100644 examples/k3s/nginx.tf diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4405dd3..eedf6a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,13 @@ terraform apply ```sh -TF_ACC=1 go test -v ./... +TF_DEBUG=1 BINARYLANE_API_TOKEN=********* TF_ACC=1 go test -v ./... +``` + +### Update modules + +```sh +go get -u && go mod tidy && go generate ``` ### Adding resources/data sources to the provider diff --git a/README.md b/README.md index 8005168..3e1d74f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # terraform-provider-binarylane -See the examples in the [examples directory](./examples/basic/main.tf). +See the examples in the [examples directory](./examples/basic/README.md). ```terraform resource "binarylane_server" "example" { @@ -10,15 +10,33 @@ resource "binarylane_server" "example" { } ``` -## WIP +## Progress -If somehow you use this in production I would be pretty impressed. +Planned features: -- [x] Create/delete a server when runing locally -- [x] Publish - - [x] [Terraform Registry](https://registry.terraform.io/providers/oscarhermoso/binarylane/latest/docs/resources/server) - - [x] OpenTofu -- [ ] Deploy the rest of the owl +- [x] Servers + - [x] Firewall Rules + - [x] Cloud Init + - [ ] Updating server properties + - [ ] Backups + - [ ] Software + - [ ] IPV6 + - [ ] Alerts +- [x] SSH Keys +- [x] Virtual Private Cloud +- [ ] Images +- [ ] Load Balancers +- [ ] DNS +- [x] Docs + - [x] Generated docs + - [ ] Review & fill out remaining descriptions + - [ ] Include examples in docs +- [x] Examples + - [x] Basic + - [x] Cloud Init + - [ ] NixOS + - [ ] Virtual Private Cloud + - [ ] Kubernetes ## Parameters @@ -78,7 +96,10 @@ jq '[ .regions[] | .slug ] | sort' tmp/regions.json ] ``` -Sizes (not all sizes are available in all regions): +### Sizes + +
+VM size ```sh curl -X GET "https://api.binarylane.com.au/v2/sizes" \ @@ -86,6 +107,7 @@ curl -X GET "https://api.binarylane.com.au/v2/sizes" \ jq '[ .sizes[] | .slug ] | sort' tmp/sizes.json ``` +
```json [ diff --git a/examples/basic/main.tf b/examples/basic/main.tf index e104680..b35e191 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -11,7 +11,7 @@ provider "binarylane" { } resource "binarylane_server" "example" { - name = "tf-example" + name = "tf-example-basic" region = "per" # or "syd", "mel", "bne", "sin" image = "ubuntu-24.04" size = "std-min" # 1 VPCU, 1 GB Memory, 20 GB NVME Storage, 1000 GB Data Transfer diff --git a/examples/k3s/.gitignore b/examples/k3s/.gitignore index e895a5a..533fc6d 100644 --- a/examples/k3s/.gitignore +++ b/examples/k3s/.gitignore @@ -35,3 +35,6 @@ override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc + +# .kube/config contains credentials +.kube diff --git a/examples/k3s/README.md b/examples/k3s/README.md index 4979e3a..28f85fc 100644 --- a/examples/k3s/README.md +++ b/examples/k3s/README.md @@ -5,3 +5,4 @@ This WIP example shows how to create a Kubernetes cluster on Binary Lane. Prior art: - [MartinHodges/create_k8s](https://github.com/MartinHodges/create_k8s) repo and the [medium article](https://medium.com/@martin.hodges/creating-a-kubernetes-cluster-from-scratch-in-1-hour-using-automation-a25e387be547) that goes with it. - https://github.com/inscapist/terraform-k3s-private-cloud +- https://github.com/schnerring/schnerring.github.io/blob/07d06fb40e3d01f2483a739f516ac4d711a5742c/content/blog/use-terraform-to-deploy-an-azure-kubernetes-service-aks-cluster-traefik-2-cert-manager-and-lets-encrypt-certificates/index.md diff --git a/examples/k3s/k3s-agent-join.sh b/examples/k3s/k3s-agent-join.sh index 63e8e50..521c1d7 100644 --- a/examples/k3s/k3s-agent-join.sh +++ b/examples/k3s/k3s-agent-join.sh @@ -10,4 +10,7 @@ curl -sfL https://get.k3s.io | sh -s - agent \ unset K3S_TOKEN unset K3S_URL +# Disable firewall recommended +ufw disable + echo "K3s Node Join Completed" diff --git a/examples/k3s/k3s-server-install.sh b/examples/k3s/k3s-server-install.sh index 8cc05e0..f3766d9 100644 --- a/examples/k3s/k3s-server-install.sh +++ b/examples/k3s/k3s-server-install.sh @@ -10,7 +10,7 @@ curl -sfL https://get.k3s.io | sh -s - server \ # --disable-cloud-controller \ # --disable servicelb \ # --disable local-storage \ -# --disable traefik \ +# --disable traefik unset INSTALL_K3S_NAME unset K3S_TOKEN @@ -19,4 +19,7 @@ unset K3S_KUBECONFIG_MODE echo "Installing Helm" curl -sfL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash +# Disable firewall recommended +ufw disable + echo "K3s Setup Completed" diff --git a/examples/k3s/main.tf b/examples/k3s/main.tf index f68ea7d..70c0f8a 100644 --- a/examples/k3s/main.tf +++ b/examples/k3s/main.tf @@ -56,6 +56,30 @@ resource "binarylane_server" "server" { wait_for_create = 60 # Must wait for the server to be ready before creating firewall rules } +data "external" "kubeconfig" { + program = [ + "/usr/bin/ssh", + "-o UserKnownHostsFile=/dev/null", + "-o StrictHostKeyChecking=no", + "root@${binarylane_server.server.0.permalink}", + "echo '{\"kubeconfig\":\"'$(cat /etc/rancher/k3s/k3s.yaml | base64)'\"}'", + ] +} + +resource "local_sensitive_file" "kubeconfig" { + depends_on = [binarylane_server.server] + + content = replace( + base64decode( + replace(data.external.kubeconfig.result.kubeconfig, " ", "") + ), + "server: https://127.0.0.1:6443", + "server: https://${binarylane_server.server.0.permalink}:6443", + ) + filename = "${path.module}/.kube/config" + file_permission = "0600" +} + # k3s Agents # ---------- data "cloudinit_config" "agent" { @@ -110,14 +134,15 @@ resource "binarylane_server_firewall_rules" "example" { server_id = each.value.id firewall_rules = [ - { - description = "K3s supervisor and Kubernetes API Server" - protocol = "tcp" - source_addresses = local.agent_ips - destination_addresses = local.server_ips - destination_ports = ["6443"] - action = "accept" - }, + # TODO: Due to a bug, this only works if you uncomment AFTER creating servers + # { + # description = "K3s supervisor and Kubernetes API Server" + # protocol = "tcp" + # source_addresses = ["0.0.0.0/0"] + # destination_addresses = local.server_ips + # destination_ports = ["6443"] + # action = "accept" + # }, { description = "Flannel VXLAN" protocol = "udp" @@ -134,5 +159,21 @@ resource "binarylane_server_firewall_rules" "example" { destination_ports = ["10250"] action = "accept" }, + { + description = "SSH" + protocol = "udp" + source_addresses = ["0.0.0.0/0"] + destination_addresses = [binarylane_vpc.example.ip_range] + destination_ports = ["22"] + action = "accept" + }, + { + description = "HTTP" + protocol = "tcp" + source_addresses = ["0.0.0.0/0"] + destination_addresses = [binarylane_vpc.example.ip_range] + destination_ports = ["80"] + action = "accept" + }, ] } diff --git a/examples/k3s/nginx.tf b/examples/k3s/nginx.tf new file mode 100644 index 0000000..6fe3d97 --- /dev/null +++ b/examples/k3s/nginx.tf @@ -0,0 +1,64 @@ +resource "kubectl_manifest" "hello" { + yaml_body = < /var/tmp/output.txt resource.TestCheckResourceAttr("binarylane_server.test", "port_blocking", "true"), resource.TestCheckResourceAttr("binarylane_server.test", "ssh_keys.#", "1"), // Only the test SSH key should be registered resource.TestCheckResourceAttrPair("binarylane_server.test", "ssh_keys.0", "binarylane_ssh_key.test", "id"), + resource.TestCheckResourceAttrSet("binarylane_server.test", "permalink"), // Verify data source values resource.TestCheckResourceAttrPair("data.binarylane_server.test", "id", "binarylane_server.test", "id"), @@ -87,6 +88,7 @@ echo "Hello World" > /var/tmp/output.txt resource.TestCheckResourceAttr("data.binarylane_server.test", "region", "per"), resource.TestCheckResourceAttr("data.binarylane_server.test", "image", "debian-12"), resource.TestCheckResourceAttr("data.binarylane_server.test", "size", "std-min"), + resource.TestCheckResourceAttrPair("data.binarylane_server.test", "permalink", "binarylane_server.test", "permalink"), ), }, { diff --git a/internal/provider/ssh_key_resource.go b/internal/provider/ssh_key_resource.go index a591b23..b35df17 100644 --- a/internal/provider/ssh_key_resource.go +++ b/internal/provider/ssh_key_resource.go @@ -7,6 +7,7 @@ import ( "terraform-provider-binarylane/internal/binarylane" "terraform-provider-binarylane/internal/resources" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" @@ -17,9 +18,9 @@ import ( // Ensure the implementation satisfies the expected interfaces. var ( - _ resource.Resource = &sshKeyResource{} - _ resource.ResourceWithConfigure = &sshKeyResource{} - // _ resource.ResourceWithImportState = &serverResource{} + _ resource.Resource = &sshKeyResource{} + _ resource.ResourceWithConfigure = &sshKeyResource{} + _ resource.ResourceWithImportState = &serverResource{} ) func NewSshKeyResource() resource.Resource { @@ -217,7 +218,7 @@ func (r *sshKeyResource) Delete(ctx context.Context, req resource.DeleteRequest, } } -// func (r *sshKeyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { -// // Retrieve import ID and save to id attribute -// resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) -// } +func (r *sshKeyResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + // Retrieve import ID and save to id attribute + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +}