add: universal provider
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"default_timeout": "10m",
|
||||
"idle_timeout": "10m",
|
||||
"operations": {
|
||||
"create": "10m",
|
||||
"modify": "7m",
|
||||
"resume": "7m",
|
||||
"suspend": "7m",
|
||||
"create_user": "7m",
|
||||
"delete_user": "6m",
|
||||
"create_database": "7m",
|
||||
"delete_database": "6m"
|
||||
},
|
||||
"overrides": {
|
||||
"services.90.create": "7m"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package provider
|
||||
|
||||
import _ "embed"
|
||||
|
||||
//go:embed operation_timeouts.json
|
||||
var operationTimeoutsConfigEmbedded []byte
|
||||
@@ -0,0 +1,177 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"terraform-provider-nubes/internal/core"
|
||||
"terraform-provider-nubes/internal/resources_core"
|
||||
"terraform-provider-nubes/internal/resources_gen"
|
||||
|
||||
"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 = &NubesProvider{}
|
||||
|
||||
type NubesProvider struct {
|
||||
version string
|
||||
}
|
||||
|
||||
// NubesProviderModel — конфигурация провайдера из HCL-блока provider {}.
|
||||
// Каждое поле соответствует атрибуту в Schema() ниже.
|
||||
// Поля Optional: если не указаны — берутся из env-переменных или defaults.
|
||||
type NubesProviderModel struct {
|
||||
ApiEndpoint types.String `tfsdk:"api_endpoint"`
|
||||
ApiToken types.String `tfsdk:"api_token"`
|
||||
// Insecure отключает проверку TLS-сертификата сервера.
|
||||
// НЕ использовать в продакшн! Только для dev-стендов с самоподписанным сертом.
|
||||
// Может быть задан также через env NUBES_INSECURE=true.
|
||||
Insecure types.Bool `tfsdk:"insecure"`
|
||||
// LogLevel задаёт глобальный уровень вывода этапов операции.
|
||||
// "none" (default) — молчать. "info" — имя этапа + длительность.
|
||||
// "debug" — info + детали подэтапов (StageMsg без timestamp-мусора).
|
||||
// Может быть переопределён атрибутом log_level в отдельном ресурсе.
|
||||
LogLevel types.String `tfsdk:"log_level"`
|
||||
}
|
||||
|
||||
func New(version string) func() provider.Provider {
|
||||
return func() provider.Provider {
|
||||
return &NubesProvider{version: version}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *NubesProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
|
||||
resp.TypeName = "nubes"
|
||||
resp.Version = p.version
|
||||
}
|
||||
|
||||
func (p *NubesProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"api_endpoint": schema.StringAttribute{
|
||||
MarkdownDescription: "API Gateway endpoint for Nubes Cloud",
|
||||
Optional: true,
|
||||
},
|
||||
"api_token": schema.StringAttribute{
|
||||
MarkdownDescription: "API authentication token",
|
||||
Optional: true,
|
||||
Sensitive: true,
|
||||
},
|
||||
// insecure: отключает проверку TLS-сертификата Nubes API.
|
||||
// По умолчанию false — сертификат проверяется (безопасно).
|
||||
// Устанавливать true только на dev-стенде с самоподписанным сертом.
|
||||
// Альтернатива: env NUBES_INSECURE=true (не требует правки .tf файлов).
|
||||
"insecure": schema.BoolAttribute{
|
||||
MarkdownDescription: "Disable TLS certificate verification. Use only for dev environments with self-signed certs. Can also be set via NUBES_INSECURE env var.",
|
||||
Optional: true,
|
||||
},
|
||||
// log_level: уровень вывода информации об этапах операций.
|
||||
// Значение применяется ко всем ресурсам, если не переопределено в ресурсе.
|
||||
"log_level": schema.StringAttribute{
|
||||
MarkdownDescription: "Logging level for operation stages. Values: `none` (default, silent), `info` (stage name + duration), `debug` (info + detailed sub-step messages). Can be overridden per resource.",
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *NubesProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
|
||||
var config NubesProviderModel
|
||||
|
||||
resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
apiEndpoint := "https://deck-api.ngcloud.ru/api/v1/index.cfm"
|
||||
apiToken := ""
|
||||
|
||||
if !config.ApiEndpoint.IsNull() {
|
||||
apiEndpoint = config.ApiEndpoint.ValueString()
|
||||
}
|
||||
|
||||
if !config.ApiToken.IsNull() {
|
||||
apiToken = strings.TrimSpace(config.ApiToken.ValueString())
|
||||
} else {
|
||||
if token := os.Getenv("NUBES_API_TOKEN"); token != "" {
|
||||
apiToken = strings.TrimSpace(token)
|
||||
}
|
||||
}
|
||||
|
||||
// --- TLS: определяем нужно ли пропустить проверку сертификата ---
|
||||
// Приоритет: config.insecure > env NUBES_INSECURE > false (безопасный default).
|
||||
// Nubes Cloud API использует валидный TLS-сертификат от доверенного CA,
|
||||
// поэтому в продакшн InsecureSkipVerify должен быть false.
|
||||
// true оставлен только для совместимости с dev-стендами без нормального сертификата.
|
||||
insecureSkipVerify := false
|
||||
if !config.Insecure.IsNull() && !config.Insecure.IsUnknown() {
|
||||
// Явно задано в provider {} блоке HCL
|
||||
insecureSkipVerify = config.Insecure.ValueBool()
|
||||
} else if os.Getenv("NUBES_INSECURE") == "true" {
|
||||
// Задано через переменную окружения (удобно для CI/CD без правки .tf файлов)
|
||||
insecureSkipVerify = true
|
||||
}
|
||||
|
||||
// HTTP transport: клонируем DefaultTransport чтобы сохранить системные настройки (proxy, timeouts).
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
transport.TLSHandshakeTimeout = 60 * time.Second
|
||||
// Force HTTP/1.1: Nubes API не поддерживает HTTP/2, принудительно отключаем.
|
||||
// MinVersion TLS 1.2 — минимально безопасная версия TLS.
|
||||
transport.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: insecureSkipVerify, // false в prod, true только для dev
|
||||
NextProtos: []string{"http/1.1"},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
transport.ForceAttemptHTTP2 = false
|
||||
|
||||
// Определяем уровень логирования операций: none (тихий) / info / debug.
|
||||
// none — дефолт, не засорять вывод terraform apply лишними строками.
|
||||
logLevel := "none"
|
||||
if !config.LogLevel.IsNull() && !config.LogLevel.IsUnknown() {
|
||||
if v := strings.TrimSpace(config.LogLevel.ValueString()); v != "" {
|
||||
logLevel = v
|
||||
}
|
||||
}
|
||||
|
||||
client := &core.UniversalClient{
|
||||
HttpClient: &http.Client{
|
||||
Transport: transport,
|
||||
Timeout: 300 * time.Second,
|
||||
},
|
||||
ApiEndpoint: apiEndpoint,
|
||||
ApiToken: apiToken,
|
||||
ProviderVersion: p.version,
|
||||
OperationTimeouts: core.DefaultOperationTimeouts(),
|
||||
LogLevel: logLevel,
|
||||
}
|
||||
|
||||
if len(operationTimeoutsConfigEmbedded) > 0 {
|
||||
timeouts, err := core.LoadOperationTimeoutsFromBytes(operationTimeoutsConfigEmbedded)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Ошибка загрузки таймаутов операций", err.Error())
|
||||
return
|
||||
}
|
||||
client.OperationTimeouts = timeouts
|
||||
}
|
||||
|
||||
resp.DataSourceData = client
|
||||
resp.ResourceData = client
|
||||
}
|
||||
|
||||
func (p *NubesProvider) Resources(ctx context.Context) []func() resource.Resource {
|
||||
resources := resources_gen.AllResources()
|
||||
resources = append(resources, resources_core.NewServiceOperationResource)
|
||||
return resources
|
||||
}
|
||||
|
||||
func (p *NubesProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user