Skip to content

Commit

Permalink
WIP: import github resources into terraform
Browse files Browse the repository at this point in the history
  • Loading branch information
zimbatm committed Feb 25, 2024
1 parent 6a0a494 commit 3805a2c
Show file tree
Hide file tree
Showing 8 changed files with 5,347 additions and 3 deletions.
17 changes: 17 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.systems.url = "github:nix-systems/default";
inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
inputs.treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
inputs.treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
inputs.opentofu-registry = {
url = "github:opentofu/registry";
flake = false;
};

outputs =
{
self,
nixpkgs,
systems,
treefmt-nix,
}:
...
}@inputs:
let
eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
in
Expand All @@ -22,7 +29,10 @@
default = pkgs.mkShell {
packages = [
pkgs.findutils
pkgs.gh
pkgs.gnumake
pkgs.jq
(pkgs.callPackage ./tofu { inherit (inputs) opentofu-registry; })
];
};
}
Expand Down
2 changes: 2 additions & 0 deletions tofu/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.terraform*
terraform.tfstate*
66 changes: 66 additions & 0 deletions tofu/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright manveru. https://gist.github.com/manveru/bcd2b4e0d3a30abbdec19573083b34b7
{
fetchurl,
go,
lib,
opentofu,
opentofu-registry,
stdenv,
unzip,
}:
let
mkTerraformProvider =
{
owner,
repo,
version,
src,
registry ? "registry.opentofu.org",
}:
let
inherit (go) GOARCH GOOS;
provider-source-address = "${registry}/${owner}/${repo}";
in
stdenv.mkDerivation {
pname = "terraform-provider-${repo}";
inherit version src;

unpackPhase = "unzip -o $src";

nativeBuildInputs = [ unzip ];

buildPhase = ":";

# The upstream terraform wrapper assumes the provider filename here.
installPhase = ''
dir=$out/libexec/terraform-providers/${provider-source-address}/${version}/${GOOS}_${GOARCH}
mkdir -p "$dir"
mv terraform-* "$dir/"
'';

passthru = {
inherit provider-source-address;
};
};

readJSON = f: builtins.fromJSON (lib.readFile f);

# fetch the latest version
providerFor =
owner: repo:
let
json = readJSON (opentofu-registry + "/providers/${lib.substring 0 1 owner}/${owner}/${repo}.json");
latest = lib.head json.versions;
matching = lib.filter (e: e.os == "linux" && e.arch == "amd64") latest.targets;
target = lib.head matching;
in
mkTerraformProvider {
inherit (latest) version;
inherit owner repo;
src = fetchurl {
url = target.download_url;
sha256 = target.shasum;
};
};
in
opentofu.withPlugins (_: [ (providerFor "integrations" "github") ])
73 changes: 73 additions & 0 deletions tofu/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env ruby
#

require "json"
require "pp"

TF = "tofu"
ORG = "NixOS"

# Just wrap `gh`, it's easier than to depend on Octokit
def gh(*command)
# HACK: assume there are less than 500 items
# HACK: assume that the command doesn't require shell escaping
IO.popen("gh --limit=500 #{command.map(&:to_s).join(" ")}") do |io|
JSON.load(io)
end
end


def tf(*command)
system(TF, *command.map(&:to_s))
end

def tf!(*command)
if !tf(*command)
throw "terraform command #{command.join(" ")} failed"
end
end

### Import Organization settings

org_id = gh(:api, "/orgs/#{ORG}", "--jq", ".id").strip

File.open("import_org.tf", "w") do |f|
f.puts(<<~EOM)
import {
id = "#{org_id}"
to = github_organization_settings.#{ORG}
}
EOM
end

### Import REPOS ###

repos = gh(:repo, :list, ORG, "--json=name")

File.open("import_repos.tf", "w") do |f|
repos.each do |repo|
name = repo["name"]

id_name = name.gsub(".", "_dot_").gsub(/\d/, "_")

f.puts(<<~EOM)
import {
id = "#{name}"
to = github_repository.#{id_name}
}
import {
id = "#{name}"
to = github_repository_collaborators.#{id_name}
}
EOM
end
end

### TODO: import teams


### Import the resources in the terraform state and generate the terraform resources

tf!(:plan, "-generate-config-out=repos.tf")
Loading

0 comments on commit 3805a2c

Please sign in to comment.