mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
* feat: Create provisioner abstraction Creates a provisioner abstraction that takes prior art from the Terraform plugin system. It's safe to assume this code will change a lot when it becomes integrated with provisionerd. Closes #10. * Ignore generated files in diff view * Check for unstaged file changes * Install protoc-gen-go * Use proper drpc plugin version * Fix serve closed pipe * Install sqlc with curl for speed * Fix install command * Format CI action * Add linguist-generated and closed pipe test * Cleanup code from comments * Add dRPC comment * Add Terraform installer for cross-platform * Build provisioner tests on Linux only
66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
package terraform
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
|
|
"github.com/coder/coder/provisionersdk/proto"
|
|
"github.com/hashicorp/terraform-config-inspect/tfconfig"
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
// Parse extracts Terraform variables from source-code.
|
|
func (t *terraform) Parse(ctx context.Context, request *proto.Parse_Request) (*proto.Parse_Response, error) {
|
|
module, diags := tfconfig.LoadModule(request.Directory)
|
|
if diags.HasErrors() {
|
|
return nil, xerrors.Errorf("load module: %w", diags.Err())
|
|
}
|
|
parameters := make([]*proto.ParameterSchema, 0, len(module.Variables))
|
|
for _, v := range module.Variables {
|
|
schema, err := convertVariableToParameter(v)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("convert variable %q: %w", v.Name, err)
|
|
}
|
|
|
|
parameters = append(parameters, schema)
|
|
}
|
|
|
|
return &proto.Parse_Response{
|
|
ParameterSchemas: parameters,
|
|
}, nil
|
|
}
|
|
|
|
// Converts a Terraform variable to a provisioner parameter.
|
|
func convertVariableToParameter(variable *tfconfig.Variable) (*proto.ParameterSchema, error) {
|
|
schema := &proto.ParameterSchema{
|
|
Name: variable.Name,
|
|
Description: variable.Description,
|
|
Sensitive: variable.Sensitive,
|
|
ValidationValueType: variable.Type,
|
|
}
|
|
|
|
if variable.Default != nil {
|
|
defaultData, err := json.Marshal(variable.Default)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("parse variable %q default: %w", variable.Name, err)
|
|
}
|
|
schema.DefaultValue = string(defaultData)
|
|
}
|
|
|
|
if len(variable.Validations) > 0 && variable.Validations[0].Condition != nil {
|
|
// Terraform can contain multiple validation blocks, but it's used sparingly
|
|
// from what it appears.
|
|
validation := variable.Validations[0]
|
|
filedata, err := os.ReadFile(variable.Pos.Filename)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("read file %q: %w", variable.Pos.Filename, err)
|
|
}
|
|
schema.ValidationCondition = string(filedata[validation.Condition.Range().Start.Byte:validation.Condition.Range().End.Byte])
|
|
schema.ValidationError = validation.ErrorMessage
|
|
schema.ValidationTypeSystem = proto.ParameterSchema_HCL
|
|
}
|
|
|
|
return schema, nil
|
|
}
|