Blog

Bauen Sie Ihren eigenen Terraform Provider mit Claude

Marta Radziszewska

Marta Radziszewska

Aktualisiert Mai 20, 2026
10 Minuten

Einführung

Terraform-Anbieter fühlen sich oft wie eine Blackbox an. Sie deklarieren Ressourcen, führen terraform apply aus, und irgendetwas macht irgendwo die richtigen API-Aufrufe. In diesem Beitrag öffne ich diese Box - indem ich selbst einen Provider baue, ohne Go wirklich zu kennen, und mit viel Hilfe von Claude.

Dies ist eine Schritt-für-Schritt-Anleitung für den Aufbau Ihres eigenen Terraform-Providers. Ganz gleich, ob Sie neugierig sind, wie Provider unter der Haube funktionieren, oder ob Sie eine benutzerdefinierte API haben, die Sie über Terraform verwalten möchten, diese Anleitung führt Sie von Null zu einem funktionierenden Provider. Keine Go-Erfahrung erforderlich.

Ein Terraform-Provider ist im Wesentlichen eine Abstraktionsschicht über einer API: Wenn ein Service CRUD-Operationen anbietet, können Sie ihn in einen Provider verpacken und ihn über Terraform wie jedes andere Stück Infrastruktur verwalten. Ich habe dieses Projekt "vibe-codiert", indem ich die API beschrieb und Claude den größten Teil der Struktur generieren ließ und dann iterierte, um zu verstehen, wie alles zusammenpasst.

Implementieren eines Anbieters

Im Kern ist ein Terraform-Anbieter eine strukturierte Schicht, die die deklarative Konfiguration in API-Aufrufe übersetzt. Sobald diese Struktur verstanden ist, wird die gesamte Implementierung wesentlich einfacher.

Terraform-Anbieter sind in der Praxis in Go implementiert. Obwohl das Plugin-System von Terraform technisch gesehen sprachunabhängig ist, unterstützt HashiCorp offiziell nur Go durch seine SDKs und Frameworks.

Da ich selbst nicht viel Erfahrung mit Go habe, habe ich mich auf Claude verlassen, um die erste Implementierung zu erstellen, und dann von dort aus gearbeitet, um sie zu verstehen und zu verfeinern.

Voraussetzungen

Um mitzumachen, benötigen Sie:

  • Installiert gehen
  • Terraform installiert

Was macht eine API geeignet?

Ein Terraform-Anbieter kann für jede API erstellt werden, die grundlegende CRUD-Operationen unterstützt:

  • Ein Objekt erstellen
  • Rufen Sie dieses Objekt ab
  • Aktualisieren Sie das Objekt
  • Löschen Sie das Objekt

Dies entspricht direkt dem Ressourcen-Lebenszyklus von Terraform.

Generierung der ersten Implementierung

Die API, mit der ich arbeitete, war nicht gut dokumentiert. Anstatt Claude auf eine Dokumentationsseite zu verweisen, habe ich selbst eine Reihe von Referenzdateien erstellt:

  • Eine Datei, die alle API-Endpunkte auflistet, gruppiert nach Operation (Erstellen, Lesen, Aktualisieren, Löschen), zusammen mit allen erforderlichen Abfrageparametern
  • Eine Reihe von JSON-Dateien mit Beispiel-Nutzdaten für Anfragen und Antworten, eine pro Endpunkt, für den eine Nutzdatenangabe erforderlich war

Wenn die API, mit der Sie arbeiten, über eine gute Dokumentation verfügt, können Sie diesen Schritt ganz überspringen und Claude stattdessen einen Link zu dieser Dokumentation geben. In meinem Fall hat sich die manuelle Erstellung der Dateien gelohnt, da ich dadurch auch gezwungen war, die API zu verstehen, bevor ich etwas generierte.

Nachdem diese Dateien vorhanden waren, war die Eingabeaufforderung einfach:

Build a Terraform provider based on the example APIs found in path/to/your/files/

Auf dieser Grundlage erstellte sie einen Anbieter mit der folgenden Struktur:

