feat: Terraform провайдер sless v0.1.0 + обновление doc/progress.md

Независимый Go-модуль terraform/provider/ для управления функциями через REST API.

Ресурсы:
- sless_function: CRUD + upload zip + WaitReady (kaniko build 5 мин)
- sless_trigger: CRUD (http/cron)

Компоненты:
- internal/client/client.go   — HTTP-клиент, готов к переносу в nubes
- internal/provider/provider.go — паттерн идентичен nubes NubesProvider
- internal/resources/           — function_resource.go, trigger_resource.go
- hack/build-and-publish.sh    — GPG-подпись + mc upload в S3

Опубликовано: terra.k8c.ru/naeel/sless v0.1.0
Проверено: terraform init успешен
This commit is contained in:
“Naeel”
2026-03-07 10:23:52 +04:00
parent 4115e0f172
commit 19c9e016a8
10 changed files with 1193 additions and 6 deletions
@@ -0,0 +1,104 @@
// 2026-03-07
// provider.go — описание провайдера sless для Terraform.
// Паттерн идентичен nubes провайдеру (NubesProvider) — для облегчения переноса.
// Атрибуты: endpoint (URL оператора) + token (Bearer).
// Env-переменные: SLESS_ENDPOINT, SLESS_API_TOKEN.
package provider
import (
"context"
"os"
"strings"
"terraform-provider-sless/internal/client"
"terraform-provider-sless/internal/resources"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"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"
)
var _ provider.Provider = &SlessProvider{}
type SlessProvider struct {
version string
}
// SlessProviderModel — конфигурация блока provider {} в .tf файле.
type SlessProviderModel struct {
Endpoint types.String `tfsdk:"endpoint"`
Token types.String `tfsdk:"token"`
}
// New возвращает фабрику провайдера — точная копия паттерна nubes.
func New(version string) func() provider.Provider {
return func() provider.Provider {
return &SlessProvider{version: version}
}
}
func (p *SlessProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "sless"
resp.Version = p.version
}
func (p *SlessProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"endpoint": schema.StringAttribute{
MarkdownDescription: "sless operator API endpoint, например http://sless-operator.sless.svc:9090",
Optional: true,
},
"token": schema.StringAttribute{
MarkdownDescription: "Bearer-токен аутентификации (env: SLESS_API_TOKEN)",
Optional: true,
Sensitive: true,
},
},
}
}
// Configure инициализирует HTTP-клиент и кладёт его в ResourceData/DataSourceData.
// Ресурсы получают клиент через Configure(req.ProviderData).
func (p *SlessProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
var config SlessProviderModel
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
if resp.Diagnostics.HasError() {
return
}
endpoint := "http://localhost:9090"
token := ""
if !config.Endpoint.IsNull() && config.Endpoint.ValueString() != "" {
endpoint = config.Endpoint.ValueString()
} else if v := os.Getenv("SLESS_ENDPOINT"); v != "" {
endpoint = v
}
if !config.Token.IsNull() {
token = strings.TrimSpace(config.Token.ValueString())
}
if token == "" {
if v := os.Getenv("SLESS_API_TOKEN"); v != "" {
token = strings.TrimSpace(v)
}
}
c := client.New(endpoint, token)
resp.ResourceData = c
resp.DataSourceData = c
}
func (p *SlessProvider) Resources(_ context.Context) []func() resource.Resource {
return []func() resource.Resource{
resources.NewFunctionResource,
resources.NewTriggerResource,
}
}
func (p *SlessProvider) DataSources(_ context.Context) []func() datasource.DataSource {
return nil
}