Skip to content

Commit

Permalink
Instance script works
Browse files Browse the repository at this point in the history
  • Loading branch information
krystian-panek-vmltech committed Nov 16, 2023
1 parent 48bcc22 commit 56fcedc
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 35 deletions.
11 changes: 6 additions & 5 deletions examples/ssh/aem.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ resource "aem_instance" "single" {
}

system {
data_dir = local.aem_single_compose_dir
bootstrap_script = <<SHELL
data_dir = local.aem_single_compose_dir
bootstrap = {
script = <<SHELL
#!/bin/sh
(
echo "Mounting EBS volume into data directory"
Expand All @@ -34,10 +35,10 @@ resource "aem_instance" "single" {
mkdir -p "${local.aem_single_compose_dir}/aem/home/lib" && \
aws s3 cp --recursive --no-progress "s3://aemc/instance/classic/" "${local.aem_single_compose_dir}/aem/home/lib"
)
SHELL
SHELL
}
}

compose {} // must be at least empty
compose {}
}

locals {
Expand Down
48 changes: 31 additions & 17 deletions internal/provider/instance_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (ic *InstanceClient) create() error {
if err := ic.saveProfileScript(); err != nil {
return err
}
if err := ic.runScript("create", ic.data.Compose.CreateScript.ValueString(), ic.dataDir()); err != nil {
if err := ic.runScript("create", ic.data.Compose.Create, ic.dataDir()); err != nil {
return err
}
tflog.Info(ic.ctx, "Created AEM instance(s)")
Expand Down Expand Up @@ -150,7 +150,7 @@ func (ic *InstanceClient) launch() error {
if err := ic.runServiceAction("start"); err != nil {
return err
}
if err := ic.runScript("launch", ic.data.Compose.LaunchScript.ValueString(), ic.dataDir()); err != nil {
if err := ic.runScript("launch", ic.data.Compose.Launch, ic.dataDir()); err != nil {
return err
}
tflog.Info(ic.ctx, "Launched AEM instance(s)")
Expand All @@ -163,7 +163,7 @@ func (ic *InstanceClient) terminate() error {
if err := ic.runServiceAction("stop"); err != nil {
return err
}
if err := ic.runScript("delete", ic.data.Compose.DeleteScript.ValueString(), ic.dataDir()); err != nil {
if err := ic.runScript("delete", ic.data.Compose.Delete, ic.dataDir()); err != nil {
return err
}
tflog.Info(ic.ctx, "Terminated AEM instance(s)")
Expand Down Expand Up @@ -204,24 +204,38 @@ func (ic *InstanceClient) ReadStatus() (InstanceStatus, error) {
}

func (ic *InstanceClient) bootstrap() error {
return ic.runScript("bootstrap", ic.data.System.BootstrapScript.ValueString(), ".")
return ic.runScript("bootstrap", ic.data.System.Bootstrap, ".")
}

func (ic *InstanceClient) runScript(name, cmdScript, dir string) error {
if cmdScript == "" {
return nil
func (ic *InstanceClient) runScript(name string, script InstanceScript, dir string) error {
scriptCmd := script.Script.ValueString()
inlineCmds := []string{}
diags := script.Inline.ElementsAs(ic.ctx, &inlineCmds, true)
if diags.HasError() {
return fmt.Errorf("unable to parse script '%s' properly: %s", name, diags)
}

tflog.Info(ic.ctx, fmt.Sprintf("Executing instance script '%s'", name))

textOut, err := ic.cl.RunShellScript(name, cmdScript, dir)
if err != nil {
return fmt.Errorf("unable to execute script '%s' properly: %w", name, err)
if scriptCmd != "" {
tflog.Info(ic.ctx, fmt.Sprintf("Executing instance script '%s'", name))
textOut, err := ic.cl.RunShellScript(name, scriptCmd, dir)
if err != nil {
return fmt.Errorf("unable to execute script '%s' properly: %w", name, err)
}
textStr := string(textOut)
tflog.Info(ic.ctx, fmt.Sprintf("Executed instance script '%s'", name))
tflog.Info(ic.ctx, textStr)
}
if len(inlineCmds) > 0 {
for i, cmd := range inlineCmds {
tflog.Info(ic.ctx, fmt.Sprintf("Executing command '%s' of script '%s' (%d/%d)", cmd, name, i+1, len(inlineCmds)))
textOut, err := ic.cl.RunShellCommand(cmd)
if err != nil {
return fmt.Errorf("unable to execute command '%s' of script '%s' properly: %w", cmd, name, err)
}
textStr := string(textOut)
tflog.Info(ic.ctx, fmt.Sprintf("Executed command '%s' of script '%s' (%d/%d)", cmd, name, i+1, len(inlineCmds)))
tflog.Info(ic.ctx, textStr)
}
}
textStr := string(textOut) // TODO how about streaming it line by line to tflog ;)

tflog.Info(ic.ctx, fmt.Sprintf("Executed instance script '%s'", name))
tflog.Info(ic.ctx, textStr)

return nil
}
61 changes: 48 additions & 13 deletions internal/provider/instance_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/defaults"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/wttech/terraform-provider-aem/internal/client"
"github.com/wttech/terraform-provider-aem/internal/provider/instance"
Expand Down Expand Up @@ -43,24 +46,52 @@ type InstanceResourceModel struct {
} `tfsdk:"client"`
Files types.Map `tfsdk:"files"`
System struct {
DataDir types.String `tfsdk:"data_dir"`
WorkDir types.String `tfsdk:"work_dir"`
Env types.Map `tfsdk:"env"`
ServiceConfig types.String `tfsdk:"service_config"`
User types.String `tfsdk:"user"`
BootstrapScript types.String `tfsdk:"bootstrap_script"`
DataDir types.String `tfsdk:"data_dir"`
WorkDir types.String `tfsdk:"work_dir"`
Env types.Map `tfsdk:"env"`
ServiceConfig types.String `tfsdk:"service_config"`
User types.String `tfsdk:"user"`
Bootstrap InstanceScript `tfsdk:"bootstrap"`
} `tfsdk:"system"`
Compose struct {
Download types.Bool `tfsdk:"download"`
Version types.String `tfsdk:"version"`
Config types.String `tfsdk:"config"`
CreateScript types.String `tfsdk:"create_script"`
LaunchScript types.String `tfsdk:"launch_script"`
DeleteScript types.String `tfsdk:"delete_script"`
Download types.Bool `tfsdk:"download"`
Version types.String `tfsdk:"version"`
Config types.String `tfsdk:"config"`
Create InstanceScript `tfsdk:"create"`
Launch InstanceScript `tfsdk:"launch"`
Delete InstanceScript `tfsdk:"delete"`
} `tfsdk:"compose"`
Instances types.List `tfsdk:"instances"`
}

type InstanceScript struct {
Inline types.List `tfsdk:"inline"`
Script types.String `tfsdk:"script"`
}

func instanceScriptSchemaDefault(inline []string, script string) defaults.Object {
var inlineValue basetypes.ListValue
if inline == nil {
inlineValue = types.ListNull(types.StringType)
} else {
inlineValues := make([]attr.Value, len(inline))
for i, v := range inline {
inlineValues[i] = types.StringValue(v)
}
inlineValue = types.ListValueMust(types.StringType, inlineValues)
}
return objectdefault.StaticValue(types.ObjectValueMust(
map[string]attr.Type{
"inline": types.ListType{ElemType: types.StringType},
"script": types.StringType,
},
map[string]attr.Value{
"inline": inlineValue,
"script": types.StringValue(script),
},
))
}

type InstanceStatusItemModel struct {
ID types.String `tfsdk:"id"`
URL types.String `tfsdk:"url"`
Expand All @@ -70,6 +101,7 @@ type InstanceStatusItemModel struct {
RunModes types.List `tfsdk:"run_modes"`
}

// fix for https://github.com/hashicorp/terraform-plugin-framework/issues/713
func (o InstanceStatusItemModel) attrTypes() map[string]attr.Type {
return map[string]attr.Type{
"id": types.StringType,
Expand Down Expand Up @@ -157,7 +189,7 @@ func (r *InstanceResource) Schema(ctx context.Context, req resource.SchemaReques
},
},
"compose": schema.SingleNestedBlock{

MarkdownDescription: "AEM Compose CLI configuration",
Attributes: map[string]schema.Attribute{
"download": schema.BoolAttribute{
MarkdownDescription: "Toggle automatic AEM Compose CLI wrapper download. If set to false, assume the wrapper is present in the data directory.",
Expand All @@ -181,6 +213,7 @@ func (r *InstanceResource) Schema(ctx context.Context, req resource.SchemaReques
MarkdownDescription: "Creates the instance or restores from backup. Forces instance recreation if changed.",
Optional: true,
Computed: true,
Default: instanceScriptSchemaDefault(nil, instance.CreateScript),
Attributes: map[string]schema.Attribute{
"inline": schema.ListAttribute{
Optional: true,
Expand All @@ -199,6 +232,7 @@ func (r *InstanceResource) Schema(ctx context.Context, req resource.SchemaReques
MarkdownDescription: "Configures launched instance. Must be idempotent as it is executed always when changed. Typically used for setting up replication agents, installing service packs, etc.",
Optional: true,
Computed: true,
Default: instanceScriptSchemaDefault(nil, instance.LaunchScript),
Attributes: map[string]schema.Attribute{
"inline": schema.ListAttribute{
Optional: true,
Expand All @@ -215,6 +249,7 @@ func (r *InstanceResource) Schema(ctx context.Context, req resource.SchemaReques
MarkdownDescription: "Deletes the instance.",
Optional: true,
Computed: true,
Default: instanceScriptSchemaDefault(nil, instance.DeleteScript),
Attributes: map[string]schema.Attribute{
"inline": schema.ListAttribute{
Optional: true,
Expand Down

0 comments on commit 56fcedc

Please sign in to comment.