hhctl CLI and Terraform provider for Hammerhead
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
bf340cdab4
19 files changed
+2442
No files matched your search
@@ -0,0 +1,92 @@
|
||||
// Package provider is the Terraform provider for Hammerhead.
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider"
|
||||
"github.com/hashicorp/terraform-plugin-framework/provider/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
|
||||
"git.veillax.com/Veillax/hhctl/client"
|
||||
)
|
||||
|
||||
type hammerheadProvider struct{ version string }
|
||||
|
||||
// New returns a provider factory.
|
||||
func New(version string) func() provider.Provider {
|
||||
return func() provider.Provider { return &hammerheadProvider{version} }
|
||||
}
|
||||
|
||||
type providerModel struct {
|
||||
URL types.String `tfsdk:"url"`
|
||||
Token types.String `tfsdk:"token"`
|
||||
Org types.String `tfsdk:"org"`
|
||||
}
|
||||
|
||||
func (p *hammerheadProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
|
||||
resp.TypeName = "hammerhead"
|
||||
resp.Version = p.version
|
||||
}
|
||||
|
||||
func (p *hammerheadProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manage a Hammerhead control plane: sites, ports, domains, edges and alert channels.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"url": schema.StringAttribute{Optional: true, Description: "Hammerhead address, e.g. https://hammerhead.example.com. Defaults to $HAMMERHEAD_URL."},
|
||||
"token": schema.StringAttribute{Optional: true, Sensitive: true, Description: "API key (hhk_...). An organization key manages that organization; edges and server alert channels need a server key. Defaults to $HAMMERHEAD_TOKEN."},
|
||||
"org": schema.StringAttribute{Optional: true, Description: "Organization ID. Optional with an organization key. Defaults to $HAMMERHEAD_ORG."},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func orDefault(v types.String, env string) string {
|
||||
if !v.IsNull() && !v.IsUnknown() {
|
||||
return v.ValueString()
|
||||
}
|
||||
return os.Getenv(env)
|
||||
}
|
||||
|
||||
func (p *hammerheadProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
|
||||
var cfg providerModel
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &cfg)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
for _, v := range []struct {
|
||||
name string
|
||||
val types.String
|
||||
}{{"url", cfg.URL}, {"token", cfg.Token}, {"org", cfg.Org}} {
|
||||
if v.val.IsUnknown() {
|
||||
resp.Diagnostics.AddAttributeError(path.Root(v.name), "Unknown "+v.name, "The value must be known when the provider is configured.")
|
||||
}
|
||||
}
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
url, token := orDefault(cfg.URL, "HAMMERHEAD_URL"), orDefault(cfg.Token, "HAMMERHEAD_TOKEN")
|
||||
if url == "" || token == "" {
|
||||
resp.Diagnostics.AddError("Missing configuration", "Set url and token in the provider block, or HAMMERHEAD_URL and HAMMERHEAD_TOKEN.")
|
||||
return
|
||||
}
|
||||
c := client.New(url, token, orDefault(cfg.Org, "HAMMERHEAD_ORG"))
|
||||
resp.ResourceData, resp.DataSourceData = c, c
|
||||
}
|
||||
|
||||
func (p *hammerheadProvider) Resources(context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{NewSite, NewPort, NewDomain, NewEdge, NewAlertChannel}
|
||||
}
|
||||
|
||||
func (p *hammerheadProvider) DataSources(context.Context) []func() datasource.DataSource {
|
||||
return []func() datasource.DataSource{NewEdgeData}
|
||||
}
|
||||
|
||||
// clientFrom pulls the configured client out of ProviderData (nil before Configure ran).
|
||||
func clientFrom(data any) *client.Client {
|
||||
c, _ := data.(*client.Client)
|
||||
return c
|
||||
}
|
||||
Reference in new issue
Block a user