package provider
import (
"context"
"crypto/tls"
"net/http"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"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/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
log "github.com/sirupsen/logrus"
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
sdk_config "repository.basistech.ru/BASIS/decort-golang-sdk/config"
)
// enumerated constants that define authentication modes for Configure
const (
MODE_UNDEF = iota // this is the invalid mode - it should never be seen
MODE_LEGACY
MODE_DECS3O
MODE_JWT
MODE_BVS
)
// Ensure DynamixProvider satisfies various provider interfaces.
var _ provider . Provider = & DynamixProvider { }
// DynamixProvider defines the provider implementation.
type DynamixProvider struct {
// version is set to the provider version on release, "dev" when the
// provider is built and ran locally, and "test" when running acceptance
// testing.
version string
}
// dynamixProviderModel describes the provider data model.
type dynamixProviderModel struct {
Authenticator types . String ` tfsdk:"authenticator" `
Oauth2Url types . String ` tfsdk:"oauth2_url" `
ControllerUrl types . String ` tfsdk:"controller_url" `
User types . String ` tfsdk:"user" `
Password types . String ` tfsdk:"password" `
BvsUser types . String ` tfsdk:"bvs_user" `
BvsPassword types . String ` tfsdk:"bvs_password" `
Domain types . String ` tfsdk:"domain" `
AppId types . String ` tfsdk:"app_id" `
AppSecret types . String ` tfsdk:"app_secret" `
Jwt types . String ` tfsdk:"jwt" `
AllowUnverifiedSsl types . Bool ` tfsdk:"allow_unverified_ssl" `
PathConfig types . String ` tfsdk:"path_config" `
PathToken types . String ` tfsdk:"path_token" `
TimeToRefresh types . Int64 ` tfsdk:"time_to_refresh" `
}
func ( p * DynamixProvider ) Metadata ( _ context . Context , _ provider . MetadataRequest , resp * provider . MetadataResponse ) {
resp . TypeName = "dynamix"
resp . Version = p . version
}
func ( p * DynamixProvider ) Schema ( _ context . Context , _ provider . SchemaRequest , resp * provider . SchemaResponse ) {
resp . Schema = schema . Schema {
Attributes : map [ string ] schema . Attribute {
"authenticator" : schema . StringAttribute {
MarkdownDescription : "Authentication mode to use when connecting to DYNAMIX cloud API. Should be one of 'decs3o', 'legacy', 'jwt' or 'bvs'." ,
Required : true ,
Validators : [ ] validator . String {
stringvalidator . OneOfCaseInsensitive ( "decs3o" , "legacy" , "jwt" , "bvs" ) , // ignore case while validating
} ,
} ,
"oauth2_url" : schema . StringAttribute {
MarkdownDescription : "OAuth2 application URL in 'decs3o' and 'bvs' authentication mode." ,
Optional : true ,
} ,
"controller_url" : schema . StringAttribute {
MarkdownDescription : "URL of DYNAMIX Cloud controller to use. API calls will be directed to this URL." ,
Required : true ,
} ,
"user" : schema . StringAttribute {
MarkdownDescription : "User name for DYNAMIX cloud API operations in 'legacy' authentication mode." ,
Optional : true ,
} ,
"password" : schema . StringAttribute {
MarkdownDescription : "User password for DYNAMIX cloud API operations in 'legacy' authentication mode." ,
Optional : true ,
} ,
"bvs_user" : schema . StringAttribute {
MarkdownDescription : "User name for DYNAMIX cloud API operations in 'bvs' authentication mode." ,
Optional : true ,
} ,
"bvs_password" : schema . StringAttribute {
MarkdownDescription : "User password for DYNAMIX cloud API operations in 'bvs' authentication mode." ,
Optional : true ,
} ,
"domain" : schema . StringAttribute {
MarkdownDescription : "User password for DYNAMIX cloud API operations in 'bvs' authentication mode." ,
Optional : true ,
} ,
"app_id" : schema . StringAttribute {
MarkdownDescription : "Application ID to access DYNAMIX cloud API in 'decs3o' and 'bvs' authentication mode." ,
Optional : true ,
} ,
"app_secret" : schema . StringAttribute {
MarkdownDescription : "Application secret to access DYNAMIX cloud API in 'decs3o' and 'bvs' authentication mode." ,
Optional : true ,
} ,
"jwt" : schema . StringAttribute {
MarkdownDescription : "JWT to access DYNAMIX cloud API in 'jwt' authentication mode." ,
Optional : true ,
} ,
"allow_unverified_ssl" : schema . BoolAttribute {
MarkdownDescription : "If true, DYNAMIX API will not verify SSL certificates. Use this with caution and in trusted environments only! Default is false." ,
Optional : true ,
} ,
"path_config" : schema . StringAttribute {
MarkdownDescription : "The path of the configuration file entry." ,
Optional : true ,
} ,
"path_token" : schema . StringAttribute {
MarkdownDescription : "The path of the token file entry." ,
Optional : true ,
} ,
"time_to_refresh" : schema . Int64Attribute {
MarkdownDescription : "The number of minutes before the expiration of the token, a refresh will be made." ,
Optional : true ,
} ,
} ,
}
}
func ( p * DynamixProvider ) Configure ( ctx context . Context , req provider . ConfigureRequest , resp * provider . ConfigureResponse ) {
// Retrieve provider data from configuration
var config dynamixProviderModel
diags := req . Config . Get ( ctx , & config )
resp . Diagnostics . Append ( diags ... )
if resp . Diagnostics . HasError ( ) {
resp . Diagnostics . AddError ( "Provider Configure: " , "error after req.Config.Get" )
log . Error ( "Provider Configure error after req.Config.Get" )
return
}
// Set up default values, values from env and save user provided values into dynamixConfig
dynamixConfig := dynamixProviderConfig { }
dynamixConfig . new ( config )
// Validate and set up authentication mode
mode , err := dynamixConfig . validateAuthenticator ( )
if err != nil {
log . Error ( err )
resp . Diagnostics . AddError ( "Provider Configure: validate error:" , err . Error ( ) )
return
}
// Set up client transport
if dynamixConfig . allowUnverifiedSsl {
log . Warn ( "Provider Configure: allow_unverified_ssl is set - will not check certificates!" )
transCfg := & http . Transport { TLSClientConfig : & tls . Config { InsecureSkipVerify : true } } //nolint:gosec
dynamixConfig . cc_client = & http . Client {
Transport : transCfg ,
}
} else {
dynamixConfig . cc_client = & http . Client { }
}
// Set up clients for data sources and resources depending on authentication mode
switch mode {
case MODE_LEGACY :
legacyConf := sdk_config . LegacyConfig {
Username : dynamixConfig . user ,
Password : dynamixConfig . password ,
DecortURL : dynamixConfig . controllerUrl ,
SSLSkipVerify : dynamixConfig . allowUnverifiedSsl ,
}
legacyClient := decort . NewLegacy ( legacyConf )
resp . DataSourceData = legacyClient
resp . ResourceData = legacyClient
case MODE_JWT :
case MODE_DECS3O :
sdkConf := sdk_config . Config {
AppID : dynamixConfig . appId ,
AppSecret : dynamixConfig . appSecret ,
SSOURL : dynamixConfig . oauth2Url ,
DecortURL : dynamixConfig . controllerUrl ,
SSLSkipVerify : dynamixConfig . allowUnverifiedSsl ,
}
decortClient := decort . New ( sdkConf )
resp . DataSourceData = decortClient
resp . ResourceData = decortClient
case MODE_BVS :
bvsConf := sdk_config . BVSConfig {
AppID : dynamixConfig . appId ,
AppSecret : dynamixConfig . appSecret ,
SSOURL : dynamixConfig . oauth2Url ,
DecortURL : dynamixConfig . controllerUrl ,
SSLSkipVerify : dynamixConfig . allowUnverifiedSsl ,
Username : dynamixConfig . bvsUser ,
Password : dynamixConfig . bvsPassword ,
Domain : dynamixConfig . domain ,
Token : dynamixConfig . token ,
PathCfg : dynamixConfig . pathConfig ,
PathToken : dynamixConfig . pathToken ,
TimeToRefresh : dynamixConfig . timeToRefresh ,
}
bvsClient := decort . NewBVS ( bvsConf )
resp . DataSourceData = bvsClient
resp . ResourceData = bvsClient
default :
log . Debugf ( "unknown authenticator mode code %d provided" , mode )
return
}
}
func ( p * DynamixProvider ) Resources ( _ context . Context ) [ ] func ( ) resource . Resource {
return newResourcesMap ( )
}
func ( p * DynamixProvider ) DataSources ( _ context . Context ) [ ] func ( ) datasource . DataSource {
return newDataSourcesMap ( )
}
func New ( version string ) func ( ) provider . Provider {
return func ( ) provider . Provider {
return & DynamixProvider {
version : version ,
}
}
}