.
├── internal
│   ├── client
│   │   └── client.go
│   └── provider
│       ├── example_resource_1.go
│       ├── example_resource_2.go
│       └── provider.go
├── go.mod
├── go.sum
└── main.go

Auf den ersten Blick mag diese Struktur kompliziert erscheinen, aber das meiste davon ist eine Standardvorlage.

Die Dateien go.mod und go.sum verwalten Abhängigkeiten und erfordern im Allgemeinen keine manuellen Änderungen.

main.go

Diese Datei dient als Einstiegspunkt für den Anbieter.

Wenn Terraform die Provider-Binärdatei startet, initialisiert main.go den Provider und richtet die Kommunikationsschicht zwischen Terraform und dem Plugin ein.

Sie definiert auch die Anbieteradresse, die von Terraform verwendet wird, um den Anbieter zu identifizieren. Diese Adresse wird bei der Veröffentlichung in der Terraform Registry relevant. Bis dahin fungiert sie als interner Bezeichner und muss nicht mit einem realen oder veröffentlichten Anbieter übereinstimmen.

client.go

Die Datei client.go ist dafür verantwortlich, wie der Anbieter mit der externen API kommuniziert.

Es umfasst in der Regel:

  • Konfiguration wie die Basis-URL und Authentifizierungsdetails
  • Ein HTTP-Client
  • Hilfsmethoden für die Erstellung von API-Anfragen

Diese Schicht abstrahiert die HTTP-Logik vom Rest des Providers.

provider.go

Die Datei provider.go verbindet die Benutzerkonfiguration mit dem API-Client.

Er liest Konfigurationswerte (z.B. API-Anmeldeinformationen), initialisiert den Client und macht ihn für alle vom Anbieter verwalteten Ressourcen verfügbar.

Diese Datei fungiert quasi als Brücke zwischen der Terraform-Konfiguration und dem zugrunde liegenden API-Client.

.gehen

Jede Ressourcendatei definiert, wie Terraform ein bestimmtes Objekt verwaltet, das von der API bereitgestellt wird.

Eine Ressourcenimplementierung besteht aus mehreren Schlüsselkomponenten:

Die Modellstruktur ist ein Entwurf dessen, was Terraform in seiner Statusdatei speichert - jedes Attribut, das der Benutzer konfigurieren kann, wird hier einem Feld zugeordnet.

type exampleServiceModel struct {
    ID   types.String `tfsdk:"id"`
    Name types.String `tfsdk:"name"`
    ...
}

Das Schema, das beschreibt, was die Benutzer in ihren .tf-Dateien angeben müssen, um die Ressource korrekt zu initialisieren. Es deklariert jedes Attribut - ob es erforderlich, optional oder vom Server berechnet ist - und dokumentiert, was jedes einzelne tut.

func (r *exampleServiceResource) Schema(...) {
  // defines all attributes
}

Die CRUD-Methoden, vier Funktionen, die den Lebenszyklus einer Ressource implementieren:

  • Erstellen - wird aufgerufen, wenn eine Ressource erstellt wird
  • Lesen - aktualisiert den Terraform-Status mit Daten aus der API
  • Aktualisieren - wendet Konfigurationsänderungen an
  • Löschen - Entfernt die Ressource

Jeder liest aus dem Plan/Zustand, ruft die API über den Client auf und schreibt das Ergebnis zurück in den Zustand.

Die Helper-Methoden werden zur Übersetzung zwischen Terraform und der API verwendet:

  • toAPIRequest wandelt den Terraform-Status in eine API-Anfrage um
  • applyAPIResponse bildet die API-Antwort zurück in den Terraform-Status

Durch diese Trennung bleibt die CRUD-Logik fokussiert und ist leichter zu pflegen.

Den Provider testen

Da ich keine Erfahrung mit Go habe und mich bei der Implementierung und den Tests stark auf KI verließ, konzentrierte ich mich hauptsächlich auf die Validierung des Anbieters durch manuelle End-to-End-Tests.

Das Ziel war einfach: den Anbieter lokal zu verwenden und zu überprüfen, ob Terraform erfolgreich Ressourcen über die API erstellen, lesen, aktualisieren und löschen kann.

