package terraform import ( "context" "reflect" "testing" "github.com/databricks/cli/bundle/config" "github.com/databricks/cli/bundle/config/resources" "github.com/databricks/cli/bundle/internal/tf/schema" "github.com/databricks/cli/libs/dyn" "github.com/databricks/cli/libs/dyn/convert" "github.com/databricks/databricks-sdk-go/service/catalog" "github.com/databricks/databricks-sdk-go/service/compute" "github.com/databricks/databricks-sdk-go/service/dashboards" "github.com/databricks/databricks-sdk-go/service/jobs" "github.com/databricks/databricks-sdk-go/service/ml" "github.com/databricks/databricks-sdk-go/service/pipelines" "github.com/databricks/databricks-sdk-go/service/serving" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func produceTerraformConfiguration(t *testing.T, config config.Root) *schema.Root { vin, err := convert.FromTyped(config, dyn.NilValue) require.NoError(t, err) out, err := BundleToTerraformWithDynValue(context.Background(), vin) require.NoError(t, err) return out } func convertToResourceStruct[T any](t *testing.T, resource *T, data any) { require.NotNil(t, resource) require.NotNil(t, data) // Convert data to a dyn.Value. vin, err := convert.FromTyped(data, dyn.NilValue) require.NoError(t, err) // Convert the dyn.Value to a struct. err = convert.ToTyped(resource, vin) require.NoError(t, err) } func TestBundleToTerraformJob(t *testing.T) { var src = resources.Job{ JobSettings: &jobs.JobSettings{ Name: "my job", JobClusters: []jobs.JobCluster{ { JobClusterKey: "key", NewCluster: compute.ClusterSpec{ SparkVersion: "10.4.x-scala2.12", }, }, }, GitSource: &jobs.GitSource{ GitProvider: jobs.GitProviderGitHub, GitUrl: "https://github.com/foo/bar", }, Parameters: []jobs.JobParameterDefinition{ { Name: "param1", Default: "default1", }, { Name: "param2", Default: "default2", }, }, }, } var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "my_job": &src, }, }, } var resource schema.ResourceJob out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Job["my_job"]) assert.Equal(t, "my job", resource.Name) assert.Len(t, resource.JobCluster, 1) assert.Equal(t, "https://github.com/foo/bar", resource.GitSource.Url) assert.Len(t, resource.Parameter, 2) assert.Equal(t, "param1", resource.Parameter[0].Name) assert.Equal(t, "param2", resource.Parameter[1].Name) assert.Nil(t, out.Data) } func TestBundleToTerraformJobPermissions(t *testing.T) { var src = resources.Job{ Permissions: []resources.Permission{ { Level: "CAN_VIEW", UserName: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "my_job": &src, }, }, } var resource schema.ResourcePermissions out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Permissions["job_my_job"]) assert.NotEmpty(t, resource.JobId) assert.Len(t, resource.AccessControl, 1) assert.Equal(t, "jane@doe.com", resource.AccessControl[0].UserName) assert.Equal(t, "CAN_VIEW", resource.AccessControl[0].PermissionLevel) } func TestBundleToTerraformJobTaskLibraries(t *testing.T) { var src = resources.Job{ JobSettings: &jobs.JobSettings{ Name: "my job", Tasks: []jobs.Task{ { TaskKey: "key", Libraries: []compute.Library{ { Pypi: &compute.PythonPyPiLibrary{ Package: "mlflow", }, }, }, }, }, }, } var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "my_job": &src, }, }, } var resource schema.ResourceJob out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Job["my_job"]) assert.Equal(t, "my job", resource.Name) require.Len(t, resource.Task, 1) require.Len(t, resource.Task[0].Library, 1) assert.Equal(t, "mlflow", resource.Task[0].Library[0].Pypi.Package) } func TestBundleToTerraformForEachTaskLibraries(t *testing.T) { var src = resources.Job{ JobSettings: &jobs.JobSettings{ Name: "my job", Tasks: []jobs.Task{ { TaskKey: "key", ForEachTask: &jobs.ForEachTask{ Inputs: "[1,2,3]", Task: jobs.Task{ TaskKey: "iteration", Libraries: []compute.Library{ { Pypi: &compute.PythonPyPiLibrary{ Package: "mlflow", }, }, }, }, }, }, }, }, } var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "my_job": &src, }, }, } var resource schema.ResourceJob out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Job["my_job"]) assert.Equal(t, "my job", resource.Name) require.Len(t, resource.Task, 1) require.Len(t, resource.Task[0].ForEachTask.Task.Library, 1) assert.Equal(t, "mlflow", resource.Task[0].ForEachTask.Task.Library[0].Pypi.Package) } func TestBundleToTerraformPipeline(t *testing.T) { var src = resources.Pipeline{ PipelineSpec: &pipelines.PipelineSpec{ Name: "my pipeline", Libraries: []pipelines.PipelineLibrary{ { Notebook: &pipelines.NotebookLibrary{ Path: "notebook path", }, }, { File: &pipelines.FileLibrary{ Path: "file path", }, }, }, Notifications: []pipelines.Notifications{ { Alerts: []string{ "on-update-fatal-failure", }, EmailRecipients: []string{ "jane@doe.com", }, }, { Alerts: []string{ "on-update-failure", "on-flow-failure", }, EmailRecipients: []string{ "jane@doe.com", "john@doe.com", }, }, }, }, } var config = config.Root{ Resources: config.Resources{ Pipelines: map[string]*resources.Pipeline{ "my_pipeline": &src, }, }, } var resource schema.ResourcePipeline out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Pipeline["my_pipeline"]) assert.Equal(t, "my pipeline", resource.Name) assert.Len(t, resource.Library, 2) assert.Len(t, resource.Notification, 2) assert.Equal(t, resource.Notification[0].Alerts, []string{"on-update-fatal-failure"}) assert.Equal(t, resource.Notification[0].EmailRecipients, []string{"jane@doe.com"}) assert.Equal(t, resource.Notification[1].Alerts, []string{"on-update-failure", "on-flow-failure"}) assert.Equal(t, resource.Notification[1].EmailRecipients, []string{"jane@doe.com", "john@doe.com"}) assert.Nil(t, out.Data) } func TestBundleToTerraformPipelinePermissions(t *testing.T) { var src = resources.Pipeline{ Permissions: []resources.Permission{ { Level: "CAN_VIEW", UserName: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ Pipelines: map[string]*resources.Pipeline{ "my_pipeline": &src, }, }, } var resource schema.ResourcePermissions out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Permissions["pipeline_my_pipeline"]) assert.NotEmpty(t, resource.PipelineId) assert.Len(t, resource.AccessControl, 1) assert.Equal(t, "jane@doe.com", resource.AccessControl[0].UserName) assert.Equal(t, "CAN_VIEW", resource.AccessControl[0].PermissionLevel) } func TestBundleToTerraformModel(t *testing.T) { var src = resources.MlflowModel{ Model: &ml.Model{ Name: "name", Description: "description", Tags: []ml.ModelTag{ { Key: "k1", Value: "v1", }, { Key: "k2", Value: "v2", }, }, }, } var config = config.Root{ Resources: config.Resources{ Models: map[string]*resources.MlflowModel{ "my_model": &src, }, }, } var resource schema.ResourceMlflowModel out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.MlflowModel["my_model"]) assert.Equal(t, "name", resource.Name) assert.Equal(t, "description", resource.Description) assert.Len(t, resource.Tags, 2) assert.Equal(t, "k1", resource.Tags[0].Key) assert.Equal(t, "v1", resource.Tags[0].Value) assert.Equal(t, "k2", resource.Tags[1].Key) assert.Equal(t, "v2", resource.Tags[1].Value) assert.Nil(t, out.Data) } func TestBundleToTerraformModelPermissions(t *testing.T) { var src = resources.MlflowModel{ Model: &ml.Model{ Name: "name", }, Permissions: []resources.Permission{ { Level: "CAN_READ", UserName: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ Models: map[string]*resources.MlflowModel{ "my_model": &src, }, }, } var resource schema.ResourcePermissions out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Permissions["mlflow_model_my_model"]) assert.NotEmpty(t, resource.RegisteredModelId) assert.Len(t, resource.AccessControl, 1) assert.Equal(t, "jane@doe.com", resource.AccessControl[0].UserName) assert.Equal(t, "CAN_READ", resource.AccessControl[0].PermissionLevel) } func TestBundleToTerraformExperiment(t *testing.T) { var src = resources.MlflowExperiment{ Experiment: &ml.Experiment{ Name: "name", }, } var config = config.Root{ Resources: config.Resources{ Experiments: map[string]*resources.MlflowExperiment{ "my_experiment": &src, }, }, } var resource schema.ResourceMlflowExperiment out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.MlflowExperiment["my_experiment"]) assert.Equal(t, "name", resource.Name) assert.Nil(t, out.Data) } func TestBundleToTerraformExperimentPermissions(t *testing.T) { var src = resources.MlflowExperiment{ Experiment: &ml.Experiment{ Name: "name", }, Permissions: []resources.Permission{ { Level: "CAN_READ", UserName: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ Experiments: map[string]*resources.MlflowExperiment{ "my_experiment": &src, }, }, } var resource schema.ResourcePermissions out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Permissions["mlflow_experiment_my_experiment"]) assert.NotEmpty(t, resource.ExperimentId) assert.Len(t, resource.AccessControl, 1) assert.Equal(t, "jane@doe.com", resource.AccessControl[0].UserName) assert.Equal(t, "CAN_READ", resource.AccessControl[0].PermissionLevel) } func TestBundleToTerraformModelServing(t *testing.T) { var src = resources.ModelServingEndpoint{ CreateServingEndpoint: &serving.CreateServingEndpoint{ Name: "name", Config: serving.EndpointCoreConfigInput{ ServedModels: []serving.ServedModelInput{ { ModelName: "model_name", ModelVersion: "1", ScaleToZeroEnabled: true, WorkloadSize: "Small", }, }, TrafficConfig: &serving.TrafficConfig{ Routes: []serving.Route{ { ServedModelName: "model_name-1", TrafficPercentage: 100, }, }, }, }, }, } var config = config.Root{ Resources: config.Resources{ ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ "my_model_serving_endpoint": &src, }, }, } var resource schema.ResourceModelServing out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.ModelServing["my_model_serving_endpoint"]) assert.Equal(t, "name", resource.Name) assert.Equal(t, "model_name", resource.Config.ServedModels[0].ModelName) assert.Equal(t, "1", resource.Config.ServedModels[0].ModelVersion) assert.Equal(t, true, resource.Config.ServedModels[0].ScaleToZeroEnabled) assert.Equal(t, "Small", resource.Config.ServedModels[0].WorkloadSize) assert.Equal(t, "model_name-1", resource.Config.TrafficConfig.Routes[0].ServedModelName) assert.Equal(t, 100, resource.Config.TrafficConfig.Routes[0].TrafficPercentage) assert.Nil(t, out.Data) } func TestBundleToTerraformModelServingPermissions(t *testing.T) { var src = resources.ModelServingEndpoint{ CreateServingEndpoint: &serving.CreateServingEndpoint{ Name: "name", // Need to specify this to satisfy the equivalence test: // The previous method of generation includes the "create" field // because it is required (not marked as `omitempty`). // The previous method used [json.Marshal] from the standard library // and as such observed the `omitempty` tag. // The new method leverages [dyn.Value] where any field that is not // explicitly set is not part of the value. Config: serving.EndpointCoreConfigInput{ ServedModels: []serving.ServedModelInput{ { ModelName: "model_name", ModelVersion: "1", ScaleToZeroEnabled: true, WorkloadSize: "Small", }, }, }, }, Permissions: []resources.Permission{ { Level: "CAN_VIEW", UserName: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ "my_model_serving_endpoint": &src, }, }, } var resource schema.ResourcePermissions out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Permissions["model_serving_my_model_serving_endpoint"]) assert.NotEmpty(t, resource.ServingEndpointId) assert.Len(t, resource.AccessControl, 1) assert.Equal(t, "jane@doe.com", resource.AccessControl[0].UserName) assert.Equal(t, "CAN_VIEW", resource.AccessControl[0].PermissionLevel) } func TestBundleToTerraformRegisteredModel(t *testing.T) { var src = resources.RegisteredModel{ CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ Name: "name", CatalogName: "catalog", SchemaName: "schema", Comment: "comment", }, } var config = config.Root{ Resources: config.Resources{ RegisteredModels: map[string]*resources.RegisteredModel{ "my_registered_model": &src, }, }, } var resource schema.ResourceRegisteredModel out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.RegisteredModel["my_registered_model"]) assert.Equal(t, "name", resource.Name) assert.Equal(t, "catalog", resource.CatalogName) assert.Equal(t, "schema", resource.SchemaName) assert.Equal(t, "comment", resource.Comment) assert.Nil(t, out.Data) } func TestBundleToTerraformRegisteredModelGrants(t *testing.T) { var src = resources.RegisteredModel{ CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ Name: "name", CatalogName: "catalog", SchemaName: "schema", }, Grants: []resources.Grant{ { Privileges: []string{"EXECUTE"}, Principal: "jane@doe.com", }, }, } var config = config.Root{ Resources: config.Resources{ RegisteredModels: map[string]*resources.RegisteredModel{ "my_registered_model": &src, }, }, } var resource schema.ResourceGrants out := produceTerraformConfiguration(t, config) convertToResourceStruct(t, &resource, out.Resource.Grants["registered_model_my_registered_model"]) assert.NotEmpty(t, resource.Function) assert.Len(t, resource.Grant, 1) assert.Equal(t, "jane@doe.com", resource.Grant[0].Principal) assert.Equal(t, "EXECUTE", resource.Grant[0].Privileges[0]) } func TestBundleToTerraformDeletedResources(t *testing.T) { var job1 = resources.Job{ JobSettings: &jobs.JobSettings{}, } var job2 = resources.Job{ ModifiedStatus: resources.ModifiedStatusDeleted, JobSettings: &jobs.JobSettings{}, } var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "my_job1": &job1, "my_job2": &job2, }, }, } vin, err := convert.FromTyped(config, dyn.NilValue) require.NoError(t, err) out, err := BundleToTerraformWithDynValue(context.Background(), vin) require.NoError(t, err) _, ok := out.Resource.Job["my_job1"] assert.True(t, ok) _, ok = out.Resource.Job["my_job2"] assert.False(t, ok) } func TestTerraformToBundleEmptyLocalResources(t *testing.T) { var config = config.Root{ Resources: config.Resources{}, } var tfState = resourcesState{ Resources: []stateResource{ { Type: "databricks_job", Mode: "managed", Name: "test_job", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_pipeline", Mode: "managed", Name: "test_pipeline", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_mlflow_model", Mode: "managed", Name: "test_mlflow_model", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_mlflow_experiment", Mode: "managed", Name: "test_mlflow_experiment", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_model_serving", Mode: "managed", Name: "test_model_serving", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_registered_model", Mode: "managed", Name: "test_registered_model", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_quality_monitor", Mode: "managed", Name: "test_monitor", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_schema", Mode: "managed", Name: "test_schema", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_volume", Mode: "managed", Name: "test_volume", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_cluster", Mode: "managed", Name: "test_cluster", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_dashboard", Mode: "managed", Name: "test_dashboard", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, }, } err := TerraformToBundle(&tfState, &config) assert.NoError(t, err) assert.Equal(t, "1", config.Resources.Jobs["test_job"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Jobs["test_job"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Pipelines["test_pipeline"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Pipelines["test_pipeline"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Models["test_mlflow_model"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Models["test_mlflow_model"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Experiments["test_mlflow_experiment"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Experiments["test_mlflow_experiment"].ModifiedStatus) assert.Equal(t, "1", config.Resources.ModelServingEndpoints["test_model_serving"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.ModelServingEndpoints["test_model_serving"].ModifiedStatus) assert.Equal(t, "1", config.Resources.RegisteredModels["test_registered_model"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.RegisteredModels["test_registered_model"].ModifiedStatus) assert.Equal(t, "1", config.Resources.QualityMonitors["test_monitor"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.QualityMonitors["test_monitor"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Schemas["test_schema"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Schemas["test_schema"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Volumes["test_volume"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Volumes["test_volume"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Clusters["test_cluster"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Clusters["test_cluster"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Dashboards["test_dashboard"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Dashboards["test_dashboard"].ModifiedStatus) AssertFullResourceCoverage(t, &config) } func TestTerraformToBundleEmptyRemoteResources(t *testing.T) { var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "test_job": { JobSettings: &jobs.JobSettings{ Name: "test_job", }, }, }, Pipelines: map[string]*resources.Pipeline{ "test_pipeline": { PipelineSpec: &pipelines.PipelineSpec{ Name: "test_pipeline", }, }, }, Models: map[string]*resources.MlflowModel{ "test_mlflow_model": { Model: &ml.Model{ Name: "test_mlflow_model", }, }, }, Experiments: map[string]*resources.MlflowExperiment{ "test_mlflow_experiment": { Experiment: &ml.Experiment{ Name: "test_mlflow_experiment", }, }, }, ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ "test_model_serving": { CreateServingEndpoint: &serving.CreateServingEndpoint{ Name: "test_model_serving", }, }, }, RegisteredModels: map[string]*resources.RegisteredModel{ "test_registered_model": { CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ Name: "test_registered_model", }, }, }, QualityMonitors: map[string]*resources.QualityMonitor{ "test_monitor": { CreateMonitor: &catalog.CreateMonitor{ TableName: "test_monitor", }, }, }, Schemas: map[string]*resources.Schema{ "test_schema": { CreateSchema: &catalog.CreateSchema{ Name: "test_schema", }, }, }, Volumes: map[string]*resources.Volume{ "test_volume": { CreateVolumeRequestContent: &catalog.CreateVolumeRequestContent{ Name: "test_volume", }, }, }, Clusters: map[string]*resources.Cluster{ "test_cluster": { ClusterSpec: &compute.ClusterSpec{ ClusterName: "test_cluster", }, }, }, Dashboards: map[string]*resources.Dashboard{ "test_dashboard": { Dashboard: &dashboards.Dashboard{ DisplayName: "test_dashboard", }, }, }, }, } var tfState = resourcesState{ Resources: nil, } err := TerraformToBundle(&tfState, &config) assert.NoError(t, err) assert.Equal(t, "", config.Resources.Jobs["test_job"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Jobs["test_job"].ModifiedStatus) assert.Equal(t, "", config.Resources.Pipelines["test_pipeline"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Pipelines["test_pipeline"].ModifiedStatus) assert.Equal(t, "", config.Resources.Models["test_mlflow_model"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Models["test_mlflow_model"].ModifiedStatus) assert.Equal(t, "", config.Resources.Experiments["test_mlflow_experiment"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Experiments["test_mlflow_experiment"].ModifiedStatus) assert.Equal(t, "", config.Resources.ModelServingEndpoints["test_model_serving"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.ModelServingEndpoints["test_model_serving"].ModifiedStatus) assert.Equal(t, "", config.Resources.RegisteredModels["test_registered_model"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.RegisteredModels["test_registered_model"].ModifiedStatus) assert.Equal(t, "", config.Resources.QualityMonitors["test_monitor"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.QualityMonitors["test_monitor"].ModifiedStatus) assert.Equal(t, "", config.Resources.Schemas["test_schema"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Schemas["test_schema"].ModifiedStatus) assert.Equal(t, "", config.Resources.Volumes["test_volume"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Volumes["test_volume"].ModifiedStatus) assert.Equal(t, "", config.Resources.Clusters["test_cluster"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Clusters["test_cluster"].ModifiedStatus) assert.Equal(t, "", config.Resources.Dashboards["test_dashboard"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Dashboards["test_dashboard"].ModifiedStatus) AssertFullResourceCoverage(t, &config) } func TestTerraformToBundleModifiedResources(t *testing.T) { var config = config.Root{ Resources: config.Resources{ Jobs: map[string]*resources.Job{ "test_job": { JobSettings: &jobs.JobSettings{ Name: "test_job", }, }, "test_job_new": { JobSettings: &jobs.JobSettings{ Name: "test_job_new", }, }, }, Pipelines: map[string]*resources.Pipeline{ "test_pipeline": { PipelineSpec: &pipelines.PipelineSpec{ Name: "test_pipeline", }, }, "test_pipeline_new": { PipelineSpec: &pipelines.PipelineSpec{ Name: "test_pipeline_new", }, }, }, Models: map[string]*resources.MlflowModel{ "test_mlflow_model": { Model: &ml.Model{ Name: "test_mlflow_model", }, }, "test_mlflow_model_new": { Model: &ml.Model{ Name: "test_mlflow_model_new", }, }, }, Experiments: map[string]*resources.MlflowExperiment{ "test_mlflow_experiment": { Experiment: &ml.Experiment{ Name: "test_mlflow_experiment", }, }, "test_mlflow_experiment_new": { Experiment: &ml.Experiment{ Name: "test_mlflow_experiment_new", }, }, }, ModelServingEndpoints: map[string]*resources.ModelServingEndpoint{ "test_model_serving": { CreateServingEndpoint: &serving.CreateServingEndpoint{ Name: "test_model_serving", }, }, "test_model_serving_new": { CreateServingEndpoint: &serving.CreateServingEndpoint{ Name: "test_model_serving_new", }, }, }, RegisteredModels: map[string]*resources.RegisteredModel{ "test_registered_model": { CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ Name: "test_registered_model", }, }, "test_registered_model_new": { CreateRegisteredModelRequest: &catalog.CreateRegisteredModelRequest{ Name: "test_registered_model_new", }, }, }, QualityMonitors: map[string]*resources.QualityMonitor{ "test_monitor": { CreateMonitor: &catalog.CreateMonitor{ TableName: "test_monitor", }, }, "test_monitor_new": { CreateMonitor: &catalog.CreateMonitor{ TableName: "test_monitor_new", }, }, }, Schemas: map[string]*resources.Schema{ "test_schema": { CreateSchema: &catalog.CreateSchema{ Name: "test_schema", }, }, "test_schema_new": { CreateSchema: &catalog.CreateSchema{ Name: "test_schema_new", }, }, }, Volumes: map[string]*resources.Volume{ "test_volume": { CreateVolumeRequestContent: &catalog.CreateVolumeRequestContent{ Name: "test_volume", }, }, "test_volume_new": { CreateVolumeRequestContent: &catalog.CreateVolumeRequestContent{ Name: "test_volume_new", }, }, }, Clusters: map[string]*resources.Cluster{ "test_cluster": { ClusterSpec: &compute.ClusterSpec{ ClusterName: "test_cluster", }, }, "test_cluster_new": { ClusterSpec: &compute.ClusterSpec{ ClusterName: "test_cluster_new", }, }, }, Dashboards: map[string]*resources.Dashboard{ "test_dashboard": { Dashboard: &dashboards.Dashboard{ DisplayName: "test_dashboard", }, }, "test_dashboard_new": { Dashboard: &dashboards.Dashboard{ DisplayName: "test_dashboard_new", }, }, }, }, } var tfState = resourcesState{ Resources: []stateResource{ { Type: "databricks_job", Mode: "managed", Name: "test_job", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_job", Mode: "managed", Name: "test_job_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_pipeline", Mode: "managed", Name: "test_pipeline", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_pipeline", Mode: "managed", Name: "test_pipeline_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_mlflow_model", Mode: "managed", Name: "test_mlflow_model", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_mlflow_model", Mode: "managed", Name: "test_mlflow_model_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_mlflow_experiment", Mode: "managed", Name: "test_mlflow_experiment", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_mlflow_experiment", Mode: "managed", Name: "test_mlflow_experiment_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_model_serving", Mode: "managed", Name: "test_model_serving", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_model_serving", Mode: "managed", Name: "test_model_serving_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_registered_model", Mode: "managed", Name: "test_registered_model", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_registered_model", Mode: "managed", Name: "test_registered_model_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_quality_monitor", Mode: "managed", Name: "test_monitor", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "test_monitor"}}, }, }, { Type: "databricks_quality_monitor", Mode: "managed", Name: "test_monitor_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "test_monitor_old"}}, }, }, { Type: "databricks_schema", Mode: "managed", Name: "test_schema", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_schema", Mode: "managed", Name: "test_schema_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_volume", Mode: "managed", Name: "test_volume", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_cluster", Mode: "managed", Name: "test_cluster", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_volume", Mode: "managed", Name: "test_volume_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_cluster", Mode: "managed", Name: "test_cluster_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, { Type: "databricks_dashboard", Mode: "managed", Name: "test_dashboard", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "1"}}, }, }, { Type: "databricks_dashboard", Mode: "managed", Name: "test_dashboard_old", Instances: []stateResourceInstance{ {Attributes: stateInstanceAttributes{ID: "2"}}, }, }, }, } err := TerraformToBundle(&tfState, &config) assert.NoError(t, err) assert.Equal(t, "1", config.Resources.Jobs["test_job"].ID) assert.Equal(t, "", config.Resources.Jobs["test_job"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Jobs["test_job_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Jobs["test_job_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Jobs["test_job_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Jobs["test_job_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Pipelines["test_pipeline"].ID) assert.Equal(t, "", config.Resources.Pipelines["test_pipeline"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Pipelines["test_pipeline_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Pipelines["test_pipeline_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Pipelines["test_pipeline_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Pipelines["test_pipeline_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Models["test_mlflow_model"].ID) assert.Equal(t, "", config.Resources.Models["test_mlflow_model"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Models["test_mlflow_model_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Models["test_mlflow_model_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Models["test_mlflow_model_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Models["test_mlflow_model_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.RegisteredModels["test_registered_model"].ID) assert.Equal(t, "", config.Resources.RegisteredModels["test_registered_model"].ModifiedStatus) assert.Equal(t, "2", config.Resources.RegisteredModels["test_registered_model_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.RegisteredModels["test_registered_model_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.RegisteredModels["test_registered_model_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.RegisteredModels["test_registered_model_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Experiments["test_mlflow_experiment"].ID) assert.Equal(t, "", config.Resources.Experiments["test_mlflow_experiment"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Experiments["test_mlflow_experiment_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Experiments["test_mlflow_experiment_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Experiments["test_mlflow_experiment_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Experiments["test_mlflow_experiment_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.ModelServingEndpoints["test_model_serving"].ID) assert.Equal(t, "", config.Resources.ModelServingEndpoints["test_model_serving"].ModifiedStatus) assert.Equal(t, "2", config.Resources.ModelServingEndpoints["test_model_serving_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.ModelServingEndpoints["test_model_serving_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.ModelServingEndpoints["test_model_serving_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.ModelServingEndpoints["test_model_serving_new"].ModifiedStatus) assert.Equal(t, "test_monitor", config.Resources.QualityMonitors["test_monitor"].ID) assert.Equal(t, "", config.Resources.QualityMonitors["test_monitor"].ModifiedStatus) assert.Equal(t, "test_monitor_old", config.Resources.QualityMonitors["test_monitor_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.QualityMonitors["test_monitor_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.QualityMonitors["test_monitor_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.QualityMonitors["test_monitor_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Schemas["test_schema"].ID) assert.Equal(t, "", config.Resources.Schemas["test_schema"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Schemas["test_schema_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Schemas["test_schema_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Schemas["test_schema_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Schemas["test_schema_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Volumes["test_volume"].ID) assert.Equal(t, "", config.Resources.Volumes["test_volume"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Volumes["test_volume_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Volumes["test_volume_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Volumes["test_volume_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Volumes["test_volume_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Clusters["test_cluster"].ID) assert.Equal(t, "", config.Resources.Clusters["test_cluster"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Clusters["test_cluster_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Clusters["test_cluster_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Clusters["test_cluster_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Clusters["test_cluster_new"].ModifiedStatus) assert.Equal(t, "1", config.Resources.Dashboards["test_dashboard"].ID) assert.Equal(t, "", config.Resources.Dashboards["test_dashboard"].ModifiedStatus) assert.Equal(t, "2", config.Resources.Dashboards["test_dashboard_old"].ID) assert.Equal(t, resources.ModifiedStatusDeleted, config.Resources.Dashboards["test_dashboard_old"].ModifiedStatus) assert.Equal(t, "", config.Resources.Dashboards["test_dashboard_new"].ID) assert.Equal(t, resources.ModifiedStatusCreated, config.Resources.Dashboards["test_dashboard_new"].ModifiedStatus) AssertFullResourceCoverage(t, &config) } func AssertFullResourceCoverage(t *testing.T, config *config.Root) { resources := reflect.ValueOf(config.Resources) for i := 0; i < resources.NumField(); i++ { field := resources.Field(i) if field.Kind() == reflect.Map { assert.True( t, !field.IsNil() && field.Len() > 0, "TerraformToBundle should support '%s' (please add it to convert.go and extend the test suite)", resources.Type().Field(i).Name, ) } } }