Skip to content

Commit

Permalink
fixup! caf77b6
Browse files Browse the repository at this point in the history
  • Loading branch information
shipperizer committed Nov 15, 2024
1 parent 7028348 commit 2f0a16c
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 222 deletions.
236 changes: 14 additions & 222 deletions internal/provider/data_source_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,9 @@ type applicationDataSource struct {

type applicationDataSourceModel struct {
ApplicationName types.String `tfsdk:"name"`
// Charm types.List `tfsdk:"charm"`
// Config types.Map `tfsdk:"config"`
// Constraints types.String `tfsdk:"constraints"`
// Expose types.List `tfsdk:"expose"`
ModelName types.String `tfsdk:"model"`
// Placement types.String `tfsdk:"placement"`
// EndpointBindings types.Set `tfsdk:"endpoint_bindings"`
// Resources types.Map `tfsdk:"resources"`
// StorageDirectives types.Map `tfsdk:"storage_directives"`
// Storage types.Set `tfsdk:"storage"`
// TODO - remove Principal when we version the schema
// and remove deprecated elements. Once we create upgrade
// functionality it can be removed from the structure.
// Principal types.Bool `tfsdk:"principal"`
Trust types.Bool `tfsdk:"trust"`
// UnitCount types.Int64 `tfsdk:"units"`
ModelName types.String `tfsdk:"model"`
Trust types.Bool `tfsdk:"trust"`
UnitCount types.Int64 `tfsdk:"units"`
// ID required by the testing framework
ID types.String `tfsdk:"id"`
}
Expand All @@ -63,15 +50,19 @@ func (d *applicationDataSource) Schema(_ context.Context, _ datasource.SchemaReq
" is not supported.",
Attributes: map[string]schema.Attribute{
"name": schema.StringAttribute{
Description: "A custom name for the application deployment. If empty, uses the charm's name.",
Description: "Name of the application deployment.",
Required: true,
},
"model": schema.StringAttribute{
Description: "The name of the model where the application is to be deployed.",
Description: "The name of the model where the application is deployed.",
Required: true,
},
"trust": schema.BoolAttribute{
Description: "Set the trust for the application.",
Description: "Trust of the application.",
Computed: true,
},
"units": schema.Int64Attribute{
Description: "The number of application units deployed for the charm.",
Computed: true,
},
"id": schema.StringAttribute{
Expand Down Expand Up @@ -147,207 +138,13 @@ func (d *applicationDataSource) Read(ctx context.Context, req datasource.ReadReq

// Use the response to fill in data

// data.Placement = types.StringValue(response.Placement)
// data.Principal = types.BoolNull()
// data.UnitCount = types.Int64Value(int64(response.Units))
data.Trust = types.BoolValue(response.Trust)

// // data requiring transformation
// dataCharm := nestedCharm{
// Name: types.StringValue(response.Name),
// Channel: types.StringValue(response.Channel),
// Revision: types.Int64Value(int64(response.Revision)),
// Base: types.StringValue(response.Base),
// Series: types.StringValue(response.Series),
// }
// charmType := req.data.Schema.GetBlocks()[CharmKey].(schema.ListNestedBlock).NestedObject.Type()
// data.Charm, dErr = types.ListValueFrom(ctx, charmType, []nestedCharm{dataCharm})
// if dErr.HasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }

// // Constraints do not apply to subordinate applications. If the application
// // is subordinate, the constraints will be set to the empty string.
// data.Constraints = types.StringValue(response.Constraints.String())

// exposeType := req.data.Schema.GetBlocks()[ExposeKey].(schema.ListNestedBlock).NestedObject.Type()
// if response.Expose != nil {
// exp := parseNestedExpose(response.Expose)
// data.Expose, dErr = types.ListValueFrom(ctx, exposeType, []nestedExpose{exp})
// if dErr.HasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }
// } else {
// data.Expose = types.ListNull(exposeType)
// }

// // we only set changes if there is any difference between
// // the previous and the current config values
// configType := req.data.Schema.GetAttributes()[ConfigKey].(schema.MapAttribute).ElementType
// data.Config, dErr = r.configureConfigData(ctx, configType, data.Config, response.Config)
// if dErr.HasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }

// endpointBindingsType := req.data.Schema.GetAttributes()[EndpointBindingsKey].(schema.SetNestedAttribute).NestedObject.Type()
// if len(response.EndpointBindings) > 0 {
// data.EndpointBindings, dErr = r.toEndpointBindingsSet(ctx, endpointBindingsType, response.EndpointBindings)
// if dErr.HasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }
// }

// // convert the storage map to a list of nestedStorage
// nestedStorageSlice := make([]nestedStorage, 0, len(response.Storage))
// for name, storage := range response.Storage {
// humanizedSize := transformSizeToHumanizedFormat(storage.Size)
// nestedStorageSlice = append(nestedStorageSlice, nestedStorage{
// Label: types.StringValue(name),
// Size: types.StringValue(humanizedSize),
// Pool: types.StringValue(storage.Pool),
// Count: types.Int64Value(int64(storage.Count)),
// })
// }
// storageType := req.data.Schema.GetAttributes()[StorageKey].(schema.SetNestedAttribute).NestedObject.Type()
// if len(nestedStorageSlice) > 0 {
// data.Storage, dErr = types.SetValueFrom(ctx, storageType, nestedStorageSlice)
// if dErr.HasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }
// } else {
// data.Storage = types.SetNull(storageType)
// }

// resourceType := req.data.Schema.GetAttributes()[ResourceKey].(schema.MapAttribute).ElementType
// data.Resources, dErr = d.configureDataSourceData(ctx, resourceType, data.Resources, response.Resources)
// if dErdasError() {
// resp.Diagnostics.Append(dErr...)
// return
// }
data.UnitCount = types.Int64Value(int64(response.Units))

d.trace("Found", applicationDataSourceModelForLogging(ctx, &data))
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

// func (d *applicationDataSource) configureConfigData(ctx context.Context, configType attr.Type, config types.Map, respCfg map[string]juju.ConfigEntry) (types.Map, diag.Diagnostics) {
// // We focus on those config entries that are not the default value.
// // If the value was the same we ignore it. If no changes were made,
// // jump to the next step.
// var previousConfig map[string]string
// diagErr := config.ElementsAs(ctx, &previousConfig, false)
// if diagErr.HasError() {
// d.trace("configureConfigData exit A")
// return types.Map{}, diagErr
// }
// if previousConfig == nil {
// previousConfig = make(map[string]string)
// }
// // known previously
// // update the values from the previous config
// changes := false
// for k, v := range respCfg {
// // Add if the value has changed from the previous state
// if previousValue, found := previousConfig[k]; found {
// if !juju.EqualConfigEntries(v, previousValue) {
// // remember that this Terraform schema type only accepts strings
// previousConfig[k] = v.String()
// changes = true
// }
// } else if !v.IsDefault {
// // Add if the value is not default
// previousConfig[k] = v.String()
// changes = true
// }
// }
// if changes {
// return types.MapValueFrom(ctx, configType, previousConfig)
// }
// return config, nil
// }

// // Read is called when the provider must read data source values in
// // order to update state. Config values should be read from the
// // ReadRequest and new state values set on the ReadResponse.
// func (d *applicationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
// // Prevent panic if the provider has not been configured.
// if d.client == nil {
// addDSClientNotConfiguredError(&resp.Diagnostics, "model")
// return
// }

// var data applicationDataSourceModel

// // Read Terraform configuration data into the model.
// resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
// if resp.Diagnostics.HasError() {
// return
// }

// // Get current juju model data source values.
// model, err := d.client.Models.GetModelByName(data.Name.ValueString())
// if err != nil {
// resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read model, got error: %s", err))
// return
// }
// d.trace(fmt.Sprintf("read juju model %q data source", data.Name))

// // Save data into Terraform state
// data.Name = types.StringValue(model.Name)
// data.UUID = types.StringValue(model.UUID)
// data.ID = types.StringValue(model.UUID)
// resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
// }

// // Convert the endpoint bindings from the juju api to terraform nestedEndpointBinding set
// func (d *applicationDataSource) toEndpointBindingsSet(ctx context.Context, endpointBindingsType attr.Type, endpointBindings map[string]string) (types.Set, diag.Diagnostics) {
// endpointBindingsSlice := make([]nestedEndpointBinding, 0, len(endpointBindings))
// for endpoint, space := range endpointBindings {
// var endpointString types.String
// if endpoint == "" {
// endpointString = types.StringNull()
// } else {
// endpointString = types.StringValue(endpoint)
// }
// endpointBindingsSlice = append(endpointBindingsSlice, nestedEndpointBinding{Endpoint: endpointString, Space: types.StringValue(space)})
// }

// return types.SetValueFrom(ctx, endpointBindingsType, endpointBindingsSlice)
// }

// func (d *applicationDataSource) configureDataSourceData(ctx context.Context, resourceType attr.Type, resources types.Map, respResources map[string]string) (types.Map, diag.Diagnostics) {
// var previousResources map[string]string
// diagErr := resources.ElementsAs(ctx, &previousResources, false)
// if diagErr.HasError() {
// d.trace("configureDataSourceData exit A")
// return types.Map{}, diagErr
// }
// if previousResources == nil {
// previousResources = make(map[string]string)
// }
// // known previously
// // update the values from the previous config
// changes := false
// for k, v := range respResources {
// // Add if the value has changed from the previous state
// if previousValue, found := previousResources[k]; found {
// if v != previousValue {
// // remember that this Terraform schema type only accepts strings
// previousResources[k] = v
// changes = true
// }
// }
// }
// if changes {
// return types.MapValueFrom(ctx, resourceType, previousResources)
// }
// return resources, nil
// }

func (d *applicationDataSource) trace(msg string, additionalFields ...map[string]interface{}) {
if d.subCtx == nil {
return
Expand All @@ -362,14 +159,9 @@ func (d *applicationDataSource) trace(msg string, additionalFields ...map[string
func applicationDataSourceModelForLogging(_ context.Context, app *applicationDataSourceModel) map[string]interface{} {
value := map[string]interface{}{
"application-name": app.ApplicationName.ValueString(),
// "charm": app.Charm.String(),
// "constraints": app.Constraints.ValueString(),
"model": app.ModelName.ValueString(),
// "placement": app.Placement.ValueString(),
// "expose": app.Expose.String(),
"trust": app.Trust.ValueBoolPointer(),
// "units": app.UnitCount.ValueInt64(),
// "storage": app.Storage.String(),
"model": app.ModelName.ValueString(),
"trust": app.Trust.ValueBoolPointer(),
"units": app.UnitCount.ValueInt64(),
}
return value
}
94 changes: 94 additions & 0 deletions internal/provider/data_source_application_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2023 Canonical Ltd.
// Licensed under the Apache License, Version 2.0, see LICENCE file for details.

package provider

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAcc_DataSourceApplication_Edge(t *testing.T) {
if testingCloud != LXDCloudTesting {
t.Skip(t.Name() + " only runs with LXD")
}
modelName := acctest.RandomWithPrefix("tf-datasource-application-test-model")
applicationName := acctest.RandomWithPrefix("tf-datasource-application-test-name")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: frameworkProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccDataSourceApplication(modelName, applicationName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.juju_application.this", "model", modelName),
resource.TestCheckResourceAttr("data.juju_application.this", "name", applicationName),
),
},
},
})
}

func TestAcc_DataSourceApplication_UpgradeProvider(t *testing.T) {
if testingCloud != LXDCloudTesting {
t.Skip(t.Name() + " only runs with LXD")
}
modelName := acctest.RandomWithPrefix("tf-datasource-application-test-model")
applicationName := acctest.RandomWithPrefix("tf-datasource-application-test-name")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },

Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
"juju": {
VersionConstraint: TestProviderStableVersion,
Source: "juju/juju",
},
},
Config: testAccDataSourceApplication(modelName, applicationName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.juju_application.this", "model", modelName),
resource.TestCheckResourceAttr("data.juju_application.this", "name", applicationName),
),
},
{
ProtoV6ProviderFactories: frameworkProviderFactories,
Config: testAccDataSourceApplication(modelName, applicationName),
PlanOnly: true,
},
},
})
}

func testAccDataSourceApplication(modelName, applicationName string) string {
return fmt.Sprintf(`
resource "juju_model" "model" {
name = %q
}
resource "juju_application" "this" {
name = %q
model = juju_model.model.name
units = 2
charm {
name = "ubuntu"
channel = "edge"
revision = 24
series = "trusty"
}
}
data "juju_application" "this" {
model = juju_model.model.name
name = juju_application.this.name
}`, modelName, applicationName)
}

0 comments on commit 2f0a16c

Please sign in to comment.