Terraform bietet über die Konfiguration dev_overrides einen eingebauten Mechanismus für die lokale Entwicklung von Providern. Wenn dev_overrides konfiguriert ist, überspringt Terraform das Herunterladen des Providers aus der Registry und verwendet stattdessen eine lokal kompilierte Binärdatei. Während terraform init sehen Sie eine Warnung wie die folgende:

Dies ist zu erwarten und zeigt an, dass Terraform Ihren lokalen Anbieter verwendet. Dieser Ansatz ermöglichte es, den Anbieter iterativ zu testen und sein Verhalten zu validieren, ohne ihn zu veröffentlichen, was die Entwicklung erheblich beschleunigt.

Testverfahren

Kompilieren Sie zunächst den Anbieter mit Go: go build. Dies erzeugt eine Binärdatei, die Terraform ausführen kann.

Als nächstes konfigurieren Sie die Terraform CLI so, dass sie auf Ihr lokales Build verweist. Dies geschieht in der CLI-Konfigurationsdatei (~/.terraformrc oder terraform.rc):

provider_installation {
  dev_overrides {
    "registry.terraform-registry/example/example_provider" = "/path/to/your/provider/binary"
  }
  direct {}
}

Dies sagt Terraform: Wenn dieser Anbieter angefordert wird, verwenden Sie die lokale Binärdatei, anstatt sie herunterzuladen.

Die Terraform-Konfiguration selbst muss nicht geändert werden. Sie können den Anbieter so referenzieren, als ob er veröffentlicht wäre:

terraform {
  required_providers {
    example = {
      source = "registry.terraform-registry/example/example_provider"
    }
  }
}

provider "example" {
  host  = "https://your-api-example.com"
  token = "your-token"
}

Aus der Sicht von Terraform ändert sich nichts - es löst den Anbieter einfach lokal auf, anstatt ihn aus der Registry zu holen.

Anmerkungen und Fehlerquellen

  • Wenn Sie lokal testen, empfiehlt es sich, ein lokales Backend zu verwenden, um Interferenzen mit einem entfernten Status zu vermeiden.
  • Wenn Sie die kompilierte Binärdatei in einem Plugins-Verzeichnis ablegen, kann es sein, dass Terraform sie auch dann noch verwendet, wenn Sie beabsichtigen, wieder zu einer Registrierungsversion zu wechseln. Entfernen Sie in diesem Fall die lokale Binärdatei, um sicherzustellen, dass Terraform die richtige Version herunterlädt.
  • Rechnen Sie mit einigen Versuchen und Fehlern - vor allem, wenn die Implementierung generiert wird -, da das Debuggen des Providerverhaltens weniger einfach sein kann als bei typischem Anwendungscode.

Freigeben von

Sobald der Anbieter lokal funktioniert, besteht der nächste Schritt darin, ihn zu paketieren und freizugeben, damit er in größerem Umfang genutzt werden kann. Terraform-Anbieter werden in der Regel mit GoReleaser veröffentlicht, einem Tool, das die Erstellung von Binärdateien, deren Paketierung und die Veröffentlichung von Veröffentlichungen automatisiert.

Ich habe Claude verwendet, um den GitHub Actions Workflow zu erstellen. Eine Sache, auf die Sie in der Eingabeaufforderung ausdrücklich hinweisen sollten, ist die GPG-Signierung. Die Terraform Registry verlangt, dass die SHA256SUMS-Datei signiert wird, und es ist leicht möglich, dass ein Workflow entsteht, der vollständig aussieht, aber diesen Schritt überspringt. Die von mir verwendete Eingabeaufforderung lautete:

Create a GitHub Actions workflow that releases the provider, triggered on version tag pushes. The release should sign the SHA256SUMS file with a GPG key stored in GitHub secrets.

Der Freigabeprozess wird durch eine Konfigurationsdatei gesteuert: .goreleaser.yml. Diese Datei enthält Konfigurationen wie z.B. für welche Distributionen die Dateien generiert werden sollen oder alles, was Sie vor der Freigabe ausführen möchten (wie z.B. Linting). Ein Beispiel finden Sie in dieser Beispielkonfiguration. Claude hat diese Datei selbständig für mich erstellt.

