github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/datadog/datadog_provider.go (about)

     1  // Copyright 2018 The Terraformer Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package datadog
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"fmt"
    21  	"net/url"
    22  	"os"
    23  	"strconv"
    24  
    25  	datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog"
    26  	datadogV2 "github.com/DataDog/datadog-api-client-go/api/v2/datadog"
    27  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    28  	"github.com/zclconf/go-cty/cty"
    29  )
    30  
    31  type DatadogProvider struct { //nolint
    32  	terraformutils.Provider
    33  	apiKey          string
    34  	appKey          string
    35  	apiURL          string
    36  	validate        bool
    37  	authV1          context.Context
    38  	authV2          context.Context
    39  	datadogClientV1 *datadogV1.APIClient
    40  	datadogClientV2 *datadogV2.APIClient
    41  }
    42  
    43  // Init check env params and initialize API Client
    44  func (p *DatadogProvider) Init(args []string) error {
    45  
    46  	if args[3] != "" {
    47  		validate, validateErr := strconv.ParseBool(args[3])
    48  		if validateErr != nil {
    49  			return fmt.Errorf(`invalid validate arg : %v`, validateErr)
    50  		}
    51  		p.validate = validate
    52  	} else if os.Getenv("DATADOG_VALIDATE") != "" {
    53  		validate, validateErr := strconv.ParseBool(os.Getenv("DATADOG_VALIDATE"))
    54  		if validateErr != nil {
    55  			return fmt.Errorf(`invalid DATADOG_VALIDATE env var : %v`, validateErr)
    56  		}
    57  		p.validate = validate
    58  	} else {
    59  		p.validate = true
    60  	}
    61  
    62  	if args[0] != "" {
    63  		p.apiKey = args[0]
    64  	} else {
    65  		if apiKey := os.Getenv("DATADOG_API_KEY"); apiKey != "" {
    66  			p.apiKey = apiKey
    67  		} else if p.validate {
    68  			return errors.New("api-key requirement")
    69  		}
    70  	}
    71  
    72  	if args[1] != "" {
    73  		p.appKey = args[1]
    74  	} else {
    75  		if appKey := os.Getenv("DATADOG_APP_KEY"); appKey != "" {
    76  			p.appKey = appKey
    77  		} else if p.validate {
    78  			return errors.New("app-key requirement")
    79  		}
    80  	}
    81  
    82  	if args[2] != "" {
    83  		p.apiURL = args[2]
    84  	} else if v := os.Getenv("DATADOG_HOST"); v != "" {
    85  		p.apiURL = v
    86  	}
    87  
    88  	// Initialize the Datadog V1 API client
    89  	authV1 := context.WithValue(
    90  		context.Background(),
    91  		datadogV1.ContextAPIKeys,
    92  		map[string]datadogV1.APIKey{
    93  			"apiKeyAuth": {
    94  				Key: p.apiKey,
    95  			},
    96  			"appKeyAuth": {
    97  				Key: p.appKey,
    98  			},
    99  		},
   100  	)
   101  	if p.apiURL != "" {
   102  		parsedAPIURL, parseErr := url.Parse(p.apiURL)
   103  		if parseErr != nil {
   104  			return fmt.Errorf(`invalid API Url : %v`, parseErr)
   105  		}
   106  		if parsedAPIURL.Host == "" || parsedAPIURL.Scheme == "" {
   107  			return fmt.Errorf(`missing protocol or host : %v`, p.apiURL)
   108  		}
   109  		// If api url is passed, set and use the api name and protocol on ServerIndex{1}
   110  		authV1 = context.WithValue(authV1, datadogV1.ContextServerIndex, 1)
   111  		authV1 = context.WithValue(authV1, datadogV1.ContextServerVariables, map[string]string{
   112  			"name":     parsedAPIURL.Host,
   113  			"protocol": parsedAPIURL.Scheme,
   114  		})
   115  	}
   116  	configV1 := datadogV1.NewConfiguration()
   117  	datadogClientV1 := datadogV1.NewAPIClient(configV1)
   118  
   119  	// Initialize the Datadog V2 API client
   120  	authV2 := context.WithValue(
   121  		context.Background(),
   122  		datadogV2.ContextAPIKeys,
   123  		map[string]datadogV2.APIKey{
   124  			"apiKeyAuth": {
   125  				Key: p.apiKey,
   126  			},
   127  			"appKeyAuth": {
   128  				Key: p.appKey,
   129  			},
   130  		},
   131  	)
   132  	if p.apiURL != "" {
   133  		parsedAPIURL, parseErr := url.Parse(p.apiURL)
   134  		if parseErr != nil {
   135  			return fmt.Errorf(`invalid API Url : %v`, parseErr)
   136  		}
   137  		if parsedAPIURL.Host == "" || parsedAPIURL.Scheme == "" {
   138  			return fmt.Errorf(`missing protocol or host : %v`, p.apiURL)
   139  		}
   140  		// If api url is passed, set and use the api name and protocol on ServerIndex{1}
   141  		authV2 = context.WithValue(authV2, datadogV2.ContextServerIndex, 1)
   142  		authV2 = context.WithValue(authV2, datadogV2.ContextServerVariables, map[string]string{
   143  			"name":     parsedAPIURL.Host,
   144  			"protocol": parsedAPIURL.Scheme,
   145  		})
   146  	}
   147  	configV2 := datadogV2.NewConfiguration()
   148  	datadogClientV2 := datadogV2.NewAPIClient(configV2)
   149  
   150  	p.authV1 = authV1
   151  	p.authV2 = authV2
   152  	p.datadogClientV1 = datadogClientV1
   153  	p.datadogClientV2 = datadogClientV2
   154  
   155  	return nil
   156  }
   157  
   158  // GetName return string of provider name for Datadog
   159  func (p *DatadogProvider) GetName() string {
   160  	return "datadog"
   161  }
   162  
   163  // GetConfig return map of provider config for Datadog
   164  func (p *DatadogProvider) GetConfig() cty.Value {
   165  	return cty.ObjectVal(map[string]cty.Value{
   166  		"api_key":  cty.StringVal(p.apiKey),
   167  		"app_key":  cty.StringVal(p.appKey),
   168  		"api_url":  cty.StringVal(p.apiURL),
   169  		"validate": cty.BoolVal(p.validate),
   170  	})
   171  }
   172  
   173  // InitService ...
   174  func (p *DatadogProvider) InitService(serviceName string, verbose bool) error {
   175  	var isSupported bool
   176  	if _, isSupported = p.GetSupportedService()[serviceName]; !isSupported {
   177  		return errors.New(p.GetName() + ": " + serviceName + " not supported service")
   178  	}
   179  	p.Service = p.GetSupportedService()[serviceName]
   180  	p.Service.SetName(serviceName)
   181  	p.Service.SetVerbose(verbose)
   182  	p.Service.SetProviderName(p.GetName())
   183  	p.Service.SetArgs(map[string]interface{}{
   184  		"api-key":         p.apiKey,
   185  		"app-key":         p.appKey,
   186  		"api-url":         p.apiURL,
   187  		"validate":        p.validate,
   188  		"authV1":          p.authV1,
   189  		"authV2":          p.authV2,
   190  		"datadogClientV1": p.datadogClientV1,
   191  		"datadogClientV2": p.datadogClientV2,
   192  	})
   193  	return nil
   194  }
   195  
   196  // GetSupportedService return map of support service for Datadog
   197  func (p *DatadogProvider) GetSupportedService() map[string]terraformutils.ServiceGenerator {
   198  	return map[string]terraformutils.ServiceGenerator{
   199  		"dashboard_list":                       &DashboardListGenerator{},
   200  		"dashboard":                            &DashboardGenerator{},
   201  		"dashboard_json":                       &DashboardJSONGenerator{},
   202  		"downtime":                             &DowntimeGenerator{},
   203  		"logs_archive":                         &LogsArchiveGenerator{},
   204  		"logs_archive_order":                   &LogsArchiveOrderGenerator{},
   205  		"logs_custom_pipeline":                 &LogsCustomPipelineGenerator{},
   206  		"logs_index":                           &LogsIndexGenerator{},
   207  		"logs_index_order":                     &LogsIndexOrderGenerator{},
   208  		"logs_integration_pipeline":            &LogsIntegrationPipelineGenerator{},
   209  		"logs_pipeline_order":                  &LogsPipelineOrderGenerator{},
   210  		"integration_aws":                      &IntegrationAWSGenerator{},
   211  		"integration_aws_lambda_arn":           &IntegrationAWSLambdaARNGenerator{},
   212  		"integration_aws_log_collection":       &IntegrationAWSLogCollectionGenerator{},
   213  		"integration_azure":                    &IntegrationAzureGenerator{},
   214  		"integration_gcp":                      &IntegrationGCPGenerator{},
   215  		"integration_pagerduty":                &IntegrationPagerdutyGenerator{},
   216  		"integration_pagerduty_service_object": &IntegrationPagerdutyServiceObjectGenerator{},
   217  		"integration_slack_channel":            &IntegrationSlackChannelGenerator{},
   218  		"metric_metadata":                      &MetricMetadataGenerator{},
   219  		"monitor":                              &MonitorGenerator{},
   220  		"security_monitoring_default_rule":     &SecurityMonitoringDefaultRuleGenerator{},
   221  		"security_monitoring_rule":             &SecurityMonitoringRuleGenerator{},
   222  		"service_level_objective":              &ServiceLevelObjectiveGenerator{},
   223  		"synthetics_test":                      &SyntheticsTestGenerator{},
   224  		"synthetics_global_variable":           &SyntheticsGlobalVariableGenerator{},
   225  		"synthetics_private_location":          &SyntheticsPrivateLocationGenerator{},
   226  		"user":                                 &UserGenerator{},
   227  		"role":                                 &RoleGenerator{},
   228  	}
   229  }
   230  
   231  // GetResourceConnections return map of resource connections for Datadog
   232  func (p DatadogProvider) GetResourceConnections() map[string]map[string][]string {
   233  	return map[string]map[string][]string{
   234  		"dashboard": {
   235  			"monitor": {
   236  				"widget.alert_graph_definition.alert_id", "id",
   237  				"widget.group_definition.widget.alert_graph_definition.alert_id", "id",
   238  				"widget.alert_value_definition.alert_id", "id",
   239  				"widget.group_definition.widget.alert_value_definition.alert_id", "id",
   240  			},
   241  			"service_level_objective": {
   242  				"widget.service_level_objective_definition.slo_id", "id",
   243  				"widget.group_definition.widget.service_level_objective_definition.slo_id", "id",
   244  			},
   245  		},
   246  		"dashboard_list": {
   247  			"dashboard": {
   248  				"dash_item.dash_id", "id",
   249  			},
   250  		},
   251  		"downtime": {
   252  			"monitor": {
   253  				"monitor_id", "id",
   254  			},
   255  		},
   256  		"integration_aws_lambda_arn": {
   257  			"integration_aws": {
   258  				"account_id", "account_id",
   259  			},
   260  		},
   261  		"integration_aws_log_collection": {
   262  			"integration_aws": {
   263  				"account_id", "account_id",
   264  			},
   265  		},
   266  		"logs_archive": {
   267  			"integration_aws": {
   268  				"s3.account_id", "account_id",
   269  				"s3.role_name", "role_name",
   270  				"s3_archive.account_id", "account_id",
   271  				"s3_archive.role_name", "role_name",
   272  			},
   273  			"integration_gcp": {
   274  				"gcs.project_id", "project_id",
   275  				"gcs.client_email", "client_email",
   276  				"gcs_archive.project_id", "project_id",
   277  				"gcs_archive.client_email", "client_email",
   278  			},
   279  			"integration_azure": {
   280  				"azure.client_id", "client_id",
   281  				"azure.tenant_id", "tenant_name",
   282  				"azure_archive.client_id", "client_id",
   283  				"azure_archive.tenant_id", "tenant_name",
   284  			},
   285  		},
   286  		"logs_archive_order": {
   287  			"logs_archive": {
   288  				"archive_ids", "id",
   289  			},
   290  		},
   291  		"logs_index_order": {
   292  			"logs_index": {
   293  				"indexes", "id",
   294  			},
   295  		},
   296  		"logs_pipeline_order": {
   297  			"logs_integration_pipeline": {
   298  				"pipelines", "id",
   299  			},
   300  			"logs_custom_pipeline": {
   301  				"pipelines", "id",
   302  			},
   303  		},
   304  		"monitor": {
   305  			"role": {
   306  				"restricted_roles", "id",
   307  			},
   308  		},
   309  		"service_level_objective": {
   310  			"monitor": {
   311  				"monitor_ids", "id",
   312  			},
   313  		},
   314  		"synthetics_test": {
   315  			"synthetics_private_location": {
   316  				"locations", "id",
   317  			},
   318  		},
   319  		"synthetics_global_variable": {
   320  			"synthetics_test": {
   321  				"parse_test_id", "id",
   322  			},
   323  		},
   324  		"user": {
   325  			"role": {
   326  				"roles", "id",
   327  			},
   328  		},
   329  	}
   330  }
   331  
   332  // GetProviderData return map of provider data for Datadog
   333  func (p DatadogProvider) GetProviderData(arg ...string) map[string]interface{} {
   334  	return map[string]interface{}{}
   335  }