From b4f6cbbe13dfd2c944978efa4ce1f83712b3439a Mon Sep 17 00:00:00 2001 From: iury fukuda Date: Thu, 18 Aug 2022 15:45:09 -0300 Subject: [PATCH] AZURE: start support --- devShell.nix | 22 +++- env/azure/config.nix | 57 +++++++++ flake.nix | 87 +++++++++----- generators/minimal-azure.nix | 4 + provision/azure/default.nix | 222 +++++++++++++++++++++++++++++++++++ 5 files changed, 363 insertions(+), 29 deletions(-) create mode 100644 env/azure/config.nix create mode 100644 generators/minimal-azure.nix create mode 100644 provision/azure/default.nix diff --git a/devShell.nix b/devShell.nix index a760b70..d733bb6 100644 --- a/devShell.nix +++ b/devShell.nix @@ -18,6 +18,9 @@ let build-gce = writeScriptBin "build-gce" '' build gce ''; + build-azure = writeScriptBin "build-azure" '' + build azure + ''; # Apply using terraform apply = writeScriptBin "apply" '' @@ -31,6 +34,9 @@ let apply-gcp = writeScriptBin "apply-gcp" '' apply gcp ''; + apply-azure = writeScriptBin "apply-azure" '' + apply azure + ''; # Destroy using terraform destroy = writeScriptBin "destroy" '' @@ -44,6 +50,9 @@ let destroy-gcp = writeScriptBin "destroy-gcp" '' destroy gcp ''; + destroy-azure = writeScriptBin "destroy-azure" '' + destroy azure + ''; # Deploy nix using colmena deploy = writeScriptBin "deploy" '' @@ -56,6 +65,9 @@ let deploy-gcp = writeScriptBin "deploy-gcp" '' deploy gcp ''; + deploy-azure = writeScriptBin "deploy-azure" '' + deploy azure + ''; # Clean SSH authorized keys clean-ssh = writeScriptBin "clean-ssh" '' @@ -69,43 +81,49 @@ let clean-ssh-gcp = writeScriptBin "clean-ssh-gcp" '' nix run .#clean-ssh-gcp ''; + clean-ssh-azure = writeScriptBin "clean-ssh-azure" '' + nix run .#clean-ssh-azure + ''; # Up and Running local vault using docker-compose by arion local-vault = writeScriptBin "local-vault" '' nix run .#local-vault ''; - # Up and running local k8s using k3d local-k8s = writeScriptBin "local-k8s" '' nix run .#local-k8s ''; - in mkShell { packages = [ # build images build build-qcow build-gce + build-azure # provision apply apply apply-libvirt apply-gcp + apply-azure # provision destroy destroy destroy-libvirt destroy-gcp + destroy-azure # deploy nix deploy deploy-libvirt deploy-gcp + deploy-azure # clean ssh authorized keys clean-ssh clean-ssh-libvirt clean-ssh-gcp + clean-ssh-azure # start local vault local-vault diff --git a/env/azure/config.nix b/env/azure/config.nix new file mode 100644 index 0000000..cd22d3a --- /dev/null +++ b/env/azure/config.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }: { + provision.azure = { + enable = true; + project = "bornlogic-consul"; + + # images = { + # nixos = { + # location = "US"; + # source = toString + # ../../images/gce/nixos-image-22.05.20220728.9370544-x86_64-linux.raw.tar.gz; + # }; + # }; + + # networks = { + # prod = { description = "production network"; }; + # stag = { description = "staging network"; }; + + # test = { + # description = "testing network"; + # subnetworks = { + # n1 = { + # cidr_range = "10.3.0.0/16"; + # description = "n1 network"; + # secondary_ranges = [{ + # range_name = "test-second-range"; + # cidr_range = "10.4.0.0/16"; + # }]; + # }; + # }; + # }; + # }; + + # replicas = { + # c2r1 = { + # tags = [ "consul" "server" "nixos" "test" ]; + # network = "test"; + # subnetwork = "n1"; + # machine_type = "e2-medium"; + # zone = "us-east1-b"; + # }; + # c2r2 = { + # tags = [ "consul" "server" "nixos" "test" ]; + # network = "test"; + # subnetwork = "n1"; + # machine_type = "e2-medium"; + # zone = "us-east1-c"; + # }; + # c2r3 = { + # tags = [ "consul" "server" "nixos" "test" ]; + # network = "test"; + # subnetwork = "n1"; + # machine_type = "e2-medium"; + # zone = "us-east1-d"; + # }; + # }; + }; +} diff --git a/flake.nix b/flake.nix index 9a94eb6..cbede5f 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,7 @@ libvirtConfig = genConfig "libvirt"; gcpConfig = genConfig "gcp"; + azureConfig = genConfig "azure"; in { # overlay overlays = import ./overlays; @@ -55,16 +56,25 @@ ]; format = "gce"; }; + # nix build .#azure + azure = nixos-generators.nixosGenerate { + inherit pkgs; + modules = [ + # minimal gcp + ./generators/minimal-azure.nix + ]; + format = "azure"; + }; }; devShells.${system}.default = self.packages.${system}.devShell; # Apps apps.${system} = { - + # nix run + default = self.apps.${system}.apply; # nix run ".#apply" # defaults to libvirt apply = self.apps.${system}.apply-libvirt; - # nix run ".#apply-libvirt" apply-libvirt = { type = "app"; @@ -72,7 +82,6 @@ scripts/terranix-apply.sh "libvirt" ${libvirtConfig} ''); }; - # nix run ".#apply-gcp" apply-gcp = { type = "app"; @@ -80,31 +89,17 @@ scripts/terranix-apply.sh "gcp" ${gcpConfig} ''); }; - - # nix run ".#local-vault" - local-vault = { - type = "app"; - program = toString (pkgs.writers.writeBash "local-vault" '' - set -euo pipefail - cd arion/ - arion up - ''); - }; - - # nix run ".#local-k8s" - local-k8s = { + # nix run ".#apply-azure" + apply-azure = { type = "app"; - program = toString (pkgs.writers.writeBash "local-k8s" '' - set -euo pipefail - scripts/k8s/local-k8s.sh - # scripts/k8s/configure.sh + program = toString (pkgs.writers.writeBash "apply-azure" '' + scripts/terranix-apply.sh "azure" ${azureConfig} ''); }; # nix run ".#destroy" # defaults to libvirt destroy = self.apps.${system}.destroy-libvirt; - # nix run ".#destroy-libvirt" destroy-libvirt = { type = "app"; @@ -112,7 +107,6 @@ scripts/terranix-destroy.sh "libvirt" ${libvirtConfig} ''); }; - # nix run ".#destroy-gcp destroy-gcp = { type = "app"; @@ -120,11 +114,17 @@ scripts/terranix-destroy.sh "gcp" ${gcpConfig} ''); }; + # nix run ".#destroy-azure + destroy-azure = { + type = "app"; + program = toString (pkgs.writers.writeBash "destroy-azure" '' + scripts/terranix-destroy.sh "azure" ${gcpConfig} + ''); + }; # nix run ".#clean-ssh" # defaults to libvirt clean-ssh = self.apps.${system}.clean-ssh-libvirt.program; - # nix run ".#clean-ssh-libvirt" clean-ssh-libvirt = { type = "app"; @@ -132,7 +132,6 @@ ./scripts/clean-ssh.sh libvirt ''); }; - # nix run ".#clean-ssh-gcp" clean-ssh-gcp = { type = "app"; @@ -140,6 +139,14 @@ ./scripts/clean-ssh.sh gcp ''); }; + # nix run ".#clean-ssh-azure" + clean-ssh-azure = { + type = "app"; + program = toString (pkgs.writers.writeBash "clean-ssh-azure" '' + ./scripts/clean-ssh.sh azure + ''); + }; + # nix run ".#deploy" # defaults to libvirt deploy = { @@ -164,8 +171,34 @@ ${pkgs.colmena}/bin/colmena apply --on @gcp ''); }; - # nix run - default = self.apps.${system}.apply; + # nix run ".#deploy-azure" + deploy-azure = { + type = "app"; + program = toString (pkgs.writers.writeBash "deploy-azure" '' + set -euo pipefail + ./scripts/clean-ssh.sh gcp + ${pkgs.colmena}/bin/colmena apply --on @azure + ''); + }; + + # nix run ".#local-vault" + local-vault = { + type = "app"; + program = toString (pkgs.writers.writeBash "local-vault" '' + set -euo pipefail + cd arion/ + arion up + ''); + }; + # nix run ".#local-k8s" + local-k8s = { + type = "app"; + program = toString (pkgs.writers.writeBash "local-k8s" '' + set -euo pipefail + scripts/k8s/local-k8s.sh + # scripts/k8s/configure.sh + ''); + }; }; # deploy @@ -191,6 +224,6 @@ in { meta = { nixpkgs = pkgs; }; defaults = import ./deploys/consul; - } // (genOutput "libvirt") // (genOutput "gcp"); + } // (genOutput "libvirt") // (genOutput "gcp") // (genOutput "azure"); }; } diff --git a/generators/minimal-azure.nix b/generators/minimal-azure.nix new file mode 100644 index 0000000..23f9fc9 --- /dev/null +++ b/generators/minimal-azure.nix @@ -0,0 +1,4 @@ +{ modulesPath, ... }: { + imports = + [ "${modulesPath}/virtualisation/azure-config.nix" ./minimal-default.nix ]; +} diff --git a/provision/azure/default.nix b/provision/azure/default.nix new file mode 100644 index 0000000..f520f21 --- /dev/null +++ b/provision/azure/default.nix @@ -0,0 +1,222 @@ +{ config, pkgs, ... }: +let inherit (pkgs) lib; +in { + options = with lib.types; + let + inherit (lib.opt) mk' mkBool'; + inherit (lib) mkOption; + azure = config.provision.azure; + networksModule = submodule ({ config, name, ... }: { + options = { + project = mk' str gcp.project "project"; + name = mk' str name "name of network"; + mtu = mk' int 1460 "Maximum Transmission Unit in bytes"; + description = mk' str "description of this resource" ""; + routing_mode = mk' (enum [ "GLOBAL" "REGIONAL" ]) "REGIONAL" + "The network-wide routing mode to use."; + auto_create_subnetworks = mkBool' false + "create a subnet for each region automatically across the 10.128.0.0/9 address range"; + delete_default_routes_on_create = mkBool' false + "If set to true, default routes (0.0.0.0/0) will be deleted immediately after network creation."; + subnetworks = mkOption { + type = (attrsOf subnetworksModule); + default = { }; + description = "subnetwork options"; + }; + }; + }); + + subnetworksModule = submodule ({ config, name, ... }: { + options = { + project = mk' str gcp.project "project"; + region = mk' str gcp.region "region name"; + name = mk' str name "name of subnetwork"; + cidr_range = mk' str "10.62.0.0/16" "cidr range network"; + network = mk' str config.name "network name"; + description = mk' str "subnetwork ${name}" "subnetwork description"; + secondary_ranges = mk' (listOf (submodule { + options = { + range_name = mk' str name "name-of-subnetwork"; + cidr_range = mk' str name "10.21.0.0/16"; + }; + })) [ ] "secondary ip range list"; + }; + }); + + imagesModule = submodule ({ config, name, ... }: { + options = { + project = mk' str gcp.project "project"; + location = mk' str gcp.region "location"; + labels = mk' (attrsOf str) { name = name; } "labels"; + name = mk' str name "name of image"; + zone = mk' str gcp.zone "name of image"; + family = mk' str "nixos" "name of family"; + description = mk' str "description ${name}" "images description"; + source = mk' str + "gs://nixos-images-gcp/nixos-image-21.05.4709.88579effa7e-x86_64-linux.raw.tar.z" + "path for imgs or name of another volume"; + + }; + }); + + replicasModule = submodule ({ config, name, ... }: { + options = { + project = mk' str gcp.project "project"; + name = mk' str name "name of replica"; + machine_type = mk' str "e2-micro" "type of machine"; + tags = mk' (listOf str) [ name ] "tags"; + image = mk' str "nixos" "image used by instances"; + zone = mk' str azure.zone "name of image"; + size = mk' int 20 "size of vm"; + network = mk' str "default" "network interface used"; + subnetwork = mk' str "n1" "subnetwork interface used"; + }; + }); + + in { + provision.azure = { + enable = mkBool' false "enable azure provision"; + project = mk' str "consul" "project name"; + region = mk' str "us-east1" "region name"; + zone = mk' str "us-east1-c" + "zone name. expected to be in same region setted, if not it takes priority over region"; + domain = mk' str "d" "domain"; + # network submodule + networks = mkOption { + type = (attrsOf networksModule); + default = { }; + description = "network options"; + }; + + # subnetwork submodule + subnetworks = mkOption { + type = (attrsOf subnetworksModule); + default = { }; + description = "subnetwork options"; + }; + + # images submodule + images = mkOption { + type = (attrsOf imagesModule); + default = { }; + description = "image options"; + }; + + # replica submodule + replicas = mkOption { + type = (attrsOf replicasModule); + default = { }; + description = "replicas options"; + }; + }; + }; + config = let + inherit (builtins) attrNames; + inherit (lib) mkIf readFile assertMsg; + inherit (lib.strings) removeSuffix; + inherit (pkgs.lib.cfg) attrsMap; + azure = config.provision.azure; + networks = azure.networks; + images = azure.images; + replicas = azure.replicas; + + in { + terraform.required_providers = + mkIf azure.enable { azurerm.source = "hashicorp/azurerm"; }; + provider.azurerm = mkIf azure.enable { + project = azure.project; + region = azure.region; + zone = azure.zone; + }; + + resource = mkIf gcp.enable { + google_storage_bucket = attrsMap images (name: { + ${name} = with images.${name}; { + inherit project location labels; + name = "${name}-${project}"; + # without it, will not destroy bucket with `destroy-gcp` + force_destroy = true; + }; + }); + google_storage_bucket_object = attrsMap images (name: { + ${name} = with images.${name}; { + inherit source; + name = "${name}.tar.gz"; + metadata = labels; + bucket = config.resource.google_storage_bucket.${name}.name; + # don't recreate it every time + lifecycle = { ignore_changes = [ "source" ]; }; + }; + }); + + google_compute_image = attrsMap images (name: { + ${name} = with images.${name}; { + inherit name project; + family = name; + raw_disk = { + source = "\${ google_storage_bucket_object.${name}.self_link }"; + container_type = "TAR"; + }; + }; + }); + + google_compute_network = attrsMap networks (name: { + ${name} = with networks.${name}; { + inherit project name mtu description routing_mode + auto_create_subnetworks delete_default_routes_on_create; + }; + }); + + google_compute_subnetwork = attrsMap networks (name: + let subnetworks = networks.${name}.subnetworks; + in attrsMap subnetworks (sname: { + ${sname} = let sub = subnetworks.${sname}; + in { + inherit (sub) project region; + name = sname; + ip_cidr_range = sub.cidr_range; + network = "\${ google_compute_network.${name}.id }"; + secondary_ip_range = map (v: { + range_name = v.range_name; + ip_cidr_range = v.cidr_range; + }) sub.secondary_ranges; + }; + })); + + google_compute_instance = attrsMap replicas (name: { + ${name} = with replicas.${name}; { + inherit name machine_type tags project zone; + network_interface = { + network = "\${ google_compute_network.${network}.self_link }"; + subnetwork = + "\${ google_compute_subnetwork.${subnetwork}.self_link }"; + access_config = { }; + }; + boot_disk = { + initialize_params = { + inherit size; + image = "\${ google_compute_image.${image}.self_link }"; + }; + }; + }; + }); + + }; + output = attrsMap replicas (name: + let + inherit (builtins) head; + repl = replicas.${name}; + pub = + "\${ google_compute_instance.${name}.network_interface.0.access_config.0.nat_ip }"; + priv = + "\${ google_compute_instance.${name}.network_interface.0.network_ip }"; + in { + ${name} = { + value = with gcp; { + inherit name domain; + ip = { inherit pub priv; }; + }; + }; + }); + }; +}