Sobald diese Datei definiert ist, kann die Freigabe einer neuen Version so einfach sein wie die Ausführung von: goreleaser release.

Dieser Befehl:

  1. Baut den Anbieter für mehrere Plattformen
  2. Packen Sie die Binärdateien
  3. Erzeugt Prüfsummen
  4. Veröffentlichen Sie eine Veröffentlichung (z.B. auf GitHub)

Was wird veröffentlicht?

Ein Terraform Provider Release ist nicht nur eine einzelne Binärdatei. Sie besteht aus mehreren Komponenten, die Terraform verwendet, um den Provider sicher zu installieren und zu verifizieren. Nachdem Sie GoReleaser ausgeführt haben, sehen Ihre Release-Artefakte (zum Beispiel in einer GitHub-Veröffentlichung) in der Regel so aus:

terraform-provider-example_0.0.1_SHA256SUMS
terraform-provider-example_0.0.1_SHA256SUMS.sig

terraform-provider-example_0.0.1_darwin_amd64.zip
terraform-provider-example_0.0.1_darwin_arm64.zip
terraform-provider-example_0.0.1_linux_amd64.zip
terraform-provider-example_0.0.1_linux_arm64.zip
terraform-provider-example_0.0.1_windows_amd64.zip

Terraform lädt das richtige Archiv auf der Grundlage des Betriebssystems und der Architektur des Benutzers herunter.

  • Die ZIP-Dateien enthalten die eigentlichen Provider-Binärdateien
  • Die SHA256SUMS-Datei enthält Prüfsummen für alle Artefakte
  • Die Signaturdatei (.sig) wird verwendet, um die Prüfsummen zu verifizieren

Diese Dateien verwendet Terraform unter der Haube, wenn es einen Provider aus der Registrierung installiert.

Veröffentlichung in der Terraform-Registry

Um einen Anbieter in der Terraform Registry zu veröffentlichen, müssen die Release-Artefakte einer bestimmten Struktur und Namenskonvention folgen.

Außerdem muss die Quelladresse des Anbieters (die zuvor in main.go und der Terraform-Konfiguration definiert wurde) mit dem Repository und dem Namensraum übereinstimmen, unter dem der Anbieter veröffentlicht wird.

Gerüst als Referenz verwenden

Wenn Sie sich nicht sicher sind, ob Sie die richtige Struktur oder das richtige Release-Setup gewählt haben, stellt HashiCorp ein Framework zur Verfügung, das Arbeitsbeispiele für die Provider-Implementierung und die Release-Konfiguration enthält: terraform-provider-scaffolding-framework

Dies kann ein nützliches Nachschlagewerk sein, wenn Sie Ihren eigenen Provider einrichten oder Probleme bei der Veröffentlichung beheben wollen.

Fazit

Die Erstellung eines Terraform-Providers war viel einfacher als erwartet. Sobald Sie die Struktur - Provider, Client und Ressourcen - verstanden haben, geht es nur noch darum, den Lebenszyklus von Terraform auf API-Aufrufe abzubilden.

Die Verwendung von Claude für den größten Teil der Implementierung ermöglichte einen schnellen Einstieg, auch ohne vorherige Go-Erfahrung. Dieser Ansatz ist zwar mit Abstrichen verbunden (vor allem bei der Codequalität und dem tieferen Verständnis), aber er ist ein überraschend effektiver Weg, um herauszufinden, wie Anbieter in der Praxis funktionieren.

Es handelte sich nicht um eine produktionsreife Implementierung, aber es reichte aus, um die beweglichen Teile zu verstehen und das Konzept durchgängig zu validieren.

Wenn Sie mit einer API arbeiten, die noch nicht von Terraform unterstützt wird, oder wenn Sie interne Systeme in Ihre Infrastruktur-Workflows integrieren möchten, ist die Erstellung eines benutzerdefinierten Anbieters eine praktikable Option - und viel weniger einschüchternd, als es zunächst scheint.

Verfasst von

Marta Radziszewska

Data Engineer

Contact

Let’s discuss how we can support your journey.