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 }