├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ ├── dependabot.yml │ ├── e2e.yml │ ├── goreleaser.yml │ ├── maintenance.yml │ └── release.yml ├── .gitmodules ├── .goreleaser.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── docs ├── configuration.md ├── deep_checking.md └── rules │ ├── README.md │ ├── google_disabled_api.md │ ├── google_project_iam_audit_config_invalid_member.md │ ├── google_project_iam_binding_invalid_member.md │ ├── google_project_iam_invalid_member.md │ ├── google_project_iam_member_invalid_member.md │ ├── google_project_iam_policy_invalid_member.md │ └── rule.md.tmpl ├── go.mod ├── go.sum ├── google ├── client.go ├── config.go ├── provider.go ├── ruleset.go └── runner.go ├── integration ├── basic │ ├── .tflint.hcl │ ├── main.tf │ └── result.json └── integration_test.go ├── main.go ├── project └── main.go ├── rules ├── api │ ├── google_disabled_api.go │ ├── google_disabled_api_test.go │ ├── helper_test.go │ └── provider.go ├── generator │ └── main.go ├── google_composer_environment_invalid_machine_type.go ├── google_composer_environment_invalid_machine_type_test.go ├── google_compute_instance_invalid_machine_type.go ├── google_compute_instance_invalid_machine_type_test.go ├── google_compute_instance_template_invalid_machine_type.go ├── google_compute_instance_template_invalid_machine_type_test.go ├── google_compute_reservation_invalid_machine_type.go ├── google_compute_reservation_invalid_machine_type_test.go ├── google_compute_resource_policy_invalid_name.go ├── google_compute_resource_policy_invalid_name_test.go ├── google_container_cluster_invalid_machine_type.go ├── google_container_cluster_invalid_machine_type_test.go ├── google_container_node_pool_invalid_machine_type.go ├── google_container_node_pool_invalid_machine_type_test.go ├── google_dataflow_job_invalid_machine_type.go ├── google_dataflow_job_invalid_machine_type_test.go ├── google_project_iam_audit_config_invalid_member.go ├── google_project_iam_audit_config_invalid_member_test.go ├── google_project_iam_binding_invalid_member.go ├── google_project_iam_binding_invalid_member_test.go ├── google_project_iam_member_invalid_member.go ├── google_project_iam_member_invalid_member_test.go ├── google_project_iam_policy_invalid_member.go ├── google_project_iam_policy_invalid_member_test.go ├── magicmodules │ ├── api_definition.go │ ├── generated_rules_test.go │ ├── google_access_context_manager_authorized_orgs_desc_invalid_asset_type.go │ ├── google_access_context_manager_authorized_orgs_desc_invalid_authorization_direction.go │ ├── google_access_context_manager_authorized_orgs_desc_invalid_authorization_type.go │ ├── google_access_context_manager_service_perimeter_invalid_perimeter_type.go │ ├── google_active_directory_domain_trust_invalid_trust_direction.go │ ├── google_active_directory_domain_trust_invalid_trust_type.go │ ├── google_alloydb_backup_invalid_type.go │ ├── google_alloydb_cluster_invalid_cluster_type.go │ ├── google_alloydb_cluster_invalid_subscription_type.go │ ├── google_alloydb_instance_invalid_availability_type.go │ ├── google_alloydb_instance_invalid_instance_type.go │ ├── google_alloydb_user_invalid_user_type.go │ ├── google_apigee_app_group_invalid_status.go │ ├── google_apigee_environment_invalid_api_proxy_type.go │ ├── google_apigee_environment_invalid_deployment_type.go │ ├── google_apigee_environment_invalid_type.go │ ├── google_apigee_organization_invalid_retention.go │ ├── google_apigee_organization_invalid_runtime_type.go │ ├── google_apigee_target_server_invalid_protocol.go │ ├── google_app_engine_domain_mapping_invalid_override_strategy.go │ ├── google_app_engine_firewall_rule_invalid_action.go │ ├── google_app_engine_flexible_app_version_invalid_serving_status.go │ ├── google_artifact_registry_repository_invalid_mode.go │ ├── google_backup_dr_backup_vault_invalid_access_restriction.go │ ├── google_backup_dr_management_server_invalid_type.go │ ├── google_beyondcorp_app_gateway_invalid_host_type.go │ ├── google_beyondcorp_app_gateway_invalid_type.go │ ├── google_beyondcorp_security_gateway_invalid_location.go │ ├── google_biglake_table_invalid_type.go │ ├── google_bigquery_datapolicy_data_policy_invalid_data_policy_type.go │ ├── google_bigquery_routine_invalid_data_governance_type.go │ ├── google_bigquery_routine_invalid_determinism_level.go │ ├── google_bigquery_routine_invalid_language.go │ ├── google_bigquery_routine_invalid_routine_type.go │ ├── google_billing_budget_invalid_ownership_scope.go │ ├── google_binary_authorization_policy_invalid_global_policy_evaluation_mode.go │ ├── google_blockchain_node_engine_blockchain_nodes_invalid_blockchain_type.go │ ├── google_certificate_manager_certificate_issuance_config_invalid_key_algorithm.go │ ├── google_certificate_manager_dns_authorization_invalid_type.go │ ├── google_cloud_asset_folder_feed_invalid_content_type.go │ ├── google_cloud_asset_organization_feed_invalid_content_type.go │ ├── google_cloud_asset_project_feed_invalid_content_type.go │ ├── google_cloud_identity_group_invalid_initial_group_config.go │ ├── google_cloud_ids_endpoint_invalid_severity.go │ ├── google_cloud_quotas_quota_preference_invalid_ignore_safety_checks.go │ ├── google_cloud_run_v2_job_invalid_launch_stage.go │ ├── google_cloud_run_v2_service_invalid_ingress.go │ ├── google_cloud_run_v2_service_invalid_launch_stage.go │ ├── google_cloudbuild_trigger_invalid_include_build_logs.go │ ├── google_compute_address_invalid_address_type.go │ ├── google_compute_address_invalid_ip_version.go │ ├── google_compute_address_invalid_ipv6_endpoint_type.go │ ├── google_compute_address_invalid_name.go │ ├── google_compute_address_invalid_network_tier.go │ ├── google_compute_backend_bucket_invalid_compression_mode.go │ ├── google_compute_backend_bucket_invalid_name.go │ ├── google_compute_backend_bucket_signed_url_key_invalid_name.go │ ├── google_compute_backend_service_invalid_compression_mode.go │ ├── google_compute_backend_service_invalid_ip_address_selection_policy.go │ ├── google_compute_backend_service_invalid_load_balancing_scheme.go │ ├── google_compute_backend_service_invalid_locality_lb_policy.go │ ├── google_compute_backend_service_invalid_protocol.go │ ├── google_compute_backend_service_invalid_session_affinity.go │ ├── google_compute_backend_service_signed_url_key_invalid_name.go │ ├── google_compute_external_vpn_gateway_invalid_redundancy_type.go │ ├── google_compute_firewall_invalid_direction.go │ ├── google_compute_firewall_policy_rule_invalid_direction.go │ ├── google_compute_forwarding_rule_invalid_ip_protocol.go │ ├── google_compute_forwarding_rule_invalid_ip_version.go │ ├── google_compute_forwarding_rule_invalid_load_balancing_scheme.go │ ├── google_compute_forwarding_rule_invalid_network_tier.go │ ├── google_compute_global_address_invalid_address_type.go │ ├── google_compute_global_address_invalid_ip_version.go │ ├── google_compute_global_forwarding_rule_invalid_ip_protocol.go │ ├── google_compute_global_forwarding_rule_invalid_ip_version.go │ ├── google_compute_global_forwarding_rule_invalid_load_balancing_scheme.go │ ├── google_compute_global_forwarding_rule_invalid_network_tier.go │ ├── google_compute_global_network_endpoint_group_invalid_network_endpoint_type.go │ ├── google_compute_ha_vpn_gateway_invalid_gateway_ip_version.go │ ├── google_compute_ha_vpn_gateway_invalid_stack_type.go │ ├── google_compute_interconnect_attachment_invalid_bandwidth.go │ ├── google_compute_interconnect_attachment_invalid_encryption.go │ ├── google_compute_interconnect_attachment_invalid_name.go │ ├── google_compute_interconnect_attachment_invalid_stack_type.go │ ├── google_compute_interconnect_attachment_invalid_type.go │ ├── google_compute_interconnect_invalid_interconnect_type.go │ ├── google_compute_interconnect_invalid_link_type.go │ ├── google_compute_interconnect_invalid_name.go │ ├── google_compute_managed_ssl_certificate_invalid_type.go │ ├── google_compute_network_attachment_invalid_connection_preference.go │ ├── google_compute_network_endpoint_group_invalid_network_endpoint_type.go │ ├── google_compute_network_firewall_policy_rule_invalid_direction.go │ ├── google_compute_network_invalid_network_firewall_policy_enforcement_order.go │ ├── google_compute_node_template_invalid_cpu_overcommit_type.go │ ├── google_compute_project_cloud_armor_tier_invalid_cloud_armor_tier.go │ ├── google_compute_public_advertised_prefix_invalid_pdp_scope.go │ ├── google_compute_public_delegated_prefix_invalid_mode.go │ ├── google_compute_region_backend_service_invalid_ip_address_selection_policy.go │ ├── google_compute_region_backend_service_invalid_load_balancing_scheme.go │ ├── google_compute_region_backend_service_invalid_locality_lb_policy.go │ ├── google_compute_region_backend_service_invalid_protocol.go │ ├── google_compute_region_backend_service_invalid_session_affinity.go │ ├── google_compute_region_commitment_invalid_category.go │ ├── google_compute_region_commitment_invalid_plan.go │ ├── google_compute_region_network_endpoint_group_invalid_network_endpoint_type.go │ ├── google_compute_region_network_firewall_policy_rule_invalid_direction.go │ ├── google_compute_region_ssl_policy_invalid_min_tls_version.go │ ├── google_compute_region_ssl_policy_invalid_profile.go │ ├── google_compute_region_target_tcp_proxy_invalid_proxy_header.go │ ├── google_compute_route_invalid_name.go │ ├── google_compute_router_nat_invalid_auto_network_tier.go │ ├── google_compute_router_nat_invalid_nat_ip_allocate_option.go │ ├── google_compute_router_nat_invalid_source_subnetwork_ip_ranges_to_nat.go │ ├── google_compute_router_nat_invalid_type.go │ ├── google_compute_router_route_policy_invalid_type.go │ ├── google_compute_ssl_policy_invalid_min_tls_version.go │ ├── google_compute_ssl_policy_invalid_profile.go │ ├── google_compute_subnetwork_invalid_ipv6_access_type.go │ ├── google_compute_subnetwork_invalid_role.go │ ├── google_compute_subnetwork_invalid_stack_type.go │ ├── google_compute_target_https_proxy_invalid_quic_override.go │ ├── google_compute_target_https_proxy_invalid_tls_early_data.go │ ├── google_compute_target_instance_invalid_nat_policy.go │ ├── google_compute_target_ssl_proxy_invalid_proxy_header.go │ ├── google_compute_target_tcp_proxy_invalid_proxy_header.go │ ├── google_data_catalog_entry_group_invalid_entry_group_id.go │ ├── google_data_catalog_entry_invalid_type.go │ ├── google_data_catalog_entry_invalid_user_specified_system.go │ ├── google_data_catalog_entry_invalid_user_specified_type.go │ ├── google_data_catalog_tag_template_invalid_tag_template_id.go │ ├── google_data_fusion_instance_invalid_type.go │ ├── google_data_loss_prevention_discovery_config_invalid_status.go │ ├── google_data_loss_prevention_job_trigger_invalid_status.go │ ├── google_data_pipeline_pipeline_invalid_state.go │ ├── google_data_pipeline_pipeline_invalid_type.go │ ├── google_database_migration_service_migration_job_invalid_dump_type.go │ ├── google_database_migration_service_migration_job_invalid_type.go │ ├── google_dataproc_metastore_service_invalid_database_type.go │ ├── google_dataproc_metastore_service_invalid_release_channel.go │ ├── google_dataproc_metastore_service_invalid_tier.go │ ├── google_deployment_manager_deployment_invalid_create_policy.go │ ├── google_deployment_manager_deployment_invalid_delete_policy.go │ ├── google_dialogflow_agent_invalid_api_version.go │ ├── google_dialogflow_agent_invalid_match_mode.go │ ├── google_dialogflow_agent_invalid_tier.go │ ├── google_dialogflow_cx_entity_type_invalid_auto_expansion_mode.go │ ├── google_dialogflow_cx_entity_type_invalid_kind.go │ ├── google_dialogflow_cx_security_settings_invalid_redaction_scope.go │ ├── google_dialogflow_cx_security_settings_invalid_redaction_strategy.go │ ├── google_dialogflow_cx_security_settings_invalid_retention_strategy.go │ ├── google_dialogflow_entity_type_invalid_kind.go │ ├── google_dialogflow_intent_invalid_webhook_state.go │ ├── google_discovery_engine_chat_engine_invalid_industry_vertical.go │ ├── google_discovery_engine_data_store_invalid_content_config.go │ ├── google_discovery_engine_data_store_invalid_industry_vertical.go │ ├── google_discovery_engine_search_engine_invalid_industry_vertical.go │ ├── google_discovery_engine_target_site_invalid_type.go │ ├── google_dns_managed_zone_invalid_visibility.go │ ├── google_document_ai_warehouse_location_invalid_access_control_mode.go │ ├── google_document_ai_warehouse_location_invalid_database_type.go │ ├── google_document_ai_warehouse_location_invalid_document_creator_default_role.go │ ├── google_edgecontainer_cluster_invalid_release_channel.go │ ├── google_filestore_instance_invalid_protocol.go │ ├── google_firebase_app_check_service_config_invalid_enforcement_mode.go │ ├── google_firebase_app_hosting_backend_invalid_serving_locality.go │ ├── google_firestore_database_invalid_app_engine_integration_mode.go │ ├── google_firestore_database_invalid_concurrency_mode.go │ ├── google_firestore_database_invalid_database_edition.go │ ├── google_firestore_database_invalid_delete_protection_state.go │ ├── google_firestore_database_invalid_point_in_time_recovery_enablement.go │ ├── google_firestore_database_invalid_type.go │ ├── google_firestore_index_invalid_api_scope.go │ ├── google_firestore_index_invalid_density.go │ ├── google_firestore_index_invalid_query_scope.go │ ├── google_gemini_code_tools_setting_binding_invalid_product.go │ ├── google_gemini_data_sharing_with_google_setting_binding_invalid_product.go │ ├── google_gemini_gemini_gcp_enablement_setting_binding_invalid_product.go │ ├── google_gemini_logging_setting_binding_invalid_product.go │ ├── google_gemini_release_channel_setting_binding_invalid_product.go │ ├── google_healthcare_fhir_store_invalid_complex_data_type_reference_parsing.go │ ├── google_healthcare_fhir_store_invalid_version.go │ ├── google_integration_connectors_connection_invalid_eventing_enablement_type.go │ ├── google_integrations_auth_config_invalid_visibility.go │ ├── google_kms_crypto_key_version_invalid_state.go │ ├── google_kms_ekm_connection_invalid_key_management_mode.go │ ├── google_kms_key_ring_import_job_invalid_import_method.go │ ├── google_kms_key_ring_import_job_invalid_protection_level.go │ ├── google_looker_instance_invalid_name.go │ ├── google_looker_instance_invalid_platform_edition.go │ ├── google_memcache_instance_invalid_memcache_version.go │ ├── google_memorystore_instance_invalid_mode.go │ ├── google_monitoring_alert_policy_invalid_combiner.go │ ├── google_monitoring_alert_policy_invalid_severity.go │ ├── google_monitoring_custom_service_invalid_service_id.go │ ├── google_monitoring_metric_descriptor_invalid_launch_stage.go │ ├── google_monitoring_metric_descriptor_invalid_metric_kind.go │ ├── google_monitoring_metric_descriptor_invalid_value_type.go │ ├── google_monitoring_slo_invalid_calendar_period.go │ ├── google_monitoring_slo_invalid_slo_id.go │ ├── google_monitoring_uptime_check_config_invalid_checker_type.go │ ├── google_netapp_storage_pool_invalid_service_level.go │ ├── google_netapp_volume_invalid_security_style.go │ ├── google_netapp_volume_quota_rule_invalid_type.go │ ├── google_netapp_volume_replication_invalid_replication_schedule.go │ ├── google_network_connectivity_group_invalid_name.go │ ├── google_network_connectivity_hub_invalid_policy_mode.go │ ├── google_network_connectivity_hub_invalid_preset_topology.go │ ├── google_network_connectivity_internal_range_invalid_peering.go │ ├── google_network_connectivity_internal_range_invalid_usage.go │ ├── google_network_connectivity_policy_based_route_invalid_next_hop_other_routes.go │ ├── google_network_connectivity_regional_endpoint_invalid_access_type.go │ ├── google_network_security_address_group_invalid_type.go │ ├── google_network_security_authz_policy_invalid_action.go │ ├── google_network_security_gateway_security_policy_rule_invalid_basic_profile.go │ ├── google_network_security_security_profile_invalid_type.go │ ├── google_network_security_tls_inspection_policy_invalid_min_tls_version.go │ ├── google_network_security_tls_inspection_policy_invalid_tls_feature_profile.go │ ├── google_network_services_authz_extension_invalid_load_balancing_scheme.go │ ├── google_network_services_authz_extension_invalid_wire_format.go │ ├── google_network_services_edge_cache_origin_invalid_protocol.go │ ├── google_network_services_endpoint_policy_invalid_type.go │ ├── google_network_services_gateway_invalid_envoy_headers.go │ ├── google_network_services_gateway_invalid_ip_version.go │ ├── google_network_services_gateway_invalid_routing_mode.go │ ├── google_network_services_gateway_invalid_type.go │ ├── google_network_services_grpc_route_invalid_location.go │ ├── google_network_services_lb_route_extension_invalid_load_balancing_scheme.go │ ├── google_network_services_lb_traffic_extension_invalid_load_balancing_scheme.go │ ├── google_network_services_mesh_invalid_location.go │ ├── google_notebooks_instance_invalid_boot_disk_type.go │ ├── google_notebooks_instance_invalid_data_disk_type.go │ ├── google_notebooks_instance_invalid_disk_encryption.go │ ├── google_notebooks_instance_invalid_nic_type.go │ ├── google_org_policy_custom_constraint_invalid_action_type.go │ ├── google_os_config_patch_deployment_invalid_patch_deployment_id.go │ ├── google_parameter_manager_parameter_invalid_format.go │ ├── google_parameter_manager_regional_parameter_invalid_format.go │ ├── google_privateca_ca_pool_invalid_tier.go │ ├── google_privateca_certificate_authority_invalid_type.go │ ├── google_pubsub_schema_invalid_type.go │ ├── google_pubsub_subscription_invalid_filter.go │ ├── google_redis_cluster_invalid_authorization_mode.go │ ├── google_redis_cluster_invalid_node_type.go │ ├── google_redis_cluster_invalid_transit_encryption_mode.go │ ├── google_redis_instance_invalid_connect_mode.go │ ├── google_redis_instance_invalid_name.go │ ├── google_redis_instance_invalid_read_replicas_mode.go │ ├── google_redis_instance_invalid_tier.go │ ├── google_redis_instance_invalid_transit_encryption_mode.go │ ├── google_scc_event_threat_detection_custom_module_invalid_enablement_state.go │ ├── google_scc_folder_custom_module_invalid_enablement_state.go │ ├── google_scc_management_folder_security_health_analytics_custom_module_invalid_enablement_state.go │ ├── google_scc_management_organization_event_threat_detection_custom_module_invalid_enablement_state.go │ ├── google_scc_management_organization_security_health_analytics_custom_module_invalid_enablement_state.go │ ├── google_scc_management_project_security_health_analytics_custom_module_invalid_enablement_state.go │ ├── google_scc_mute_config_invalid_type.go │ ├── google_scc_organization_custom_module_invalid_enablement_state.go │ ├── google_scc_project_custom_module_invalid_enablement_state.go │ ├── google_scc_source_invalid_display_name.go │ ├── google_scc_v2_organization_source_invalid_display_name.go │ ├── google_securityposture_posture_invalid_state.go │ ├── google_site_verification_web_resource_invalid_verification_method.go │ ├── google_spanner_backup_schedule_invalid_name.go │ ├── google_spanner_database_invalid_database_dialect.go │ ├── google_spanner_database_invalid_name.go │ ├── google_spanner_instance_invalid_default_backup_schedule_type.go │ ├── google_spanner_instance_invalid_edition.go │ ├── google_spanner_instance_invalid_name.go │ ├── google_spanner_instance_partition_invalid_name.go │ ├── google_storage_anywhere_cache_invalid_admission_policy.go │ ├── google_storage_bucket_access_control_invalid_role.go │ ├── google_storage_default_object_access_control_invalid_role.go │ ├── google_storage_hmac_key_invalid_state.go │ ├── google_storage_managed_folder_invalid_name.go │ ├── google_storage_object_access_control_invalid_role.go │ ├── google_tags_tag_key_invalid_purpose.go │ ├── google_vmwareengine_external_access_rule_invalid_action.go │ ├── google_vmwareengine_network_invalid_type.go │ ├── google_vmwareengine_network_peering_invalid_peer_network_type.go │ ├── google_vmwareengine_private_cloud_invalid_type.go │ ├── google_workflows_workflow_invalid_call_log_level.go │ ├── google_workflows_workflow_invalid_execution_history_level.go │ ├── provider.go │ ├── validation.go │ └── verify │ │ └── validation.go ├── provider.go ├── rule.go.tmpl ├── rule_test.go.tmpl └── utils.go └── tools ├── README.md └── release ├── go.mod ├── go.sum ├── main.go └── release-note.md /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: weekly 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | schedule: 11 | - cron: "0 0 * * *" 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | test: 18 | name: ${{ matrix.os }} 19 | runs-on: ${{ matrix.os }} 20 | strategy: 21 | matrix: 22 | os: [ubuntu-latest, windows-latest] 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 26 | - name: Set up Go 27 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 28 | with: 29 | go-version-file: 'go.mod' 30 | - name: Run tests 31 | run: make test 32 | - name: Run build 33 | run: make build 34 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: github.event.pull_request.user.login == 'dependabot[bot]' 12 | steps: 13 | - name: Enable auto-merge for Dependabot PRs 14 | run: gh pr merge --auto --squash "$PR_URL" 15 | env: 16 | PR_URL: ${{github.event.pull_request.html_url}} 17 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 18 | -------------------------------------------------------------------------------- /.github/workflows/e2e.yml: -------------------------------------------------------------------------------- 1 | name: e2e 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | schedule: 11 | - cron: "0 0 * * *" 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | e2e: 18 | name: ${{ matrix.os }} (${{ matrix.version }}) 19 | runs-on: ${{ matrix.os }} 20 | strategy: 21 | matrix: 22 | os: [ubuntu-latest, windows-latest] 23 | version: [v0.42.0, latest] 24 | env: 25 | TFLINT_VERSION: ${{ matrix.version }} 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | - name: Set up Go 30 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 31 | with: 32 | go-version-file: 'go.mod' 33 | - name: Install TFLint 34 | run: curl -sL https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash 35 | env: 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | - name: Install plugin (Linux) 38 | if: runner.os == 'Linux' 39 | run: make install 40 | - name: Install plugin (Windows) 41 | if: runner.os == 'Windows' 42 | run: | 43 | mkdir -p ~/.tflint.d/plugins 44 | go build -o ~/.tflint.d/plugins/tflint-ruleset-google.exe 45 | shell: bash 46 | - name: Run E2E tests 47 | run: make e2e 48 | -------------------------------------------------------------------------------- /.github/workflows/goreleaser.yml: -------------------------------------------------------------------------------- 1 | name: goreleaser 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | permissions: 12 | contents: read 13 | 14 | jobs: 15 | check: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | with: 21 | fetch-depth: 0 22 | - name: Set up Go 23 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 24 | with: 25 | go-version-file: 'go.mod' 26 | - name: Run GoReleaser 27 | uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 28 | with: 29 | version: v2.7.0 30 | args: check 31 | -------------------------------------------------------------------------------- /.github/workflows/maintenance.yml: -------------------------------------------------------------------------------- 1 | name: maintenance 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | schedule: 7 | - cron: '0 0 * * 1' 8 | workflow_dispatch: # Enables on-demand/manual triggering 9 | 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | 14 | jobs: 15 | job: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 19 | - run: git submodule update --init --depth=0 20 | - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 21 | with: 22 | go-version-file: 'go.mod' 23 | - name: make tflint in tools/magic-modules 24 | run: | 25 | git submodule update --remote 26 | go install golang.org/x/tools/cmd/goimports@latest 27 | cd tools/magic-modules 28 | make tflint 29 | env: 30 | OUTPUT_PATH: ${{ github.workspace }}/rules/magicmodules 31 | - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 32 | with: 33 | commit-message: | 34 | Update Magic Modules 35 | title: Update Magic Modules 36 | delete-branch: true 37 | body: | 38 | This is an automated pull request triggered by GitHub Actions. To trigger check runs, close and re-open it. 39 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | branches: 6 | - '!*' 7 | tags: 8 | - v*.*.* 9 | 10 | permissions: 11 | contents: write 12 | id-token: write 13 | attestations: write 14 | 15 | jobs: 16 | goreleaser: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 21 | with: 22 | fetch-depth: 0 23 | - name: Set up Go 24 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 25 | with: 26 | go-version-file: 'go.mod' 27 | - name: Install Cosign 28 | uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 29 | - name: Run GoReleaser 30 | uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0 31 | with: 32 | version: v2.7.0 33 | args: release --release-notes tools/release/release-note.md 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | - uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 37 | with: 38 | subject-path: 'dist/checksums.txt' 39 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tools/magic-modules"] 2 | path = tools/magic-modules 3 | url = https://github.com/terraform-linters/magic-modules.git 4 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example goreleaser.yaml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | version: 2 4 | env: 5 | - CGO_ENABLED=0 6 | builds: 7 | - targets: 8 | - darwin_amd64 9 | - darwin_arm64 10 | - linux_386 11 | - linux_amd64 12 | - linux_arm 13 | - linux_arm64 14 | - windows_386 15 | - windows_amd64 16 | hooks: 17 | post: 18 | - mkdir -p ./dist/raw 19 | - cp "{{ .Path }}" "./dist/raw/{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" 20 | archives: 21 | - id: zip 22 | name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}" 23 | formats: 24 | - 'zip' 25 | files: 26 | - none* 27 | checksum: 28 | name_template: 'checksums.txt' 29 | extra_files: 30 | - glob: ./dist/raw/* 31 | signs: 32 | - cmd: cosign 33 | signature: '${artifact}.keyless.sig' 34 | certificate: '${artifact}.pem' 35 | output: true 36 | artifacts: checksum 37 | args: 38 | - sign-blob 39 | - '--output-certificate=${certificate}' 40 | - '--output-signature=${signature}' 41 | - '${artifact}' 42 | - --yes 43 | release: 44 | github: 45 | owner: terraform-linters 46 | name: tflint-ruleset-google 47 | draft: true 48 | snapshot: 49 | version_template: "{{ .Tag }}-dev" 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: build 2 | 3 | test: 4 | go test $$(go list ./... | grep -v integration) 5 | 6 | e2e: 7 | cd integration && go test && cd ../ 8 | 9 | build: 10 | go build 11 | 12 | install: build 13 | mkdir -p ~/.tflint.d/plugins 14 | mv ./tflint-ruleset-google ~/.tflint.d/plugins 15 | 16 | release: 17 | cd tools/release; go run main.go 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TFLint Ruleset for terraform-provider-google 2 | [![Build Status](https://github.com/terraform-linters/tflint-ruleset-google/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/terraform-linters/tflint-ruleset-google/actions) 3 | [![GitHub release](https://img.shields.io/github/release/terraform-linters/tflint-ruleset-google.svg)](https://github.com/terraform-linters/tflint-ruleset-google/releases/latest) 4 | [![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-blue.svg)](LICENSE) 5 | 6 | TFLint ruleset plugin for Terraform Google Cloud Platform provider 7 | 8 | ## Requirements 9 | 10 | - TFLint v0.42+ 11 | - Go v1.24 12 | 13 | ## Installation 14 | 15 | You can install the plugin by adding a config to `.tflint.hcl` and running `tflint --init`: 16 | 17 | ```hcl 18 | plugin "google" { 19 | enabled = true 20 | version = "0.32.0" 21 | source = "github.com/terraform-linters/tflint-ruleset-google" 22 | } 23 | ``` 24 | 25 | For more configuration about the plugin, see [Plugin Configuration](docs/configuration.md). 26 | 27 | ## Rules 28 | 29 | 100+ rules are available. See the [documentation](docs/rules/README.md). 30 | 31 | ## Building the plugin 32 | 33 | Clone the repository locally and run the following command: 34 | 35 | ``` 36 | $ make 37 | ``` 38 | 39 | You can easily install the built plugin with the following: 40 | 41 | ``` 42 | $ make install 43 | ``` 44 | 45 | Note that if you install the plugin with `make install`, you must omit the `version` and `source` attributes in `.tflint.hcl`: 46 | 47 | ```hcl 48 | plugin "google" { 49 | enabled = true 50 | } 51 | ``` 52 | 53 | ## Add a new rule 54 | 55 | If you are interested in adding a new rule to this ruleset, you can use the generator. Run the following command: 56 | 57 | ``` 58 | $ go run ./rules/generator 59 | ``` 60 | 61 | Follow the instructions to edit the generated files and open a new pull request. 62 | -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | This plugin can take advantage of additional features by configure the `plugin` block. Currently, this configuration is only available for [Deep Checking](deep_checking.md). 4 | 5 | Here's an example: 6 | 7 | ```hcl 8 | plugin "google" { 9 | // Plugin common attributes 10 | 11 | deep_check = false 12 | } 13 | ``` 14 | 15 | ## `deep_check` 16 | 17 | Default: false 18 | 19 | Enable [Deep Checking](deep_checking.md). 20 | -------------------------------------------------------------------------------- /docs/deep_checking.md: -------------------------------------------------------------------------------- 1 | # Deep Checking 2 | 3 | Deep Checking uses your provider's credentials to perform a more strict inspection. 4 | 5 | For example, you can confirm that the API you are trying to use in the project is enabled. See also the [google_disabled_api](rules/google_disabled_api.md) rule. 6 | 7 | ```console 8 | $ tflint 9 | 1 issue(s) found: 10 | 11 | Error: Compute Engine API has not been used in foo-bar-baz before or it is disabled. (google_disabled_api) 12 | 13 | on template.tf line 25: 14 | 25: resource "google_compute_network" "vpc_network" { 15 | 16 | ``` 17 | 18 | You can enable Deep Checking by changing the plugin configuration. 19 | 20 | ```hcl 21 | plugin "google" { 22 | enabled = true 23 | 24 | deep_check = true 25 | } 26 | ``` 27 | 28 | ## Credentials 29 | 30 | Currently, credentials, regions, etc. declared inside the "google" provider block are not considered except for the `project` attribute. You need to pass the credentials to TFLint using environment variables and so on. 31 | -------------------------------------------------------------------------------- /docs/rules/README.md: -------------------------------------------------------------------------------- 1 | # Rules 2 | 3 | This documentation describes a list of rules available by enabling this ruleset. 4 | 5 | ## Basic Rules 6 | 7 | ### Invalid machine types 8 | 9 | These rules warn you if a machine type not listed at https://cloud.google.com/compute/docs/machine-types is being used. Please note that custom machine types cannot be detected correctly. These rules consider all machine types starting with `[e2|n2|n2d|n1]-custom-` to be valid. 10 | 11 | |Name|Severity|Enabled| 12 | | --- | --- | --- | 13 | |google_composer_environment_invalid_machine_type|ERROR|✔| 14 | |google_compute_instance_invalid_machine_type|ERROR|✔| 15 | |google_compute_instance_template_invalid_machine_type|ERROR|✔| 16 | |google_compute_reservation_invalid_machine_type|ERROR|✔| 17 | |google_container_cluster_invalid_machine_type|ERROR|✔| 18 | |google_container_node_pool_invalid_machine_type|ERROR|✔| 19 | |google_dataflow_job_invalid_machine_type|ERROR|✔| 20 | 21 | ### Invalid member 22 | 23 | This rule warn you if a member value in IAM related resources is invalid. 24 | 25 | |Name|Severity|Enabled| 26 | | --- | --- | --- | 27 | |google_project_iam_audit_config_invalid_member|ERROR|✔| 28 | |google_project_iam_binding_invalid_member|ERROR|✔| 29 | |google_project_iam_member_invalid_member|ERROR|✔| 30 | |google_project_iam_policy_invalid_member|ERROR|✔| 31 | 32 | ## Magic Modules Rules 33 | 34 | These are the rules that warn against invalid values generated from [Magic Modules](https://github.com/terraform-linters/magic-modules). These rules are defined under the [`rules/magicmodules`](../../rules/magicmodules) directory. 35 | 36 | See the [`tools`](../../tools) directory for how to generate these rules. 37 | 38 | ## Deep Checking Rules 39 | 40 | By enabling [Deep Checking](../deep_checking.md), you can enable rules that invoke API to perform more strict checking. 41 | 42 | |Name|Severity|Enabled| 43 | | --- | --- | --- | 44 | |google_disabled_api|ERROR|✔| 45 | -------------------------------------------------------------------------------- /docs/rules/google_disabled_api.md: -------------------------------------------------------------------------------- 1 | # google_disabled_api 2 | 3 | Disallow to declare resources with disabled API. 4 | 5 | ## Example 6 | 7 | ```hcl 8 | resource "google_compute_network" "vpc_network" { 9 | name = "terraform-network" 10 | auto_create_subnetworks = "true" 11 | } 12 | ``` 13 | 14 | ``` 15 | $ tflint 16 | 1 issue(s) found: 17 | 18 | Error: Compute Engine API has not been used in foo-bar-baz before or it is disabled. (google_disabled_api) 19 | 20 | on template.tf line 1: 21 | 1: resource "google_compute_network" "vpc_network" { 22 | 23 | ``` 24 | 25 | [Service Usage API](https://cloud.google.com/service-usage/docs/reference/rest) must be enabled in order to use this rule. 26 | 27 | ## Why 28 | 29 | `terraform apply` will fail when the resources refer to disabled APIs. 30 | 31 | ``` 32 | $ terraform apply 33 | 34 | ... 35 | 36 | Error: Error creating Network: googleapi: Error 403: Compute Engine API has not been used in project 1234567890 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/compute.googleapis.com/overview?project=1234567890 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry., accessNotConfigured 37 | ``` 38 | 39 | Even more unfortunately, not all errors are returned. For example, if you have resources that depend on multiple disabled APIs, you will not see an error for the other APIs. This rule allows you to detect all disabled API errors in advance. 40 | 41 | ## How to Fix 42 | 43 | Enable the API from the Cloud Console in your project or remove the resource. 44 | 45 | https://cloud.google.com/endpoints/docs/openapi/enable-api 46 | 47 | -------------------------------------------------------------------------------- /docs/rules/google_project_iam_audit_config_invalid_member.md: -------------------------------------------------------------------------------- 1 | # google_project_iam_audit_config_invalid_member 2 | 3 | This is a [google_project_iam_invalid_member rule](../google_project_iam_invalid_member.md) against `google_project_iam_audit_config` resource. 4 | -------------------------------------------------------------------------------- /docs/rules/google_project_iam_binding_invalid_member.md: -------------------------------------------------------------------------------- 1 | # google_project_iam_binding_invalid_member 2 | 3 | This is a [google_project_iam_invalid_member rule](../google_project_iam_invalid_member.md) against `google_project_iam_binding` resource. 4 | -------------------------------------------------------------------------------- /docs/rules/google_project_iam_invalid_member.md: -------------------------------------------------------------------------------- 1 | # google_project_iam_invalid_member 2 | 3 | Check IAM member format against IAM policy for projects: 4 | 5 | - `google_project_iam_policy` 6 | - `google_project_iam_binding` 7 | - `google_project_iam_member` 8 | - `google_project_iam_audit_config` 9 | 10 | ## Example 11 | 12 | Here is an example of `google_project_iam_member`. 13 | 14 | ```hcl 15 | resource "google_project_iam_member" "iam_member" { 16 | member = "jane@example.com" 17 | } 18 | ``` 19 | 20 | ``` 21 | $ tflint 22 | 1 issue(s) found: 23 | 24 | Error: jane@example.com is an invalid member format. (google_project_iam_member) 25 | 26 | on template.tf line 1: 27 | 1: resource "google_project_iam_member" "iam_member" { 28 | 29 | ``` 30 | 31 | ## Why 32 | 33 | A member value you wrote is invalid. `terraform apply` will result in failure. 34 | In particular, don't forget to add a prefix to the value. Since the principal type is identified with a prefix, a value without a prefix cannot be interpreted correctly. There are two exceptions; `allUsers` and `allAuthenticatedUsers` are valid without a prefix. In conclusion, the valid member values are: 35 | 36 | - `allUsers` 37 | - `allAuthenticatedUsers` 38 | - `user:{emailid}` 39 | - `serviceAccount:{emailid}` 40 | - `group:{emailid}` 41 | - `domain:{domain}` 42 | 43 | See these documents in detail: 44 | 45 | - https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam#member/members 46 | - https://cloud.google.com/iam/docs/overview#concepts_related_identity 47 | - https://cloud.google.com/iam/docs/overview#cloud-iam-policy 48 | 49 | ## How To Fix 50 | 51 | See the document. Probably you just need to add some prefixes. The example can be fixed as below: 52 | 53 | ```hcl 54 | resource "google_project_iam_member" "iam_member" { 55 | member = "user:jane@example.com" 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /docs/rules/google_project_iam_member_invalid_member.md: -------------------------------------------------------------------------------- 1 | # google_project_iam_member_invalid_member 2 | 3 | This is a [google_project_iam_invalid_member rule](../google_project_iam_invalid_member.md) against `google_project_iam_member` resource. 4 | -------------------------------------------------------------------------------- /docs/rules/google_project_iam_policy_invalid_member.md: -------------------------------------------------------------------------------- 1 | # google_project_iam_policy_invalid_member 2 | 3 | This is a [google_project_iam_invalid_member rule](../google_project_iam_invalid_member.md) against `google_project_iam_policy` resource. 4 | -------------------------------------------------------------------------------- /docs/rules/rule.md.tmpl: -------------------------------------------------------------------------------- 1 | # {{ .RuleName }} 2 | 3 | // TODO: Write the rule's description here 4 | 5 | ## Example 6 | 7 | ```hcl 8 | resource "null_resource" "foo" { 9 | // TODO: Write the example Terraform code which violates the rule 10 | } 11 | ``` 12 | 13 | ``` 14 | $ tflint 15 | 16 | // TODO: Write the output when inspects the above code 17 | 18 | ``` 19 | 20 | ## Why 21 | 22 | // TODO: Write why you should follow the rule. This section is also a place to explain the value of the rule 23 | 24 | ## How To Fix 25 | 26 | // TODO: Write how to fix it to avoid the problem 27 | -------------------------------------------------------------------------------- /google/client.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/api/serviceusage/v1" 7 | ) 8 | 9 | // Client is a wrapper of the Google API client 10 | type Client struct { 11 | ServiceUsage *serviceusage.Service 12 | } 13 | 14 | // NewClient returns a new Client 15 | func NewClient() (*Client, error) { 16 | serviceusageClient, err := serviceusage.NewService(context.TODO()) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | return &Client{ 22 | ServiceUsage: serviceusageClient, 23 | }, nil 24 | } 25 | -------------------------------------------------------------------------------- /google/config.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | // Config is the configuration for the ruleset. 4 | type Config struct { 5 | DeepCheck bool `hclext:"deep_check,optional"` 6 | } 7 | -------------------------------------------------------------------------------- /google/provider.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleProviderBlockSchema is a schema of `google` provider block 11 | var GoogleProviderBlockSchema = &hclext.BodySchema{ 12 | Attributes: []hclext.AttributeSchema{ 13 | {Name: "project"}, 14 | }, 15 | } 16 | 17 | // GetProject retrieves project_id from the "provider" block in the Terraform configuration and environment variables 18 | func GetProject(runner tflint.Runner) (string, error) { 19 | providers, err := runner.GetModuleContent( 20 | &hclext.BodySchema{ 21 | Blocks: []hclext.BlockSchema{ 22 | { 23 | Type: "provider", 24 | LabelNames: []string{"name"}, 25 | Body: GoogleProviderBlockSchema, 26 | }, 27 | }, 28 | }, 29 | &tflint.GetModuleContentOption{ModuleCtx: tflint.RootModuleCtxType}, 30 | ) 31 | if err != nil { 32 | return "", err 33 | } 34 | 35 | for _, provider := range providers.Blocks { 36 | if provider.Labels[0] != "google" { 37 | continue 38 | } 39 | 40 | opts := &tflint.EvaluateExprOption{ModuleCtx: tflint.RootModuleCtxType} 41 | 42 | if attr, exists := provider.Body.Attributes["project"]; exists { 43 | var project string 44 | err := runner.EvaluateExpr(attr.Expr, func(val string) error { 45 | project = val 46 | return nil 47 | }, opts) 48 | 49 | return project, err 50 | } 51 | } 52 | 53 | return getProjectFromEnv(), nil 54 | } 55 | 56 | func getProjectFromEnv() string { 57 | envs := []string{"GOOGLE_PROJECT", "GOOGLE_CLOUD_PROJECT", "GCLOUD_PROJECT", "CLOUDSDK_CORE_PROJECT"} 58 | for _, env := range envs { 59 | if project := os.Getenv(env); project != "" { 60 | return project 61 | } 62 | } 63 | return "" 64 | } 65 | -------------------------------------------------------------------------------- /google/ruleset.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 5 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 6 | ) 7 | 8 | // RuleSet is the custom ruleset for the Google provider plugin. 9 | type RuleSet struct { 10 | tflint.BuiltinRuleSet 11 | config *Config 12 | } 13 | 14 | func (r *RuleSet) ConfigSchema() *hclext.BodySchema { 15 | r.config = &Config{} 16 | return hclext.ImpliedBodySchema(r.config) 17 | } 18 | 19 | // ApplyConfig reflects the plugin configuration to the ruleset. 20 | func (r *RuleSet) ApplyConfig(body *hclext.BodyContent) error { 21 | diags := hclext.DecodeBody(body, nil, r.config) 22 | if diags.HasErrors() { 23 | return diags 24 | } 25 | 26 | if r.config.DeepCheck { 27 | return nil 28 | } 29 | 30 | // Disable deep checking rules 31 | enabledRules := []tflint.Rule{} 32 | for _, rule := range r.EnabledRules { 33 | meta := rule.Metadata() 34 | // Deep checking rules must have metadata like `map[string]bool{"deep": true}`` 35 | if meta == nil { 36 | enabledRules = append(enabledRules, rule) 37 | } 38 | } 39 | r.EnabledRules = enabledRules 40 | 41 | return nil 42 | } 43 | 44 | // NewRunner injects a custom Google runner 45 | func (r *RuleSet) NewRunner(runner tflint.Runner) (tflint.Runner, error) { 46 | return NewRunner(runner, r.config) 47 | } 48 | -------------------------------------------------------------------------------- /google/runner.go: -------------------------------------------------------------------------------- 1 | package google 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 7 | ) 8 | 9 | // Runner is a wrapper of RPC client for inserting custom actions for Google provider. 10 | type Runner struct { 11 | tflint.Runner 12 | Client *Client 13 | Project string 14 | } 15 | 16 | // NewRunner returns a custom Google runner. 17 | func NewRunner(runner tflint.Runner, config *Config) (*Runner, error) { 18 | var client *Client 19 | var project string 20 | var err error 21 | if config.DeepCheck { 22 | client, err = NewClient() 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | project, err = GetProject(runner) 28 | if err != nil { 29 | return nil, err 30 | } 31 | } 32 | 33 | return &Runner{ 34 | Runner: runner, 35 | Client: client, 36 | Project: project, 37 | }, nil 38 | } 39 | 40 | // ParentProject returns a part of the API path about the parent project 41 | func (r *Runner) ParentProject() string { 42 | return fmt.Sprintf("projects/%s", r.Project) 43 | } 44 | -------------------------------------------------------------------------------- /integration/basic/.tflint.hcl: -------------------------------------------------------------------------------- 1 | plugin "terraform" { 2 | enabled = false 3 | } 4 | 5 | plugin "google" { 6 | enabled = true 7 | } 8 | -------------------------------------------------------------------------------- /integration/basic/main.tf: -------------------------------------------------------------------------------- 1 | resource "google_app_engine_domain_mapping" "domain_mapping" { 2 | domain_name = "verified-domain.com" 3 | override_strategy = "DEFAULT" 4 | 5 | ssl_settings { 6 | ssl_management_type = "AUTOMATIC" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /integration/basic/result.json: -------------------------------------------------------------------------------- 1 | { 2 | "issues":[ 3 | { 4 | "rule":{ 5 | "name":"google_app_engine_domain_mapping_invalid_override_strategy", 6 | "severity":"error", 7 | "link":"" 8 | }, 9 | "message":"expected override_strategy to be one of [\"STRICT\" \"OVERRIDE\" \"\"], got DEFAULT", 10 | "range":{ 11 | "filename":"main.tf", 12 | "start":{ 13 | "line":3, 14 | "column":23 15 | }, 16 | "end":{ 17 | "line":3, 18 | "column":32 19 | } 20 | }, 21 | "callers":[ 22 | 23 | ] 24 | } 25 | ], 26 | "errors":[] 27 | } 28 | -------------------------------------------------------------------------------- /integration/integration_test.go: -------------------------------------------------------------------------------- 1 | package integration 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | "os" 8 | "os/exec" 9 | "testing" 10 | 11 | "github.com/google/go-cmp/cmp" 12 | ) 13 | 14 | func TestIntegration(t *testing.T) { 15 | cases := []struct { 16 | Name string 17 | Command *exec.Cmd 18 | Dir string 19 | }{ 20 | { 21 | Name: "basic", 22 | Command: exec.Command("tflint", "--format", "json", "--force"), 23 | Dir: "basic", 24 | }, 25 | } 26 | 27 | dir, _ := os.Getwd() 28 | defer os.Chdir(dir) 29 | 30 | for _, tc := range cases { 31 | testDir := dir + "/" + tc.Dir 32 | os.Chdir(testDir) 33 | 34 | var stdout, stderr bytes.Buffer 35 | tc.Command.Stdout = &stdout 36 | tc.Command.Stderr = &stderr 37 | if err := tc.Command.Run(); err != nil { 38 | t.Fatalf("Failed `%s`: %s, stdout=%s stderr=%s", tc.Name, err, stdout.String(), stderr.String()) 39 | } 40 | 41 | ret, err := ioutil.ReadFile("result.json") 42 | if err != nil { 43 | t.Fatalf("Failed `%s`: %s", tc.Name, err) 44 | } 45 | 46 | var expected interface{} 47 | if err := json.Unmarshal(ret, &expected); err != nil { 48 | t.Fatalf("Failed `%s`: %s", tc.Name, err) 49 | } 50 | 51 | var got interface{} 52 | if err := json.Unmarshal(stdout.Bytes(), &got); err != nil { 53 | t.Fatalf("Failed `%s`: %s", tc.Name, err) 54 | } 55 | 56 | if !cmp.Equal(got, expected) { 57 | t.Fatalf("Failed `%s`: diff=%s", tc.Name, cmp.Diff(expected, got)) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/terraform-linters/tflint-plugin-sdk/plugin" 5 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 6 | "github.com/terraform-linters/tflint-ruleset-google/google" 7 | "github.com/terraform-linters/tflint-ruleset-google/project" 8 | "github.com/terraform-linters/tflint-ruleset-google/rules" 9 | ) 10 | 11 | func main() { 12 | plugin.Serve(&plugin.ServeOpts{ 13 | RuleSet: &google.RuleSet{ 14 | BuiltinRuleSet: tflint.BuiltinRuleSet{ 15 | Name: "google", 16 | Version: project.Version, 17 | Rules: rules.Rules, 18 | }, 19 | }, 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /project/main.go: -------------------------------------------------------------------------------- 1 | package project 2 | 3 | import "fmt" 4 | 5 | // Version is ruleset version 6 | const Version string = "0.32.0" 7 | 8 | // ReferenceLink returns the rule reference link 9 | func ReferenceLink(name string) string { 10 | return fmt.Sprintf("https://github.com/terraform-linters/tflint-ruleset-google/blob/v%s/docs/rules/%s.md", Version, name) 11 | } 12 | -------------------------------------------------------------------------------- /rules/api/google_disabled_api_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | "google.golang.org/api/serviceusage/v1" 9 | ) 10 | 11 | func Test_Check(t *testing.T) { 12 | cases := []struct { 13 | Name string 14 | Content string 15 | Response map[string]*serviceusage.GoogleApiServiceusageV1Service 16 | Expected helper.Issues 17 | }{ 18 | { 19 | Name: "No resources", 20 | Content: ` 21 | terraform {}`, 22 | Response: map[string]*serviceusage.GoogleApiServiceusageV1Service{}, 23 | Expected: helper.Issues{}, 24 | }, 25 | { 26 | Name: "compute.googleapis.com is not enabled", 27 | Content: ` 28 | resource "google_compute_network" "vpc_network" { 29 | name = "terraform-network" 30 | auto_create_subnetworks = "true" 31 | }`, 32 | Response: map[string]*serviceusage.GoogleApiServiceusageV1Service{}, 33 | Expected: helper.Issues{ 34 | { 35 | Rule: NewGoogleDisabledAPIRule(), 36 | Message: "compute.googleapis.com has not been used in foo-bar-baz before or it is disabled.", 37 | Range: hcl.Range{ 38 | Filename: "resource.tf", 39 | Start: hcl.Pos{Line: 2, Column: 1}, 40 | End: hcl.Pos{Line: 2, Column: 48}, 41 | }, 42 | }, 43 | }, 44 | }, 45 | { 46 | Name: "compute.googleapis.com is enabled", 47 | Content: ` 48 | resource "google_compute_network" "vpc_network" { 49 | name = "terraform-network" 50 | auto_create_subnetworks = "true" 51 | }`, 52 | Response: map[string]*serviceusage.GoogleApiServiceusageV1Service{ 53 | "compute.googleapis.com": { 54 | Config: &serviceusage.GoogleApiServiceusageV1ServiceConfig{ 55 | Title: "Compute Engine API", 56 | Name: "compute.googleapis.com", 57 | }, 58 | Name: "projects/123456789/services/compute.googleapis.com", 59 | Parent: "projects/123456789", 60 | State: "ENABLED", 61 | }, 62 | }, 63 | Expected: helper.Issues{}, 64 | }, 65 | } 66 | 67 | rule := NewGoogleDisabledAPIRule() 68 | 69 | for _, tc := range cases { 70 | t.Run(tc.Name, func(t *testing.T) { 71 | runner := NewTestRunner(t, map[string]string{"resource.tf": tc.Content}) 72 | 73 | rule.prepared = true 74 | rule.enabledAPIs = tc.Response 75 | 76 | if err := rule.Check(runner); err != nil { 77 | t.Fatalf("Unexpected error occurred: %s", err) 78 | } 79 | helper.AssertIssues(t, tc.Expected, runner.Runner.(*helper.Runner).Issues) 80 | }) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /rules/api/helper_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 7 | "github.com/terraform-linters/tflint-ruleset-google/google" 8 | ) 9 | 10 | func NewTestRunner(t *testing.T, files map[string]string) *google.Runner { 11 | return &google.Runner{ 12 | Runner: helper.TestRunner(t, files), 13 | Client: &google.Client{}, 14 | Project: "foo-bar-baz", 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /rules/api/provider.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "github.com/terraform-linters/tflint-plugin-sdk/tflint" 4 | 5 | // Rules is a list of rules with invoking APIs 6 | var Rules = []tflint.Rule{ 7 | NewGoogleDisabledAPIRule(), 8 | } 9 | -------------------------------------------------------------------------------- /rules/google_composer_environment_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleComposerEnvironmentInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleComposerEnvironmentInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleComposerEnvironmentInvalidMachineTypeRule returns a new rule 16 | func NewGoogleComposerEnvironmentInvalidMachineTypeRule() *GoogleComposerEnvironmentInvalidMachineTypeRule { 17 | return &GoogleComposerEnvironmentInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleComposerEnvironmentInvalidMachineTypeRule) Name() string { 22 | return "google_composer_environment_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleComposerEnvironmentInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleComposerEnvironmentInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleComposerEnvironmentInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleComposerEnvironmentInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_composer_environment", &hclext.BodySchema{ 43 | Blocks: []hclext.BlockSchema{ 44 | { 45 | Type: "config", 46 | Body: &hclext.BodySchema{ 47 | Blocks: []hclext.BlockSchema{ 48 | { 49 | Type: "node_config", 50 | Body: &hclext.BodySchema{ 51 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 52 | }, 53 | }, 54 | }, 55 | }, 56 | }, 57 | }, 58 | }, nil) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | for _, resource := range resources.Blocks { 64 | for _, config := range resource.Body.Blocks { 65 | for _, nodeConfig := range config.Body.Blocks { 66 | attribute, exists := nodeConfig.Body.Attributes["machine_type"] 67 | if !exists { 68 | continue 69 | } 70 | 71 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 72 | if validMachineTypes[machineType] || isCustomType(machineType) { 73 | return nil 74 | } 75 | 76 | return runner.EmitIssue( 77 | r, 78 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 79 | attribute.Expr.Range(), 80 | ) 81 | }, nil) 82 | if err != nil { 83 | return err 84 | } 85 | } 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/google_compute_instance_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleComputeInstanceInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleComputeInstanceInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleComputeInstanceInvalidMachineTypeRule returns a new rule 16 | func NewGoogleComputeInstanceInvalidMachineTypeRule() *GoogleComputeInstanceInvalidMachineTypeRule { 17 | return &GoogleComputeInstanceInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleComputeInstanceInvalidMachineTypeRule) Name() string { 22 | return "google_compute_instance_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleComputeInstanceInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleComputeInstanceInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleComputeInstanceInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleComputeInstanceInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_compute_instance", &hclext.BodySchema{ 43 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 44 | }, nil) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | for _, resource := range resources.Blocks { 50 | attribute, exists := resource.Body.Attributes["machine_type"] 51 | if !exists { 52 | continue 53 | } 54 | 55 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 56 | if validMachineTypes[machineType] || isCustomType(machineType) { 57 | return nil 58 | } 59 | 60 | return runner.EmitIssue( 61 | r, 62 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 63 | attribute.Expr.Range(), 64 | ) 65 | }, nil) 66 | if err != nil { 67 | return err 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /rules/google_compute_instance_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleComputeInstanceInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_compute_instance" "vm_instance" { 20 | machine_type = "n2-standard-1" 21 | }`, 22 | Expected: helper.Issues{ 23 | { 24 | Rule: NewGoogleComputeInstanceInvalidMachineTypeRule(), 25 | Message: `"n2-standard-1" is an invalid as machine type`, 26 | Range: hcl.Range{ 27 | Filename: "resource.tf", 28 | Start: hcl.Pos{Line: 3, Column: 20}, 29 | End: hcl.Pos{Line: 3, Column: 35}, 30 | }, 31 | }, 32 | }, 33 | }, 34 | { 35 | Name: "valid type", 36 | Content: ` 37 | resource "google_compute_instance" "vm_instance" { 38 | machine_type = "n2-standard-2" 39 | }`, 40 | Expected: helper.Issues{}, 41 | }, 42 | { 43 | Name: "custom type", 44 | Content: ` 45 | resource "google_compute_instance" "vm_instance" { 46 | machine_type = "n2-custom-6-20480" 47 | }`, 48 | Expected: helper.Issues{}, 49 | }, 50 | } 51 | 52 | rule := NewGoogleComputeInstanceInvalidMachineTypeRule() 53 | 54 | for _, tc := range cases { 55 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 56 | 57 | if err := rule.Check(runner); err != nil { 58 | t.Fatalf("Unexpected error occurred: %s", err) 59 | } 60 | 61 | helper.AssertIssues(t, tc.Expected, runner.Issues) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rules/google_compute_instance_template_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleComputeInstanceTemplateInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleComputeInstanceTemplateInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleComputeInstanceTemplateInvalidMachineTypeRule returns a new rule 16 | func NewGoogleComputeInstanceTemplateInvalidMachineTypeRule() *GoogleComputeInstanceTemplateInvalidMachineTypeRule { 17 | return &GoogleComputeInstanceTemplateInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleComputeInstanceTemplateInvalidMachineTypeRule) Name() string { 22 | return "google_compute_instance_template_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleComputeInstanceTemplateInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleComputeInstanceTemplateInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleComputeInstanceTemplateInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleComputeInstanceTemplateInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_compute_instance_template", &hclext.BodySchema{ 43 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 44 | }, nil) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | for _, resource := range resources.Blocks { 50 | attribute, exists := resource.Body.Attributes["machine_type"] 51 | if !exists { 52 | continue 53 | } 54 | 55 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 56 | if validMachineTypes[machineType] || isCustomType(machineType) { 57 | return nil 58 | } 59 | 60 | return runner.EmitIssue( 61 | r, 62 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 63 | attribute.Expr.Range(), 64 | ) 65 | }, nil) 66 | if err != nil { 67 | return err 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /rules/google_compute_instance_template_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleComputeInstanceTemplateInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_compute_instance_template" "vm_instance" { 20 | machine_type = "n2-standard-1" 21 | }`, 22 | Expected: helper.Issues{ 23 | { 24 | Rule: NewGoogleComputeInstanceTemplateInvalidMachineTypeRule(), 25 | Message: `"n2-standard-1" is an invalid as machine type`, 26 | Range: hcl.Range{ 27 | Filename: "resource.tf", 28 | Start: hcl.Pos{Line: 3, Column: 20}, 29 | End: hcl.Pos{Line: 3, Column: 35}, 30 | }, 31 | }, 32 | }, 33 | }, 34 | { 35 | Name: "valid type", 36 | Content: ` 37 | resource "google_compute_instance_template" "vm_instance" { 38 | machine_type = "n2-standard-2" 39 | }`, 40 | Expected: helper.Issues{}, 41 | }, 42 | { 43 | Name: "custom type", 44 | Content: ` 45 | resource "google_compute_instance_template" "vm_instance" { 46 | machine_type = "n2-custom-6-20480" 47 | }`, 48 | Expected: helper.Issues{}, 49 | }, 50 | } 51 | 52 | rule := NewGoogleComputeInstanceTemplateInvalidMachineTypeRule() 53 | 54 | for _, tc := range cases { 55 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 56 | 57 | if err := rule.Check(runner); err != nil { 58 | t.Fatalf("Unexpected error occurred: %s", err) 59 | } 60 | 61 | helper.AssertIssues(t, tc.Expected, runner.Issues) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rules/google_compute_reservation_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleComputeReservationInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleComputeReservationInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleComputeReservationInvalidMachineTypeRule returns a new rule 16 | func NewGoogleComputeReservationInvalidMachineTypeRule() *GoogleComputeReservationInvalidMachineTypeRule { 17 | return &GoogleComputeReservationInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleComputeReservationInvalidMachineTypeRule) Name() string { 22 | return "google_compute_reservation_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleComputeReservationInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleComputeReservationInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleComputeReservationInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleComputeReservationInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_compute_reservation", &hclext.BodySchema{ 43 | Blocks: []hclext.BlockSchema{ 44 | { 45 | Type: "specific_reservation", 46 | Body: &hclext.BodySchema{ 47 | Blocks: []hclext.BlockSchema{ 48 | { 49 | Type: "instance_properties", 50 | Body: &hclext.BodySchema{ 51 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 52 | }, 53 | }, 54 | }, 55 | }, 56 | }, 57 | }, 58 | }, nil) 59 | if err != nil { 60 | return err 61 | } 62 | 63 | for _, resource := range resources.Blocks { 64 | for _, reservations := range resource.Body.Blocks { 65 | for _, properties := range reservations.Body.Blocks { 66 | attribute, exists := properties.Body.Attributes["machine_type"] 67 | if !exists { 68 | continue 69 | } 70 | 71 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 72 | if validMachineTypes[machineType] || isCustomType(machineType) { 73 | return nil 74 | } 75 | 76 | return runner.EmitIssue( 77 | r, 78 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 79 | attribute.Expr.Range(), 80 | ) 81 | }, nil) 82 | if err != nil { 83 | return err 84 | } 85 | } 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/google_compute_reservation_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleComputeReservationInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_compute_reservation" "gce_reservation" { 20 | name = "gce-reservation" 21 | zone = "us-central1-a" 22 | 23 | specific_reservation { 24 | count = 1 25 | instance_properties { 26 | min_cpu_platform = "Intel Cascade Lake" 27 | machine_type = "n2_standard_2" 28 | } 29 | } 30 | }`, 31 | Expected: helper.Issues{ 32 | { 33 | Rule: NewGoogleComputeReservationInvalidMachineTypeRule(), 34 | Message: `"n2_standard_2" is an invalid as machine type`, 35 | Range: hcl.Range{ 36 | Filename: "resource.tf", 37 | Start: hcl.Pos{Line: 10, Column: 26}, 38 | End: hcl.Pos{Line: 10, Column: 41}, 39 | }, 40 | }, 41 | }, 42 | }, 43 | { 44 | Name: "valid type", 45 | Content: ` 46 | resource "google_compute_reservation" "gce_reservation" { 47 | name = "gce-reservation" 48 | zone = "us-central1-a" 49 | 50 | specific_reservation { 51 | count = 1 52 | instance_properties { 53 | min_cpu_platform = "Intel Cascade Lake" 54 | machine_type = "n2-standard-2" 55 | } 56 | } 57 | }`, 58 | Expected: helper.Issues{}, 59 | }, 60 | { 61 | Name: "custom type", 62 | Content: ` 63 | resource "google_compute_reservation" "gce_reservation" { 64 | name = "gce-reservation" 65 | zone = "us-central1-a" 66 | 67 | specific_reservation { 68 | count = 1 69 | instance_properties { 70 | min_cpu_platform = "Intel Cascade Lake" 71 | machine_type = "n2-custom-6-20480" 72 | } 73 | } 74 | }`, 75 | Expected: helper.Issues{}, 76 | }, 77 | } 78 | 79 | rule := NewGoogleComputeReservationInvalidMachineTypeRule() 80 | 81 | for _, tc := range cases { 82 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 83 | 84 | if err := rule.Check(runner); err != nil { 85 | t.Fatalf("Unexpected error occurred: %s", err) 86 | } 87 | 88 | helper.AssertIssues(t, tc.Expected, runner.Issues) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /rules/google_compute_resource_policy_invalid_name.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 5 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 6 | ) 7 | 8 | // GoogleComputeResourcePolicyInvalidNameRule checks whether the name is invalid 9 | type GoogleComputeResourcePolicyInvalidNameRule struct { 10 | tflint.DefaultRule 11 | 12 | resourceType string 13 | attributeName string 14 | } 15 | 16 | // NewGoogleComputeResourcePolicyInvalidNameRule returns new rule with default attributes 17 | func NewGoogleComputeResourcePolicyInvalidNameRule() *GoogleComputeResourcePolicyInvalidNameRule { 18 | return &GoogleComputeResourcePolicyInvalidNameRule{ 19 | resourceType: "google_compute_resource_policy", 20 | attributeName: "name", 21 | } 22 | } 23 | 24 | // Name returns the rule name 25 | func (r *GoogleComputeResourcePolicyInvalidNameRule) Name() string { 26 | return "google_compute_resource_policy_invalid_name" 27 | } 28 | 29 | // Enabled returns whether the rule is enabled by default 30 | func (r *GoogleComputeResourcePolicyInvalidNameRule) Enabled() bool { 31 | return true 32 | } 33 | 34 | // Severity returns the rule severity 35 | func (r *GoogleComputeResourcePolicyInvalidNameRule) Severity() tflint.Severity { 36 | return tflint.ERROR 37 | } 38 | 39 | // Link returns the rule reference link 40 | func (r *GoogleComputeResourcePolicyInvalidNameRule) Link() string { 41 | return "" 42 | } 43 | 44 | // Check checks whether the name is invalid 45 | func (r *GoogleComputeResourcePolicyInvalidNameRule) Check(runner tflint.Runner) error { 46 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 47 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 48 | }, nil) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | for _, resource := range resources.Blocks { 54 | attribute, exists := resource.Body.Attributes[r.attributeName] 55 | if !exists { 56 | continue 57 | } 58 | 59 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 60 | validateFunc := validateRegexp(`^[a-z]([-a-z0-9]*[a-z0-9])$`) 61 | 62 | _, errors := validateFunc(val, r.attributeName) 63 | for _, err := range errors { 64 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 65 | return err 66 | } 67 | } 68 | return nil 69 | }, nil) 70 | if err != nil { 71 | return err 72 | } 73 | } 74 | 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /rules/google_compute_resource_policy_invalid_name_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleComputeResourcePolicyInvalidName(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "basic", 18 | Content: ` 19 | resource "google_compute_resource_policy" "snapshot_policy" { 20 | name = "snapshot_policy" 21 | } 22 | `, 23 | Expected: helper.Issues{ 24 | { 25 | Rule: NewGoogleComputeResourcePolicyInvalidNameRule(), 26 | Message: `"name" ("snapshot_policy") doesn't match regexp "^[a-z]([-a-z0-9]*[a-z0-9])$"`, 27 | Range: hcl.Range{ 28 | Filename: "resource.tf", 29 | Start: hcl.Pos{Line: 3, Column: 10}, 30 | End: hcl.Pos{Line: 3, Column: 27}, 31 | }, 32 | }, 33 | }, 34 | }, 35 | } 36 | 37 | rule := NewGoogleComputeResourcePolicyInvalidNameRule() 38 | 39 | for _, tc := range cases { 40 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 41 | 42 | if err := rule.Check(runner); err != nil { 43 | t.Fatalf("Unexpected error occurred: %s", err) 44 | } 45 | 46 | helper.AssertIssues(t, tc.Expected, runner.Issues) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rules/google_container_cluster_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleContainerClusterInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleContainerClusterInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleContainerClusterInvalidMachineTypeRule returns a new rule 16 | func NewGoogleContainerClusterInvalidMachineTypeRule() *GoogleContainerClusterInvalidMachineTypeRule { 17 | return &GoogleContainerClusterInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleContainerClusterInvalidMachineTypeRule) Name() string { 22 | return "google_container_cluster_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleContainerClusterInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleContainerClusterInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleContainerClusterInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleContainerClusterInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_container_cluster", &hclext.BodySchema{ 43 | Blocks: []hclext.BlockSchema{ 44 | { 45 | Type: "node_config", 46 | Body: &hclext.BodySchema{ 47 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 48 | }, 49 | }, 50 | }, 51 | }, nil) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | for _, resource := range resources.Blocks { 57 | for _, nodeConfig := range resource.Body.Blocks { 58 | attribute, exists := nodeConfig.Body.Attributes["machine_type"] 59 | if !exists { 60 | continue 61 | } 62 | 63 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 64 | if validMachineTypes[machineType] || isCustomType(machineType) { 65 | return nil 66 | } 67 | 68 | return runner.EmitIssue( 69 | r, 70 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 71 | attribute.Expr.Range(), 72 | ) 73 | }, nil) 74 | if err != nil { 75 | return err 76 | } 77 | } 78 | } 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /rules/google_container_cluster_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleContainerClusterInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_container_cluster" "primary_preemptible_nodes" { 20 | name = "my-node-pool" 21 | location = "us-central1" 22 | initial_node_count = 1 23 | 24 | node_config { 25 | preemptible = true 26 | machine_type = "n2-medium" 27 | 28 | oauth_scopes = [ 29 | "https://www.googleapis.com/auth/logging.write", 30 | "https://www.googleapis.com/auth/monitoring", 31 | ] 32 | } 33 | }`, 34 | Expected: helper.Issues{ 35 | { 36 | Rule: NewGoogleContainerClusterInvalidMachineTypeRule(), 37 | Message: `"n2-medium" is an invalid as machine type`, 38 | Range: hcl.Range{ 39 | Filename: "resource.tf", 40 | Start: hcl.Pos{Line: 9, Column: 20}, 41 | End: hcl.Pos{Line: 9, Column: 31}, 42 | }, 43 | }, 44 | }, 45 | }, 46 | { 47 | Name: "valid type", 48 | Content: ` 49 | resource "google_container_cluster" "primary_preemptible_nodes" { 50 | name = "my-node-pool" 51 | location = "us-central1" 52 | initial_node_count = 1 53 | 54 | node_config { 55 | preemptible = true 56 | machine_type = "e2-medium" 57 | 58 | oauth_scopes = [ 59 | "https://www.googleapis.com/auth/logging.write", 60 | "https://www.googleapis.com/auth/monitoring", 61 | ] 62 | } 63 | }`, 64 | Expected: helper.Issues{}, 65 | }, 66 | { 67 | Name: "custom type", 68 | Content: ` 69 | resource "google_container_cluster" "primary_preemptible_nodes" { 70 | name = "my-node-pool" 71 | location = "us-central1" 72 | initial_node_count = 1 73 | 74 | node_config { 75 | preemptible = true 76 | machine_type = "n2-custom-6-20480" 77 | 78 | oauth_scopes = [ 79 | "https://www.googleapis.com/auth/logging.write", 80 | "https://www.googleapis.com/auth/monitoring", 81 | ] 82 | } 83 | }`, 84 | Expected: helper.Issues{}, 85 | }, 86 | } 87 | 88 | rule := NewGoogleContainerClusterInvalidMachineTypeRule() 89 | 90 | for _, tc := range cases { 91 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 92 | 93 | if err := rule.Check(runner); err != nil { 94 | t.Fatalf("Unexpected error occurred: %s", err) 95 | } 96 | 97 | helper.AssertIssues(t, tc.Expected, runner.Issues) 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /rules/google_container_node_pool_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleContainerNodePoolInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleContainerNodePoolInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleContainerNodePoolInvalidMachineTypeRule returns a new rule 16 | func NewGoogleContainerNodePoolInvalidMachineTypeRule() *GoogleContainerNodePoolInvalidMachineTypeRule { 17 | return &GoogleContainerNodePoolInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleContainerNodePoolInvalidMachineTypeRule) Name() string { 22 | return "google_container_node_pool_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleContainerNodePoolInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleContainerNodePoolInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleContainerNodePoolInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleContainerNodePoolInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_container_node_pool", &hclext.BodySchema{ 43 | Blocks: []hclext.BlockSchema{ 44 | { 45 | Type: "node_config", 46 | Body: &hclext.BodySchema{ 47 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 48 | }, 49 | }, 50 | }, 51 | }, nil) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | for _, resource := range resources.Blocks { 57 | for _, nodeConfig := range resource.Body.Blocks { 58 | attribute, exists := nodeConfig.Body.Attributes["machine_type"] 59 | if !exists { 60 | continue 61 | } 62 | 63 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 64 | if validMachineTypes[machineType] || isCustomType(machineType) { 65 | return nil 66 | } 67 | 68 | return runner.EmitIssue( 69 | r, 70 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 71 | attribute.Expr.Range(), 72 | ) 73 | }, nil) 74 | if err != nil { 75 | return err 76 | } 77 | } 78 | } 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /rules/google_container_node_pool_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleContainerNodePoolInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_container_node_pool" "primary_preemptible_nodes" { 20 | name = "my-node-pool" 21 | location = "us-central1" 22 | cluster = google_container_cluster.primary.name 23 | node_count = 1 24 | 25 | node_config { 26 | preemptible = true 27 | machine_type = "n2-medium" 28 | 29 | oauth_scopes = [ 30 | "https://www.googleapis.com/auth/logging.write", 31 | "https://www.googleapis.com/auth/monitoring", 32 | ] 33 | } 34 | }`, 35 | Expected: helper.Issues{ 36 | { 37 | Rule: NewGoogleContainerNodePoolInvalidMachineTypeRule(), 38 | Message: `"n2-medium" is an invalid as machine type`, 39 | Range: hcl.Range{ 40 | Filename: "resource.tf", 41 | Start: hcl.Pos{Line: 10, Column: 20}, 42 | End: hcl.Pos{Line: 10, Column: 31}, 43 | }, 44 | }, 45 | }, 46 | }, 47 | { 48 | Name: "valid type", 49 | Content: ` 50 | resource "google_container_node_pool" "primary_preemptible_nodes" { 51 | name = "my-node-pool" 52 | location = "us-central1" 53 | cluster = google_container_cluster.primary.name 54 | node_count = 1 55 | 56 | node_config { 57 | preemptible = true 58 | machine_type = "e2-medium" 59 | 60 | oauth_scopes = [ 61 | "https://www.googleapis.com/auth/logging.write", 62 | "https://www.googleapis.com/auth/monitoring", 63 | ] 64 | } 65 | }`, 66 | Expected: helper.Issues{}, 67 | }, 68 | { 69 | Name: "custom type", 70 | Content: ` 71 | resource "google_container_node_pool" "primary_preemptible_nodes" { 72 | name = "my-node-pool" 73 | location = "us-central1" 74 | cluster = google_container_cluster.primary.name 75 | node_count = 1 76 | 77 | node_config { 78 | preemptible = true 79 | machine_type = "n2-custom-6-20480" 80 | 81 | oauth_scopes = [ 82 | "https://www.googleapis.com/auth/logging.write", 83 | "https://www.googleapis.com/auth/monitoring", 84 | ] 85 | } 86 | }`, 87 | Expected: helper.Issues{}, 88 | }, 89 | } 90 | 91 | rule := NewGoogleContainerNodePoolInvalidMachineTypeRule() 92 | 93 | for _, tc := range cases { 94 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 95 | 96 | if err := rule.Check(runner); err != nil { 97 | t.Fatalf("Unexpected error occurred: %s", err) 98 | } 99 | 100 | helper.AssertIssues(t, tc.Expected, runner.Issues) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /rules/google_dataflow_job_invalid_machine_type.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | ) 9 | 10 | // GoogleDataflowJobInvalidMachineTypeRule checks whether the machine type is invalid 11 | type GoogleDataflowJobInvalidMachineTypeRule struct { 12 | tflint.DefaultRule 13 | } 14 | 15 | // NewGoogleDataflowJobInvalidMachineTypeRule returns a new rule 16 | func NewGoogleDataflowJobInvalidMachineTypeRule() *GoogleDataflowJobInvalidMachineTypeRule { 17 | return &GoogleDataflowJobInvalidMachineTypeRule{} 18 | } 19 | 20 | // Name returns the rule name 21 | func (r *GoogleDataflowJobInvalidMachineTypeRule) Name() string { 22 | return "google_dataflow_job_invalid_machine_type" 23 | } 24 | 25 | // Enabled returns whether the rule is enabled by default 26 | func (r *GoogleDataflowJobInvalidMachineTypeRule) Enabled() bool { 27 | return true 28 | } 29 | 30 | // Severity returns the rule severity 31 | func (r *GoogleDataflowJobInvalidMachineTypeRule) Severity() tflint.Severity { 32 | return tflint.ERROR 33 | } 34 | 35 | // Link returns the rule reference link 36 | func (r *GoogleDataflowJobInvalidMachineTypeRule) Link() string { 37 | return "" 38 | } 39 | 40 | // Check checks whether the machine type is invalid 41 | func (r *GoogleDataflowJobInvalidMachineTypeRule) Check(runner tflint.Runner) error { 42 | resources, err := runner.GetResourceContent("google_dataflow_job", &hclext.BodySchema{ 43 | Attributes: []hclext.AttributeSchema{{Name: "machine_type"}}, 44 | }, nil) 45 | if err != nil { 46 | return err 47 | } 48 | 49 | for _, resource := range resources.Blocks { 50 | attribute, exists := resource.Body.Attributes["machine_type"] 51 | if !exists { 52 | continue 53 | } 54 | 55 | err := runner.EvaluateExpr(attribute.Expr, func(machineType string) error { 56 | if validMachineTypes[machineType] || isCustomType(machineType) { 57 | return nil 58 | } 59 | 60 | return runner.EmitIssue( 61 | r, 62 | fmt.Sprintf(`"%s" is an invalid as machine type`, machineType), 63 | attribute.Expr.Range(), 64 | ) 65 | }, nil) 66 | if err != nil { 67 | return err 68 | } 69 | } 70 | 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /rules/google_dataflow_job_invalid_machine_type_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleDataflowJobInvalidMachineType(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid type", 18 | Content: ` 19 | resource "google_dataflow_job" "vm_instance" { 20 | machine_type = "n2-standard-1" 21 | }`, 22 | Expected: helper.Issues{ 23 | { 24 | Rule: NewGoogleDataflowJobInvalidMachineTypeRule(), 25 | Message: `"n2-standard-1" is an invalid as machine type`, 26 | Range: hcl.Range{ 27 | Filename: "resource.tf", 28 | Start: hcl.Pos{Line: 3, Column: 20}, 29 | End: hcl.Pos{Line: 3, Column: 35}, 30 | }, 31 | }, 32 | }, 33 | }, 34 | { 35 | Name: "valid type", 36 | Content: ` 37 | resource "google_dataflow_job" "vm_instance" { 38 | machine_type = "n2-standard-2" 39 | }`, 40 | Expected: helper.Issues{}, 41 | }, 42 | { 43 | Name: "custom type", 44 | Content: ` 45 | resource "google_dataflow_job" "vm_instance" { 46 | machine_type = "n2-custom-6-20480" 47 | }`, 48 | Expected: helper.Issues{}, 49 | }, 50 | } 51 | 52 | rule := NewGoogleDataflowJobInvalidMachineTypeRule() 53 | 54 | for _, tc := range cases { 55 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 56 | 57 | if err := rule.Check(runner); err != nil { 58 | t.Fatalf("Unexpected error occurred: %s", err) 59 | } 60 | 61 | helper.AssertIssues(t, tc.Expected, runner.Issues) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /rules/google_project_iam_audit_config_invalid_member.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | "github.com/terraform-linters/tflint-ruleset-google/project" 9 | ) 10 | 11 | // GoogleProjectIamAuditConfigInvalidMemberRule checks whether member value is invalid 12 | type GoogleProjectIamAuditConfigInvalidMemberRule struct { 13 | tflint.DefaultRule 14 | 15 | resourceType string 16 | blockName string 17 | attributeName string 18 | } 19 | 20 | func NewGoogleProjectIamAuditConfigInvalidMemberRule() *GoogleProjectIamAuditConfigInvalidMemberRule { 21 | return &GoogleProjectIamAuditConfigInvalidMemberRule{ 22 | resourceType: "google_project_iam_audit_config", 23 | blockName: "audit_log_config", 24 | attributeName: "exempted_members", 25 | } 26 | } 27 | 28 | // Name returns the rule name 29 | func (r *GoogleProjectIamAuditConfigInvalidMemberRule) Name() string { 30 | return "google_project_iam_audit_config_invalid_member" 31 | } 32 | 33 | // Enabled returns whether the rule is enabled by default 34 | func (r *GoogleProjectIamAuditConfigInvalidMemberRule) Enabled() bool { 35 | return true 36 | } 37 | 38 | // Severity returns the rule severity 39 | func (r *GoogleProjectIamAuditConfigInvalidMemberRule) Severity() tflint.Severity { 40 | return tflint.ERROR 41 | } 42 | 43 | // Link returns the rule reference link 44 | func (r *GoogleProjectIamAuditConfigInvalidMemberRule) Link() string { 45 | return project.ReferenceLink(r.Name()) 46 | } 47 | 48 | // Check checks whether member format is invalid 49 | func (r *GoogleProjectIamAuditConfigInvalidMemberRule) Check(runner tflint.Runner) error { 50 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 51 | Blocks: []hclext.BlockSchema{ 52 | { 53 | Type: r.blockName, 54 | Body: &hclext.BodySchema{ 55 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 56 | }, 57 | }, 58 | }, 59 | }, nil) 60 | if err != nil { 61 | return err 62 | } 63 | 64 | for _, resource := range resources.Blocks { 65 | for _, config := range resource.Body.Blocks { 66 | attribute, exists := config.Body.Attributes[r.attributeName] 67 | if !exists { 68 | continue 69 | } 70 | 71 | err := runner.EvaluateExpr(attribute.Expr, func(members []string) error { 72 | for _, member := range members { 73 | if !isValidIAMMemberFormat(member) { 74 | return runner.EmitIssue( 75 | r, 76 | fmt.Sprintf("%s is an invalid member format", member), 77 | attribute.Expr.Range(), 78 | ) 79 | } 80 | } 81 | return nil 82 | }, nil) 83 | if err != nil { 84 | return err 85 | } 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/google_project_iam_audit_config_invalid_member_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleProjectIamAuditConfigInvalidMember(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid member", 18 | Content: ` 19 | resource "google_project_iam_audit_config" "iam_audit_config" { 20 | audit_log_config { 21 | exempted_members = [ 22 | "jane@example.com", 23 | ] 24 | } 25 | } 26 | `, 27 | Expected: helper.Issues{ 28 | { 29 | Rule: NewGoogleProjectIamAuditConfigInvalidMemberRule(), 30 | Message: "jane@example.com is an invalid member format", 31 | Range: hcl.Range{ 32 | Filename: "resource.tf", 33 | Start: hcl.Pos{Line: 4, Column: 22}, 34 | End: hcl.Pos{Line: 6, Column: 4}, 35 | }, 36 | }, 37 | }, 38 | }, 39 | { 40 | Name: "valid member", 41 | Content: ` 42 | resource "google_project_iam_audit_config" "iam_audit_config" { 43 | audit_log_config { 44 | exempted_members = [ 45 | "user:jane@example.com", 46 | ] 47 | } 48 | } 49 | `, 50 | Expected: helper.Issues{}, 51 | }, 52 | { 53 | Name: "no member", 54 | Content: ` 55 | resource "google_project_iam_audit_config" "iam_audit_config" { 56 | audit_log_config { 57 | } 58 | } 59 | `, 60 | Expected: helper.Issues{}, 61 | }, 62 | } 63 | 64 | rule := NewGoogleProjectIamAuditConfigInvalidMemberRule() 65 | 66 | for _, tc := range cases { 67 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 68 | 69 | if err := rule.Check(runner); err != nil { 70 | t.Fatalf("Unexpected error occurred: %s", err) 71 | } 72 | 73 | helper.AssertIssues(t, tc.Expected, runner.Issues) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rules/google_project_iam_binding_invalid_member.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | "github.com/terraform-linters/tflint-ruleset-google/project" 9 | ) 10 | 11 | // GoogleProjectIamBindingInvalidMemberRule checks whether member value is invalid 12 | type GoogleProjectIamBindingInvalidMemberRule struct { 13 | tflint.DefaultRule 14 | 15 | resourceType string 16 | attributeName string 17 | } 18 | 19 | // NewGoogleProjectIamBindingInvalidMemberRule returns new rule with default attributes 20 | func NewGoogleProjectIamBindingInvalidMemberRule() *GoogleProjectIamBindingInvalidMemberRule { 21 | return &GoogleProjectIamBindingInvalidMemberRule{ 22 | resourceType: "google_project_iam_binding", 23 | attributeName: "members", 24 | } 25 | } 26 | 27 | // Name returns the rule name 28 | func (r *GoogleProjectIamBindingInvalidMemberRule) Name() string { 29 | return "google_project_iam_binding_invalid_member" 30 | } 31 | 32 | // Enabled returns whether the rule is enabled by default 33 | func (r *GoogleProjectIamBindingInvalidMemberRule) Enabled() bool { 34 | return true 35 | } 36 | 37 | // Severity returns the rule severity 38 | func (r *GoogleProjectIamBindingInvalidMemberRule) Severity() tflint.Severity { 39 | return tflint.ERROR 40 | } 41 | 42 | // Link returns the rule reference link 43 | func (r *GoogleProjectIamBindingInvalidMemberRule) Link() string { 44 | return project.ReferenceLink(r.Name()) 45 | } 46 | 47 | // Check checks whether member format is invalid 48 | func (r *GoogleProjectIamBindingInvalidMemberRule) Check(runner tflint.Runner) error { 49 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 50 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 51 | }, nil) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | for _, resource := range resources.Blocks { 57 | attribute, exists := resource.Body.Attributes[r.attributeName] 58 | if !exists { 59 | continue 60 | } 61 | 62 | err := runner.EvaluateExpr(attribute.Expr, func(members []string) error { 63 | for _, member := range members { 64 | if !isValidIAMMemberFormat(member) { 65 | return runner.EmitIssue( 66 | r, 67 | fmt.Sprintf("%s is an invalid member format", member), 68 | attribute.Expr.Range(), 69 | ) 70 | } 71 | } 72 | return nil 73 | }, nil) 74 | if err != nil { 75 | return err 76 | } 77 | } 78 | 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /rules/google_project_iam_binding_invalid_member_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleProjectIamBindingInvalidMember(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid member", 18 | Content: ` 19 | resource "google_project_iam_binding" "iam_binding" { 20 | members = [ 21 | "jane@example.com", 22 | ] 23 | } 24 | `, 25 | Expected: helper.Issues{ 26 | { 27 | Rule: NewGoogleProjectIamBindingInvalidMemberRule(), 28 | Message: "jane@example.com is an invalid member format", 29 | Range: hcl.Range{ 30 | Filename: "resource.tf", 31 | Start: hcl.Pos{Line: 3, Column: 12}, 32 | End: hcl.Pos{Line: 5, Column: 3}, 33 | }, 34 | }, 35 | }, 36 | }, 37 | { 38 | Name: "valid member", 39 | Content: ` 40 | resource "google_project_iam_binding" "iam_binding" { 41 | members = [ 42 | "user:jane@example.com", 43 | ] 44 | } 45 | `, 46 | Expected: helper.Issues{}, 47 | }, 48 | } 49 | 50 | rule := NewGoogleProjectIamBindingInvalidMemberRule() 51 | 52 | for _, tc := range cases { 53 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 54 | 55 | if err := rule.Check(runner); err != nil { 56 | t.Fatalf("Unexpected error occurred: %s", err) 57 | } 58 | 59 | helper.AssertIssues(t, tc.Expected, runner.Issues) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rules/google_project_iam_member_invalid_member.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | "github.com/terraform-linters/tflint-ruleset-google/project" 9 | ) 10 | 11 | // GoogleProjectIamMemberInvalidMemberRule checks whether member value is invalid 12 | type GoogleProjectIamMemberInvalidMemberRule struct { 13 | tflint.DefaultRule 14 | 15 | resourceType string 16 | attributeName string 17 | } 18 | 19 | // NewGoogleProjectIamMemberInvalidMemberRule returns new rule with default attributes 20 | func NewGoogleProjectIamMemberInvalidMemberRule() *GoogleProjectIamMemberInvalidMemberRule { 21 | return &GoogleProjectIamMemberInvalidMemberRule{ 22 | resourceType: "google_project_iam_member", 23 | attributeName: "member", 24 | } 25 | } 26 | 27 | // Name returns the rule name 28 | func (r *GoogleProjectIamMemberInvalidMemberRule) Name() string { 29 | return "google_project_iam_member_invalid_member" 30 | } 31 | 32 | // Enabled returns whether the rule is enabled by default 33 | func (r *GoogleProjectIamMemberInvalidMemberRule) Enabled() bool { 34 | return true 35 | } 36 | 37 | // Severity returns the rule severity 38 | func (r *GoogleProjectIamMemberInvalidMemberRule) Severity() tflint.Severity { 39 | return tflint.ERROR 40 | } 41 | 42 | // Link returns the rule reference link 43 | func (r *GoogleProjectIamMemberInvalidMemberRule) Link() string { 44 | return project.ReferenceLink(r.Name()) 45 | } 46 | 47 | // Check checks whether member format is invalid 48 | func (r *GoogleProjectIamMemberInvalidMemberRule) Check(runner tflint.Runner) error { 49 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 50 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 51 | }, nil) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | for _, resource := range resources.Blocks { 57 | attribute, exists := resource.Body.Attributes[r.attributeName] 58 | if !exists { 59 | continue 60 | } 61 | 62 | err := runner.EvaluateExpr(attribute.Expr, func(member string) error { 63 | if isValidIAMMemberFormat(member) { 64 | return nil 65 | } 66 | return runner.EmitIssue( 67 | r, 68 | fmt.Sprintf("%s is an invalid member format", member), 69 | attribute.Expr.Range(), 70 | ) 71 | }, nil) 72 | if err != nil { 73 | return err 74 | } 75 | } 76 | 77 | return nil 78 | } 79 | -------------------------------------------------------------------------------- /rules/google_project_iam_member_invalid_member_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleProjectIamMemberInvalidMember(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid member", 18 | Content: ` 19 | resource "google_project_iam_member" "iam_member" { 20 | member = "jane@example.com" 21 | } 22 | `, 23 | Expected: helper.Issues{ 24 | { 25 | Rule: NewGoogleProjectIamMemberInvalidMemberRule(), 26 | Message: "jane@example.com is an invalid member format", 27 | Range: hcl.Range{ 28 | Filename: "resource.tf", 29 | Start: hcl.Pos{Line: 3, Column: 11}, 30 | End: hcl.Pos{Line: 3, Column: 29}, 31 | }, 32 | }, 33 | }, 34 | }, 35 | { 36 | Name: "valid member", 37 | Content: ` 38 | resource "google_project_iam_member" "iam_member" { 39 | member = "user:jane@example.com" 40 | } 41 | `, 42 | Expected: helper.Issues{}, 43 | }, 44 | { 45 | Name: "valid member", 46 | Content: ` 47 | resource "google_project_iam_member" "iam_member" { 48 | member = "allUsers" 49 | } 50 | `, 51 | Expected: helper.Issues{}, 52 | }, 53 | } 54 | 55 | rule := NewGoogleProjectIamMemberInvalidMemberRule() 56 | 57 | for _, tc := range cases { 58 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 59 | 60 | if err := rule.Check(runner); err != nil { 61 | t.Fatalf("Unexpected error occurred: %s", err) 62 | } 63 | 64 | helper.AssertIssues(t, tc.Expected, runner.Issues) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /rules/google_project_iam_policy_invalid_member.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 7 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 8 | "github.com/terraform-linters/tflint-ruleset-google/project" 9 | ) 10 | 11 | // GoogleProjectIamPolicyInvalidMemberRule checks whether member value is invalid 12 | type GoogleProjectIamPolicyInvalidMemberRule struct { 13 | tflint.DefaultRule 14 | 15 | resourceType string 16 | attributeName string 17 | } 18 | 19 | // NewGoogleProjectIamPolicyInvalidMemberRule returns new rule with default attributes 20 | func NewGoogleProjectIamPolicyInvalidMemberRule() *GoogleProjectIamPolicyInvalidMemberRule { 21 | return &GoogleProjectIamPolicyInvalidMemberRule{ 22 | resourceType: "google_project_iam_policy", 23 | attributeName: "members", 24 | } 25 | } 26 | 27 | // Name returns the rule name 28 | func (r *GoogleProjectIamPolicyInvalidMemberRule) Name() string { 29 | return "google_project_iam_policy_invalid_member" 30 | } 31 | 32 | // Enabled returns whether the rule is enabled by default 33 | func (r *GoogleProjectIamPolicyInvalidMemberRule) Enabled() bool { 34 | return true 35 | } 36 | 37 | // Severity returns the rule severity 38 | func (r *GoogleProjectIamPolicyInvalidMemberRule) Severity() tflint.Severity { 39 | return tflint.ERROR 40 | } 41 | 42 | // Link returns the rule reference link 43 | func (r *GoogleProjectIamPolicyInvalidMemberRule) Link() string { 44 | return project.ReferenceLink(r.Name()) 45 | } 46 | 47 | // Check checks whether member format is invalid 48 | func (r *GoogleProjectIamPolicyInvalidMemberRule) Check(runner tflint.Runner) error { 49 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 50 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 51 | }, nil) 52 | if err != nil { 53 | return err 54 | } 55 | 56 | for _, resource := range resources.Blocks { 57 | attribute, exists := resource.Body.Attributes[r.attributeName] 58 | if !exists { 59 | continue 60 | } 61 | 62 | err := runner.EvaluateExpr(attribute.Expr, func(members []string) error { 63 | for _, member := range members { 64 | if !isValidIAMMemberFormat(member) { 65 | return runner.EmitIssue( 66 | r, 67 | fmt.Sprintf("%s is an invalid member format", member), 68 | attribute.Expr.Range(), 69 | ) 70 | } 71 | 72 | } 73 | return nil 74 | }, nil) 75 | if err != nil { 76 | return err 77 | } 78 | } 79 | 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /rules/google_project_iam_policy_invalid_member_test.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_GoogleProjectIamPolicyInvalidMember(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid member", 18 | Content: ` 19 | resource "google_project_iam_policy" "iam_policy" { 20 | members = [ 21 | "jane@example.com", 22 | ] 23 | } 24 | `, 25 | Expected: helper.Issues{ 26 | { 27 | Rule: NewGoogleProjectIamPolicyInvalidMemberRule(), 28 | Message: "jane@example.com is an invalid member format", 29 | Range: hcl.Range{ 30 | Filename: "resource.tf", 31 | Start: hcl.Pos{Line: 3, Column: 12}, 32 | End: hcl.Pos{Line: 5, Column: 3}, 33 | }, 34 | }, 35 | }, 36 | }, 37 | { 38 | Name: "valid member", 39 | Content: ` 40 | resource "google_project_iam_policy" "iam_policy" { 41 | members = [ 42 | "user:jane@example.com", 43 | ] 44 | } 45 | `, 46 | Expected: helper.Issues{}, 47 | }, 48 | } 49 | 50 | rule := NewGoogleProjectIamPolicyInvalidMemberRule() 51 | 52 | for _, tc := range cases { 53 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 54 | 55 | if err := rule.Check(runner); err != nil { 56 | t.Fatalf("Unexpected error occurred: %s", err) 57 | } 58 | 59 | helper.AssertIssues(t, tc.Expected, runner.Issues) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rules/magicmodules/generated_rules_test.go: -------------------------------------------------------------------------------- 1 | package magicmodules 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_generatedRegexRule(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "invalid", 18 | Content: ` 19 | resource "google_compute_backend_bucket" "main" { 20 | name = "123" 21 | }`, 22 | Expected: helper.Issues{ 23 | { 24 | Rule: NewGoogleComputeBackendBucketInvalidNameRule(), 25 | Message: `"name" ("123") doesn't match regexp "^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$"`, 26 | Range: hcl.Range{ 27 | Filename: "resource.tf", 28 | Start: hcl.Pos{Line: 3, Column: 10}, 29 | End: hcl.Pos{Line: 3, Column: 15}, 30 | }, 31 | }, 32 | }, 33 | }, 34 | { 35 | Name: "valid", 36 | Content: ` 37 | resource "google_compute_backend_bucket" "main" { 38 | name = "valid" 39 | }`, 40 | Expected: helper.Issues{}, 41 | }, 42 | } 43 | 44 | rule := NewGoogleComputeBackendBucketInvalidNameRule() 45 | 46 | for _, tc := range cases { 47 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 48 | 49 | if err := rule.Check(runner); err != nil { 50 | t.Fatalf("Unexpected error occurred: %s", err) 51 | } 52 | 53 | helper.AssertIssues(t, tc.Expected, runner.Issues) 54 | } 55 | } 56 | 57 | func Test_generatedEnumRule(t *testing.T) { 58 | cases := []struct { 59 | Name string 60 | Content string 61 | Expected helper.Issues 62 | }{ 63 | { 64 | Name: "invalid", 65 | Content: ` 66 | resource "google_cloud_asset_folder_feed" "main" { 67 | content_type = "INVALID" 68 | }`, 69 | Expected: helper.Issues{ 70 | { 71 | Rule: NewGoogleCloudAssetFolderFeedInvalidContentTypeRule(), 72 | Message: `expected content_type to be one of ["CONTENT_TYPE_UNSPECIFIED" "RESOURCE" "IAM_POLICY" "ORG_POLICY" "OS_INVENTORY" "ACCESS_POLICY" ""], got INVALID`, 73 | Range: hcl.Range{ 74 | Filename: "resource.tf", 75 | Start: hcl.Pos{Line: 3, Column: 18}, 76 | End: hcl.Pos{Line: 3, Column: 27}, 77 | }, 78 | }, 79 | }, 80 | }, 81 | { 82 | Name: "valid", 83 | Content: ` 84 | resource "google_cloud_asset_folder_feed" "main" { 85 | name = "RESOURCE" 86 | }`, 87 | Expected: helper.Issues{}, 88 | }, 89 | } 90 | 91 | rule := NewGoogleCloudAssetFolderFeedInvalidContentTypeRule() 92 | 93 | for _, tc := range cases { 94 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 95 | 96 | if err := rule.Check(runner); err != nil { 97 | t.Fatalf("Unexpected error occurred: %s", err) 98 | } 99 | 100 | helper.AssertIssues(t, tc.Expected, runner.Issues) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /rules/magicmodules/google_alloydb_backup_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleAlloydbBackupInvalidTypeRule checks the pattern is valid 24 | type GoogleAlloydbBackupInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleAlloydbBackupInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleAlloydbBackupInvalidTypeRule() *GoogleAlloydbBackupInvalidTypeRule { 33 | return &GoogleAlloydbBackupInvalidTypeRule{ 34 | resourceType: "google_alloydb_backup", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleAlloydbBackupInvalidTypeRule) Name() string { 41 | return "google_alloydb_backup_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleAlloydbBackupInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleAlloydbBackupInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleAlloydbBackupInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleAlloydbBackupInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"TYPE_UNSPECIFIED", "ON_DEMAND", "AUTOMATED", "CONTINUOUS", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_alloydb_user_invalid_user_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleAlloydbUserInvalidUserTypeRule checks the pattern is valid 24 | type GoogleAlloydbUserInvalidUserTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleAlloydbUserInvalidUserTypeRule returns new rule with default attributes 32 | func NewGoogleAlloydbUserInvalidUserTypeRule() *GoogleAlloydbUserInvalidUserTypeRule { 33 | return &GoogleAlloydbUserInvalidUserTypeRule{ 34 | resourceType: "google_alloydb_user", 35 | attributeName: "user_type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleAlloydbUserInvalidUserTypeRule) Name() string { 41 | return "google_alloydb_user_invalid_user_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleAlloydbUserInvalidUserTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleAlloydbUserInvalidUserTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleAlloydbUserInvalidUserTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleAlloydbUserInvalidUserTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ALLOYDB_BUILT_IN", "ALLOYDB_IAM_USER"}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_apigee_app_group_invalid_status.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleApigeeAppGroupInvalidStatusRule checks the pattern is valid 24 | type GoogleApigeeAppGroupInvalidStatusRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleApigeeAppGroupInvalidStatusRule returns new rule with default attributes 32 | func NewGoogleApigeeAppGroupInvalidStatusRule() *GoogleApigeeAppGroupInvalidStatusRule { 33 | return &GoogleApigeeAppGroupInvalidStatusRule{ 34 | resourceType: "google_apigee_app_group", 35 | attributeName: "status", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleApigeeAppGroupInvalidStatusRule) Name() string { 41 | return "google_apigee_app_group_invalid_status" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleApigeeAppGroupInvalidStatusRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleApigeeAppGroupInvalidStatusRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleApigeeAppGroupInvalidStatusRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleApigeeAppGroupInvalidStatusRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"active", "inactive", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_apigee_environment_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleApigeeEnvironmentInvalidTypeRule checks the pattern is valid 24 | type GoogleApigeeEnvironmentInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleApigeeEnvironmentInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleApigeeEnvironmentInvalidTypeRule() *GoogleApigeeEnvironmentInvalidTypeRule { 33 | return &GoogleApigeeEnvironmentInvalidTypeRule{ 34 | resourceType: "google_apigee_environment", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleApigeeEnvironmentInvalidTypeRule) Name() string { 41 | return "google_apigee_environment_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleApigeeEnvironmentInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleApigeeEnvironmentInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleApigeeEnvironmentInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleApigeeEnvironmentInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ENVIRONMENT_TYPE_UNSPECIFIED", "BASE", "INTERMEDIATE", "COMPREHENSIVE", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_biglake_table_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleBiglakeTableInvalidTypeRule checks the pattern is valid 24 | type GoogleBiglakeTableInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleBiglakeTableInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleBiglakeTableInvalidTypeRule() *GoogleBiglakeTableInvalidTypeRule { 33 | return &GoogleBiglakeTableInvalidTypeRule{ 34 | resourceType: "google_biglake_table", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleBiglakeTableInvalidTypeRule) Name() string { 41 | return "google_biglake_table_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleBiglakeTableInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleBiglakeTableInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleBiglakeTableInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleBiglakeTableInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"HIVE", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_bigquery_routine_invalid_language.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleBigqueryRoutineInvalidLanguageRule checks the pattern is valid 24 | type GoogleBigqueryRoutineInvalidLanguageRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleBigqueryRoutineInvalidLanguageRule returns new rule with default attributes 32 | func NewGoogleBigqueryRoutineInvalidLanguageRule() *GoogleBigqueryRoutineInvalidLanguageRule { 33 | return &GoogleBigqueryRoutineInvalidLanguageRule{ 34 | resourceType: "google_bigquery_routine", 35 | attributeName: "language", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleBigqueryRoutineInvalidLanguageRule) Name() string { 41 | return "google_bigquery_routine_invalid_language" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleBigqueryRoutineInvalidLanguageRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleBigqueryRoutineInvalidLanguageRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleBigqueryRoutineInvalidLanguageRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleBigqueryRoutineInvalidLanguageRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"SQL", "JAVASCRIPT", "PYTHON", "JAVA", "SCALA", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_address_invalid_ip_version.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleComputeAddressInvalidIpVersionRule checks the pattern is valid 24 | type GoogleComputeAddressInvalidIpVersionRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleComputeAddressInvalidIpVersionRule returns new rule with default attributes 32 | func NewGoogleComputeAddressInvalidIpVersionRule() *GoogleComputeAddressInvalidIpVersionRule { 33 | return &GoogleComputeAddressInvalidIpVersionRule{ 34 | resourceType: "google_compute_address", 35 | attributeName: "ip_version", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleComputeAddressInvalidIpVersionRule) Name() string { 41 | return "google_compute_address_invalid_ip_version" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleComputeAddressInvalidIpVersionRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleComputeAddressInvalidIpVersionRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleComputeAddressInvalidIpVersionRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleComputeAddressInvalidIpVersionRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"IPV4", "IPV6", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_address_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleComputeAddressInvalidNameRule checks the pattern is valid 23 | type GoogleComputeAddressInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleComputeAddressInvalidNameRule returns new rule with default attributes 31 | func NewGoogleComputeAddressInvalidNameRule() *GoogleComputeAddressInvalidNameRule { 32 | return &GoogleComputeAddressInvalidNameRule{ 33 | resourceType: "google_compute_address", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleComputeAddressInvalidNameRule) Name() string { 40 | return "google_compute_address_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleComputeAddressInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleComputeAddressInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleComputeAddressInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleComputeAddressInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_backend_bucket_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleComputeBackendBucketInvalidNameRule checks the pattern is valid 23 | type GoogleComputeBackendBucketInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleComputeBackendBucketInvalidNameRule returns new rule with default attributes 31 | func NewGoogleComputeBackendBucketInvalidNameRule() *GoogleComputeBackendBucketInvalidNameRule { 32 | return &GoogleComputeBackendBucketInvalidNameRule{ 33 | resourceType: "google_compute_backend_bucket", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleComputeBackendBucketInvalidNameRule) Name() string { 40 | return "google_compute_backend_bucket_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleComputeBackendBucketInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleComputeBackendBucketInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleComputeBackendBucketInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleComputeBackendBucketInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_firewall_invalid_direction.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleComputeFirewallInvalidDirectionRule checks the pattern is valid 24 | type GoogleComputeFirewallInvalidDirectionRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleComputeFirewallInvalidDirectionRule returns new rule with default attributes 32 | func NewGoogleComputeFirewallInvalidDirectionRule() *GoogleComputeFirewallInvalidDirectionRule { 33 | return &GoogleComputeFirewallInvalidDirectionRule{ 34 | resourceType: "google_compute_firewall", 35 | attributeName: "direction", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleComputeFirewallInvalidDirectionRule) Name() string { 41 | return "google_compute_firewall_invalid_direction" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleComputeFirewallInvalidDirectionRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleComputeFirewallInvalidDirectionRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleComputeFirewallInvalidDirectionRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleComputeFirewallInvalidDirectionRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"INGRESS", "EGRESS", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_interconnect_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleComputeInterconnectInvalidNameRule checks the pattern is valid 23 | type GoogleComputeInterconnectInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleComputeInterconnectInvalidNameRule returns new rule with default attributes 31 | func NewGoogleComputeInterconnectInvalidNameRule() *GoogleComputeInterconnectInvalidNameRule { 32 | return &GoogleComputeInterconnectInvalidNameRule{ 33 | resourceType: "google_compute_interconnect", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleComputeInterconnectInvalidNameRule) Name() string { 40 | return "google_compute_interconnect_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleComputeInterconnectInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleComputeInterconnectInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleComputeInterconnectInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleComputeInterconnectInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z]([-a-z0-9]*[a-z0-9])?$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_route_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleComputeRouteInvalidNameRule checks the pattern is valid 23 | type GoogleComputeRouteInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleComputeRouteInvalidNameRule returns new rule with default attributes 31 | func NewGoogleComputeRouteInvalidNameRule() *GoogleComputeRouteInvalidNameRule { 32 | return &GoogleComputeRouteInvalidNameRule{ 33 | resourceType: "google_compute_route", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleComputeRouteInvalidNameRule) Name() string { 40 | return "google_compute_route_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleComputeRouteInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleComputeRouteInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleComputeRouteInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleComputeRouteInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z]([-a-z0-9]*[a-z0-9])?$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_router_nat_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleComputeRouterNatInvalidTypeRule checks the pattern is valid 24 | type GoogleComputeRouterNatInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleComputeRouterNatInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleComputeRouterNatInvalidTypeRule() *GoogleComputeRouterNatInvalidTypeRule { 33 | return &GoogleComputeRouterNatInvalidTypeRule{ 34 | resourceType: "google_compute_router_nat", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleComputeRouterNatInvalidTypeRule) Name() string { 41 | return "google_compute_router_nat_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleComputeRouterNatInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleComputeRouterNatInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleComputeRouterNatInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleComputeRouterNatInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"PUBLIC", "PRIVATE", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_compute_subnetwork_invalid_role.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleComputeSubnetworkInvalidRoleRule checks the pattern is valid 24 | type GoogleComputeSubnetworkInvalidRoleRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleComputeSubnetworkInvalidRoleRule returns new rule with default attributes 32 | func NewGoogleComputeSubnetworkInvalidRoleRule() *GoogleComputeSubnetworkInvalidRoleRule { 33 | return &GoogleComputeSubnetworkInvalidRoleRule{ 34 | resourceType: "google_compute_subnetwork", 35 | attributeName: "role", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleComputeSubnetworkInvalidRoleRule) Name() string { 41 | return "google_compute_subnetwork_invalid_role" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleComputeSubnetworkInvalidRoleRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleComputeSubnetworkInvalidRoleRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleComputeSubnetworkInvalidRoleRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleComputeSubnetworkInvalidRoleRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ACTIVE", "BACKUP", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_data_catalog_entry_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleDataCatalogEntryInvalidTypeRule checks the pattern is valid 24 | type GoogleDataCatalogEntryInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleDataCatalogEntryInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleDataCatalogEntryInvalidTypeRule() *GoogleDataCatalogEntryInvalidTypeRule { 33 | return &GoogleDataCatalogEntryInvalidTypeRule{ 34 | resourceType: "google_data_catalog_entry", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleDataCatalogEntryInvalidTypeRule) Name() string { 41 | return "google_data_catalog_entry_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleDataCatalogEntryInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleDataCatalogEntryInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleDataCatalogEntryInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleDataCatalogEntryInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"FILESET", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_data_fusion_instance_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleDataFusionInstanceInvalidTypeRule checks the pattern is valid 24 | type GoogleDataFusionInstanceInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleDataFusionInstanceInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleDataFusionInstanceInvalidTypeRule() *GoogleDataFusionInstanceInvalidTypeRule { 33 | return &GoogleDataFusionInstanceInvalidTypeRule{ 34 | resourceType: "google_data_fusion_instance", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleDataFusionInstanceInvalidTypeRule) Name() string { 41 | return "google_data_fusion_instance_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleDataFusionInstanceInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleDataFusionInstanceInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleDataFusionInstanceInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleDataFusionInstanceInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"BASIC", "ENTERPRISE", "DEVELOPER"}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_dialogflow_agent_invalid_tier.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleDialogflowAgentInvalidTierRule checks the pattern is valid 24 | type GoogleDialogflowAgentInvalidTierRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleDialogflowAgentInvalidTierRule returns new rule with default attributes 32 | func NewGoogleDialogflowAgentInvalidTierRule() *GoogleDialogflowAgentInvalidTierRule { 33 | return &GoogleDialogflowAgentInvalidTierRule{ 34 | resourceType: "google_dialogflow_agent", 35 | attributeName: "tier", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleDialogflowAgentInvalidTierRule) Name() string { 41 | return "google_dialogflow_agent_invalid_tier" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleDialogflowAgentInvalidTierRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleDialogflowAgentInvalidTierRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleDialogflowAgentInvalidTierRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleDialogflowAgentInvalidTierRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"TIER_STANDARD", "TIER_ENTERPRISE", "TIER_ENTERPRISE_PLUS", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_dns_managed_zone_invalid_visibility.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleDnsManagedZoneInvalidVisibilityRule checks the pattern is valid 24 | type GoogleDnsManagedZoneInvalidVisibilityRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleDnsManagedZoneInvalidVisibilityRule returns new rule with default attributes 32 | func NewGoogleDnsManagedZoneInvalidVisibilityRule() *GoogleDnsManagedZoneInvalidVisibilityRule { 33 | return &GoogleDnsManagedZoneInvalidVisibilityRule{ 34 | resourceType: "google_dns_managed_zone", 35 | attributeName: "visibility", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleDnsManagedZoneInvalidVisibilityRule) Name() string { 41 | return "google_dns_managed_zone_invalid_visibility" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleDnsManagedZoneInvalidVisibilityRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleDnsManagedZoneInvalidVisibilityRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleDnsManagedZoneInvalidVisibilityRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleDnsManagedZoneInvalidVisibilityRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"private", "public", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_firestore_database_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleFirestoreDatabaseInvalidTypeRule checks the pattern is valid 24 | type GoogleFirestoreDatabaseInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleFirestoreDatabaseInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleFirestoreDatabaseInvalidTypeRule() *GoogleFirestoreDatabaseInvalidTypeRule { 33 | return &GoogleFirestoreDatabaseInvalidTypeRule{ 34 | resourceType: "google_firestore_database", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleFirestoreDatabaseInvalidTypeRule) Name() string { 41 | return "google_firestore_database_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleFirestoreDatabaseInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleFirestoreDatabaseInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleFirestoreDatabaseInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleFirestoreDatabaseInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"FIRESTORE_NATIVE", "DATASTORE_MODE"}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_firestore_index_invalid_api_scope.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleFirestoreIndexInvalidApiScopeRule checks the pattern is valid 24 | type GoogleFirestoreIndexInvalidApiScopeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleFirestoreIndexInvalidApiScopeRule returns new rule with default attributes 32 | func NewGoogleFirestoreIndexInvalidApiScopeRule() *GoogleFirestoreIndexInvalidApiScopeRule { 33 | return &GoogleFirestoreIndexInvalidApiScopeRule{ 34 | resourceType: "google_firestore_index", 35 | attributeName: "api_scope", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleFirestoreIndexInvalidApiScopeRule) Name() string { 41 | return "google_firestore_index_invalid_api_scope" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleFirestoreIndexInvalidApiScopeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleFirestoreIndexInvalidApiScopeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleFirestoreIndexInvalidApiScopeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleFirestoreIndexInvalidApiScopeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ANY_API", "DATASTORE_MODE_API", "MONGODB_COMPATIBLE_API", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_firestore_index_invalid_density.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleFirestoreIndexInvalidDensityRule checks the pattern is valid 24 | type GoogleFirestoreIndexInvalidDensityRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleFirestoreIndexInvalidDensityRule returns new rule with default attributes 32 | func NewGoogleFirestoreIndexInvalidDensityRule() *GoogleFirestoreIndexInvalidDensityRule { 33 | return &GoogleFirestoreIndexInvalidDensityRule{ 34 | resourceType: "google_firestore_index", 35 | attributeName: "density", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleFirestoreIndexInvalidDensityRule) Name() string { 41 | return "google_firestore_index_invalid_density" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleFirestoreIndexInvalidDensityRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleFirestoreIndexInvalidDensityRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleFirestoreIndexInvalidDensityRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleFirestoreIndexInvalidDensityRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"SPARSE_ALL", "SPARSE_ANY", "DENSE", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_looker_instance_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleLookerInstanceInvalidNameRule checks the pattern is valid 23 | type GoogleLookerInstanceInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleLookerInstanceInvalidNameRule returns new rule with default attributes 31 | func NewGoogleLookerInstanceInvalidNameRule() *GoogleLookerInstanceInvalidNameRule { 32 | return &GoogleLookerInstanceInvalidNameRule{ 33 | resourceType: "google_looker_instance", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleLookerInstanceInvalidNameRule) Name() string { 40 | return "google_looker_instance_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleLookerInstanceInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleLookerInstanceInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleLookerInstanceInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleLookerInstanceInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][a-z0-9-]{0,61}[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_memorystore_instance_invalid_mode.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleMemorystoreInstanceInvalidModeRule checks the pattern is valid 24 | type GoogleMemorystoreInstanceInvalidModeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleMemorystoreInstanceInvalidModeRule returns new rule with default attributes 32 | func NewGoogleMemorystoreInstanceInvalidModeRule() *GoogleMemorystoreInstanceInvalidModeRule { 33 | return &GoogleMemorystoreInstanceInvalidModeRule{ 34 | resourceType: "google_memorystore_instance", 35 | attributeName: "mode", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleMemorystoreInstanceInvalidModeRule) Name() string { 41 | return "google_memorystore_instance_invalid_mode" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleMemorystoreInstanceInvalidModeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleMemorystoreInstanceInvalidModeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleMemorystoreInstanceInvalidModeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleMemorystoreInstanceInvalidModeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"CLUSTER", "CLUSTER_DISABLED", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_monitoring_slo_invalid_slo_id.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleMonitoringSloInvalidSloIdRule checks the pattern is valid 23 | type GoogleMonitoringSloInvalidSloIdRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleMonitoringSloInvalidSloIdRule returns new rule with default attributes 31 | func NewGoogleMonitoringSloInvalidSloIdRule() *GoogleMonitoringSloInvalidSloIdRule { 32 | return &GoogleMonitoringSloInvalidSloIdRule{ 33 | resourceType: "google_monitoring_slo", 34 | attributeName: "slo_id", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleMonitoringSloInvalidSloIdRule) Name() string { 40 | return "google_monitoring_slo_invalid_slo_id" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleMonitoringSloInvalidSloIdRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleMonitoringSloInvalidSloIdRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleMonitoringSloInvalidSloIdRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleMonitoringSloInvalidSloIdRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-zA-Z0-9\-_:.]+$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_network_services_grpc_route_invalid_location.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleNetworkServicesGrpcRouteInvalidLocationRule checks the pattern is valid 23 | type GoogleNetworkServicesGrpcRouteInvalidLocationRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleNetworkServicesGrpcRouteInvalidLocationRule returns new rule with default attributes 31 | func NewGoogleNetworkServicesGrpcRouteInvalidLocationRule() *GoogleNetworkServicesGrpcRouteInvalidLocationRule { 32 | return &GoogleNetworkServicesGrpcRouteInvalidLocationRule{ 33 | resourceType: "google_network_services_grpc_route", 34 | attributeName: "location", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleNetworkServicesGrpcRouteInvalidLocationRule) Name() string { 40 | return "google_network_services_grpc_route_invalid_location" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleNetworkServicesGrpcRouteInvalidLocationRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleNetworkServicesGrpcRouteInvalidLocationRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleNetworkServicesGrpcRouteInvalidLocationRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleNetworkServicesGrpcRouteInvalidLocationRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^global$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_network_services_mesh_invalid_location.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleNetworkServicesMeshInvalidLocationRule checks the pattern is valid 23 | type GoogleNetworkServicesMeshInvalidLocationRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleNetworkServicesMeshInvalidLocationRule returns new rule with default attributes 31 | func NewGoogleNetworkServicesMeshInvalidLocationRule() *GoogleNetworkServicesMeshInvalidLocationRule { 32 | return &GoogleNetworkServicesMeshInvalidLocationRule{ 33 | resourceType: "google_network_services_mesh", 34 | attributeName: "location", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleNetworkServicesMeshInvalidLocationRule) Name() string { 40 | return "google_network_services_mesh_invalid_location" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleNetworkServicesMeshInvalidLocationRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleNetworkServicesMeshInvalidLocationRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleNetworkServicesMeshInvalidLocationRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleNetworkServicesMeshInvalidLocationRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^global$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_privateca_ca_pool_invalid_tier.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GooglePrivatecaCaPoolInvalidTierRule checks the pattern is valid 24 | type GooglePrivatecaCaPoolInvalidTierRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGooglePrivatecaCaPoolInvalidTierRule returns new rule with default attributes 32 | func NewGooglePrivatecaCaPoolInvalidTierRule() *GooglePrivatecaCaPoolInvalidTierRule { 33 | return &GooglePrivatecaCaPoolInvalidTierRule{ 34 | resourceType: "google_privateca_ca_pool", 35 | attributeName: "tier", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GooglePrivatecaCaPoolInvalidTierRule) Name() string { 41 | return "google_privateca_ca_pool_invalid_tier" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GooglePrivatecaCaPoolInvalidTierRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GooglePrivatecaCaPoolInvalidTierRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GooglePrivatecaCaPoolInvalidTierRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GooglePrivatecaCaPoolInvalidTierRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ENTERPRISE", "DEVOPS"}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_pubsub_schema_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GooglePubsubSchemaInvalidTypeRule checks the pattern is valid 24 | type GooglePubsubSchemaInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGooglePubsubSchemaInvalidTypeRule returns new rule with default attributes 32 | func NewGooglePubsubSchemaInvalidTypeRule() *GooglePubsubSchemaInvalidTypeRule { 33 | return &GooglePubsubSchemaInvalidTypeRule{ 34 | resourceType: "google_pubsub_schema", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GooglePubsubSchemaInvalidTypeRule) Name() string { 41 | return "google_pubsub_schema_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GooglePubsubSchemaInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GooglePubsubSchemaInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GooglePubsubSchemaInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GooglePubsubSchemaInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"TYPE_UNSPECIFIED", "PROTOCOL_BUFFER", "AVRO", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_pubsub_subscription_invalid_filter.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GooglePubsubSubscriptionInvalidFilterRule checks the pattern is valid 23 | type GooglePubsubSubscriptionInvalidFilterRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGooglePubsubSubscriptionInvalidFilterRule returns new rule with default attributes 31 | func NewGooglePubsubSubscriptionInvalidFilterRule() *GooglePubsubSubscriptionInvalidFilterRule { 32 | return &GooglePubsubSubscriptionInvalidFilterRule{ 33 | resourceType: "google_pubsub_subscription", 34 | attributeName: "filter", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GooglePubsubSubscriptionInvalidFilterRule) Name() string { 40 | return "google_pubsub_subscription_invalid_filter" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GooglePubsubSubscriptionInvalidFilterRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GooglePubsubSubscriptionInvalidFilterRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GooglePubsubSubscriptionInvalidFilterRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GooglePubsubSubscriptionInvalidFilterRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[\s\S]{0,256}$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_redis_instance_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleRedisInstanceInvalidNameRule checks the pattern is valid 23 | type GoogleRedisInstanceInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleRedisInstanceInvalidNameRule returns new rule with default attributes 31 | func NewGoogleRedisInstanceInvalidNameRule() *GoogleRedisInstanceInvalidNameRule { 32 | return &GoogleRedisInstanceInvalidNameRule{ 33 | resourceType: "google_redis_instance", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleRedisInstanceInvalidNameRule) Name() string { 40 | return "google_redis_instance_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleRedisInstanceInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleRedisInstanceInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleRedisInstanceInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleRedisInstanceInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][a-z0-9-]{0,39}[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_redis_instance_invalid_tier.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleRedisInstanceInvalidTierRule checks the pattern is valid 24 | type GoogleRedisInstanceInvalidTierRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleRedisInstanceInvalidTierRule returns new rule with default attributes 32 | func NewGoogleRedisInstanceInvalidTierRule() *GoogleRedisInstanceInvalidTierRule { 33 | return &GoogleRedisInstanceInvalidTierRule{ 34 | resourceType: "google_redis_instance", 35 | attributeName: "tier", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleRedisInstanceInvalidTierRule) Name() string { 41 | return "google_redis_instance_invalid_tier" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleRedisInstanceInvalidTierRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleRedisInstanceInvalidTierRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleRedisInstanceInvalidTierRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleRedisInstanceInvalidTierRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"BASIC", "STANDARD_HA", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_scc_mute_config_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleSccMuteConfigInvalidTypeRule checks the pattern is valid 24 | type GoogleSccMuteConfigInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleSccMuteConfigInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleSccMuteConfigInvalidTypeRule() *GoogleSccMuteConfigInvalidTypeRule { 33 | return &GoogleSccMuteConfigInvalidTypeRule{ 34 | resourceType: "google_scc_mute_config", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleSccMuteConfigInvalidTypeRule) Name() string { 41 | return "google_scc_mute_config_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleSccMuteConfigInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleSccMuteConfigInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleSccMuteConfigInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleSccMuteConfigInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"MUTE_CONFIG_TYPE_UNSPECIFIED", "STATIC", "DYNAMIC", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_scc_source_invalid_display_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleSccSourceInvalidDisplayNameRule checks the pattern is valid 23 | type GoogleSccSourceInvalidDisplayNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleSccSourceInvalidDisplayNameRule returns new rule with default attributes 31 | func NewGoogleSccSourceInvalidDisplayNameRule() *GoogleSccSourceInvalidDisplayNameRule { 32 | return &GoogleSccSourceInvalidDisplayNameRule{ 33 | resourceType: "google_scc_source", 34 | attributeName: "display_name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleSccSourceInvalidDisplayNameRule) Name() string { 40 | return "google_scc_source_invalid_display_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleSccSourceInvalidDisplayNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleSccSourceInvalidDisplayNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleSccSourceInvalidDisplayNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleSccSourceInvalidDisplayNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`[\p{L}\p{N}]({\p{L}\p{N}_- ]{0,30}[\p{L}\p{N}])?`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_spanner_backup_schedule_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleSpannerBackupScheduleInvalidNameRule checks the pattern is valid 23 | type GoogleSpannerBackupScheduleInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleSpannerBackupScheduleInvalidNameRule returns new rule with default attributes 31 | func NewGoogleSpannerBackupScheduleInvalidNameRule() *GoogleSpannerBackupScheduleInvalidNameRule { 32 | return &GoogleSpannerBackupScheduleInvalidNameRule{ 33 | resourceType: "google_spanner_backup_schedule", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleSpannerBackupScheduleInvalidNameRule) Name() string { 40 | return "google_spanner_backup_schedule_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleSpannerBackupScheduleInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleSpannerBackupScheduleInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleSpannerBackupScheduleInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleSpannerBackupScheduleInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][a-z0-9_\-]*[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_spanner_database_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleSpannerDatabaseInvalidNameRule checks the pattern is valid 23 | type GoogleSpannerDatabaseInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleSpannerDatabaseInvalidNameRule returns new rule with default attributes 31 | func NewGoogleSpannerDatabaseInvalidNameRule() *GoogleSpannerDatabaseInvalidNameRule { 32 | return &GoogleSpannerDatabaseInvalidNameRule{ 33 | resourceType: "google_spanner_database", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleSpannerDatabaseInvalidNameRule) Name() string { 40 | return "google_spanner_database_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleSpannerDatabaseInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleSpannerDatabaseInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleSpannerDatabaseInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleSpannerDatabaseInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][a-z0-9_\-]*[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_spanner_instance_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleSpannerInstanceInvalidNameRule checks the pattern is valid 23 | type GoogleSpannerInstanceInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleSpannerInstanceInvalidNameRule returns new rule with default attributes 31 | func NewGoogleSpannerInstanceInvalidNameRule() *GoogleSpannerInstanceInvalidNameRule { 32 | return &GoogleSpannerInstanceInvalidNameRule{ 33 | resourceType: "google_spanner_instance", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleSpannerInstanceInvalidNameRule) Name() string { 40 | return "google_spanner_instance_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleSpannerInstanceInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleSpannerInstanceInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleSpannerInstanceInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleSpannerInstanceInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][-a-z0-9]*[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_spanner_instance_partition_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleSpannerInstancePartitionInvalidNameRule checks the pattern is valid 23 | type GoogleSpannerInstancePartitionInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleSpannerInstancePartitionInvalidNameRule returns new rule with default attributes 31 | func NewGoogleSpannerInstancePartitionInvalidNameRule() *GoogleSpannerInstancePartitionInvalidNameRule { 32 | return &GoogleSpannerInstancePartitionInvalidNameRule{ 33 | resourceType: "google_spanner_instance_partition", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleSpannerInstancePartitionInvalidNameRule) Name() string { 40 | return "google_spanner_instance_partition_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleSpannerInstancePartitionInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleSpannerInstancePartitionInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleSpannerInstancePartitionInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleSpannerInstancePartitionInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`^[a-z][a-z0-9-]{0,61}[a-z0-9]$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_storage_hmac_key_invalid_state.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleStorageHmacKeyInvalidStateRule checks the pattern is valid 24 | type GoogleStorageHmacKeyInvalidStateRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleStorageHmacKeyInvalidStateRule returns new rule with default attributes 32 | func NewGoogleStorageHmacKeyInvalidStateRule() *GoogleStorageHmacKeyInvalidStateRule { 33 | return &GoogleStorageHmacKeyInvalidStateRule{ 34 | resourceType: "google_storage_hmac_key", 35 | attributeName: "state", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleStorageHmacKeyInvalidStateRule) Name() string { 41 | return "google_storage_hmac_key_invalid_state" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleStorageHmacKeyInvalidStateRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleStorageHmacKeyInvalidStateRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleStorageHmacKeyInvalidStateRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleStorageHmacKeyInvalidStateRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"ACTIVE", "INACTIVE", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_storage_managed_folder_invalid_name.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 19 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 20 | ) 21 | 22 | // GoogleStorageManagedFolderInvalidNameRule checks the pattern is valid 23 | type GoogleStorageManagedFolderInvalidNameRule struct { 24 | tflint.DefaultRule 25 | 26 | resourceType string 27 | attributeName string 28 | } 29 | 30 | // NewGoogleStorageManagedFolderInvalidNameRule returns new rule with default attributes 31 | func NewGoogleStorageManagedFolderInvalidNameRule() *GoogleStorageManagedFolderInvalidNameRule { 32 | return &GoogleStorageManagedFolderInvalidNameRule{ 33 | resourceType: "google_storage_managed_folder", 34 | attributeName: "name", 35 | } 36 | } 37 | 38 | // Name returns the rule name 39 | func (r *GoogleStorageManagedFolderInvalidNameRule) Name() string { 40 | return "google_storage_managed_folder_invalid_name" 41 | } 42 | 43 | // Enabled returns whether the rule is enabled by default 44 | func (r *GoogleStorageManagedFolderInvalidNameRule) Enabled() bool { 45 | return true 46 | } 47 | 48 | // Severity returns the rule severity 49 | func (r *GoogleStorageManagedFolderInvalidNameRule) Severity() tflint.Severity { 50 | return tflint.ERROR 51 | } 52 | 53 | // Link returns the rule reference link 54 | func (r *GoogleStorageManagedFolderInvalidNameRule) Link() string { 55 | return "" 56 | } 57 | 58 | // Check checks the pattern is valid 59 | func (r *GoogleStorageManagedFolderInvalidNameRule) Check(runner tflint.Runner) error { 60 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 61 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 62 | }, nil) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | for _, resource := range resources.Blocks { 68 | attribute, exists := resource.Body.Attributes[r.attributeName] 69 | if !exists { 70 | continue 71 | } 72 | 73 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 74 | validateFunc := validateRegexp(`/$`) 75 | 76 | _, errors := validateFunc(val, r.attributeName) 77 | for _, err := range errors { 78 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 79 | return err 80 | } 81 | } 82 | return nil 83 | }, nil) 84 | if err != nil { 85 | return err 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /rules/magicmodules/google_tags_tag_key_invalid_purpose.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleTagsTagKeyInvalidPurposeRule checks the pattern is valid 24 | type GoogleTagsTagKeyInvalidPurposeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleTagsTagKeyInvalidPurposeRule returns new rule with default attributes 32 | func NewGoogleTagsTagKeyInvalidPurposeRule() *GoogleTagsTagKeyInvalidPurposeRule { 33 | return &GoogleTagsTagKeyInvalidPurposeRule{ 34 | resourceType: "google_tags_tag_key", 35 | attributeName: "purpose", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleTagsTagKeyInvalidPurposeRule) Name() string { 41 | return "google_tags_tag_key_invalid_purpose" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleTagsTagKeyInvalidPurposeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleTagsTagKeyInvalidPurposeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleTagsTagKeyInvalidPurposeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleTagsTagKeyInvalidPurposeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"GCE_FIREWALL", ""}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/magicmodules/google_vmwareengine_network_invalid_type.go: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // 3 | // *** AUTO GENERATED CODE *** Type: MMv1 *** 4 | // 5 | // ---------------------------------------------------------------------------- 6 | // 7 | // This file is automatically generated by Magic Modules and manual 8 | // changes will be clobbered when the file is regenerated. 9 | // 10 | // Please read more about how to change this file in 11 | // .github/CONTRIBUTING.md. 12 | // 13 | // ---------------------------------------------------------------------------- 14 | 15 | package magicmodules 16 | 17 | import ( 18 | "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" 19 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 20 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 21 | ) 22 | 23 | // GoogleVmwareengineNetworkInvalidTypeRule checks the pattern is valid 24 | type GoogleVmwareengineNetworkInvalidTypeRule struct { 25 | tflint.DefaultRule 26 | 27 | resourceType string 28 | attributeName string 29 | } 30 | 31 | // NewGoogleVmwareengineNetworkInvalidTypeRule returns new rule with default attributes 32 | func NewGoogleVmwareengineNetworkInvalidTypeRule() *GoogleVmwareengineNetworkInvalidTypeRule { 33 | return &GoogleVmwareengineNetworkInvalidTypeRule{ 34 | resourceType: "google_vmwareengine_network", 35 | attributeName: "type", 36 | } 37 | } 38 | 39 | // Name returns the rule name 40 | func (r *GoogleVmwareengineNetworkInvalidTypeRule) Name() string { 41 | return "google_vmwareengine_network_invalid_type" 42 | } 43 | 44 | // Enabled returns whether the rule is enabled by default 45 | func (r *GoogleVmwareengineNetworkInvalidTypeRule) Enabled() bool { 46 | return true 47 | } 48 | 49 | // Severity returns the rule severity 50 | func (r *GoogleVmwareengineNetworkInvalidTypeRule) Severity() tflint.Severity { 51 | return tflint.ERROR 52 | } 53 | 54 | // Link returns the rule reference link 55 | func (r *GoogleVmwareengineNetworkInvalidTypeRule) Link() string { 56 | return "" 57 | } 58 | 59 | // Check checks the pattern is valid 60 | func (r *GoogleVmwareengineNetworkInvalidTypeRule) Check(runner tflint.Runner) error { 61 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 62 | Attributes: []hclext.AttributeSchema{{Name: r.attributeName}}, 63 | }, nil) 64 | if err != nil { 65 | return err 66 | } 67 | 68 | for _, resource := range resources.Blocks { 69 | attribute, exists := resource.Body.Attributes[r.attributeName] 70 | if !exists { 71 | continue 72 | } 73 | 74 | err := runner.EvaluateExpr(attribute.Expr, func(val string) error { 75 | validateFunc := validation.StringInSlice([]string{"LEGACY", "STANDARD"}, false) 76 | 77 | _, errors := validateFunc(val, r.attributeName) 78 | for _, err := range errors { 79 | if err := runner.EmitIssue(r, err.Error(), attribute.Expr.Range()); err != nil { 80 | return err 81 | } 82 | } 83 | return nil 84 | }, nil) 85 | if err != nil { 86 | return err 87 | } 88 | } 89 | 90 | return nil 91 | } 92 | -------------------------------------------------------------------------------- /rules/provider.go: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 5 | "github.com/terraform-linters/tflint-ruleset-google/rules/api" 6 | "github.com/terraform-linters/tflint-ruleset-google/rules/magicmodules" 7 | ) 8 | 9 | var manualRules = []tflint.Rule{ 10 | NewGoogleComposerEnvironmentInvalidMachineTypeRule(), 11 | NewGoogleComputeInstanceInvalidMachineTypeRule(), 12 | NewGoogleComputeReservationInvalidMachineTypeRule(), 13 | NewGoogleComputeInstanceTemplateInvalidMachineTypeRule(), 14 | NewGoogleContainerClusterInvalidMachineTypeRule(), 15 | NewGoogleContainerNodePoolInvalidMachineTypeRule(), 16 | NewGoogleDataflowJobInvalidMachineTypeRule(), 17 | NewGoogleComputeResourcePolicyInvalidNameRule(), 18 | NewGoogleProjectIamMemberInvalidMemberRule(), 19 | NewGoogleProjectIamAuditConfigInvalidMemberRule(), 20 | NewGoogleProjectIamBindingInvalidMemberRule(), 21 | NewGoogleProjectIamPolicyInvalidMemberRule(), 22 | } 23 | 24 | // Rules is a list of all rules 25 | var Rules []tflint.Rule 26 | 27 | func init() { 28 | Rules = append(Rules, manualRules...) 29 | Rules = append(Rules, magicmodules.Rules...) 30 | Rules = append(Rules, api.Rules...) 31 | } 32 | -------------------------------------------------------------------------------- /rules/rule.go.tmpl: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "github.com/terraform-linters/tflint-plugin-sdk/hclext" 5 | "github.com/terraform-linters/tflint-plugin-sdk/tflint" 6 | "github.com/terraform-linters/tflint-ruleset-google/project" 7 | ) 8 | 9 | // TODO: Write the rule's description here 10 | // {{ .RuleNameCC }}Rule checks ... 11 | type {{ .RuleNameCC }}Rule struct { 12 | tflint.DefaultRule 13 | 14 | resourceType string 15 | attributeName string 16 | } 17 | 18 | // New{{ .RuleNameCC }}Rule returns new rule with default attributes 19 | func New{{ .RuleNameCC }}Rule() *{{ .RuleNameCC }}Rule { 20 | return &{{ .RuleNameCC }}Rule{ 21 | // TODO: Write resource type and attribute name here 22 | resourceType: "...", 23 | attributeName: "...", 24 | } 25 | } 26 | 27 | // Name returns the rule name 28 | func (r *{{ .RuleNameCC }}Rule) Name() string { 29 | return "{{ .RuleName }}" 30 | } 31 | 32 | // Enabled returns whether the rule is enabled by default 33 | func (r *{{ .RuleNameCC }}Rule) Enabled() bool { 34 | // TODO: Determine whether the rule is enabled by default 35 | return true 36 | } 37 | 38 | // Severity returns the rule severity 39 | func (r *{{ .RuleNameCC }}Rule) Severity() tflint.Severity { 40 | // TODO: Determine the rule's severiry 41 | return tflint.ERROR 42 | } 43 | 44 | // Link returns the rule reference link 45 | func (r *{{ .RuleNameCC }}Rule) Link() string { 46 | // TODO: If the rule is so trivial that no documentation is needed, return "" instead. 47 | return project.ReferenceLink(r.Name()) 48 | } 49 | 50 | // TODO: Write the details of the inspection 51 | // Check checks ... 52 | func (r *{{ .RuleNameCC }}Rule) Check(runner tflint.Runner) error { 53 | // TODO: Write the implementation here. See this documentation for what tflint.Runner can do. 54 | // https://pkg.go.dev/github.com/terraform-linters/tflint-plugin-sdk/tflint#Runner 55 | 56 | resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ 57 | Attributes: []hclext.AttributeSchema{ 58 | {Name: r.attributeName}, 59 | }, 60 | }, nil) 61 | if err != nil { 62 | return err 63 | } 64 | 65 | for _, resource := range resources.Blocks { 66 | attribute, exists := resource.Body.Attributes[r.attributeName] 67 | if !exists { 68 | continue 69 | } 70 | 71 | err := runner.EvaluateExpr(attribute.Expr, func (val string) error { 72 | if val == "" { 73 | runner.EmitIssue( 74 | r, 75 | "TODO", 76 | attribute.Expr.Range(), 77 | ) 78 | } 79 | return nil 80 | }, nil) 81 | if err != nil { 82 | return err 83 | } 84 | } 85 | 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /rules/rule_test.go.tmpl: -------------------------------------------------------------------------------- 1 | package rules 2 | 3 | import ( 4 | "testing" 5 | 6 | hcl "github.com/hashicorp/hcl/v2" 7 | "github.com/terraform-linters/tflint-plugin-sdk/helper" 8 | ) 9 | 10 | func Test_{{ .RuleNameCC }}(t *testing.T) { 11 | cases := []struct { 12 | Name string 13 | Content string 14 | Expected helper.Issues 15 | }{ 16 | { 17 | Name: "basic", 18 | Content: ` 19 | resource "null_resource" "null" { 20 | } 21 | `, 22 | Expected: helper.Issues{ 23 | { 24 | Rule: New{{ .RuleNameCC }}Rule(), 25 | Message: "TODO", 26 | Range: hcl.Range{ 27 | Filename: "resource.tf", 28 | Start: hcl.Pos{Line: 0, Column: 0}, 29 | End: hcl.Pos{Line: 0, Column: 0}, 30 | }, 31 | }, 32 | }, 33 | }, 34 | } 35 | 36 | rule := New{{ .RuleNameCC }}Rule() 37 | 38 | for _, tc := range cases { 39 | runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content}) 40 | 41 | if err := rule.Check(runner); err != nil { 42 | t.Fatalf("Unexpected error occurred: %s", err) 43 | } 44 | 45 | helper.AssertIssues(t, tc.Expected, runner.Issues) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Automation tools 2 | 3 | This directory contains scripts for automating various operations. 4 | 5 | ## Magic Modules 6 | 7 | [Magic Modules](https://github.com/GoogleCloudPlatform/magic-modules) is a tool used to autogenerate Terraform Provider for GCP. We have [forked this project](https://github.com/terraform-linters/magic-modules) to allow the validation to automatically generate rules for TFLint. 8 | 9 | See the README for how to use this module. You can generate rules with the command like the following: 10 | 11 | ```console 12 | $ bundle exec compiler -a --force tflint -v ga -e terraform -o $GOPATH/src/github.com/terraform-linters/tflint-ruleset-google/rules/magicmodules 13 | ``` 14 | -------------------------------------------------------------------------------- /tools/release/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/terraform-linters/tflint-ruleset-google/tools/release 2 | 3 | go 1.24.0 4 | 5 | require ( 6 | github.com/google/go-github/v69 v69.2.0 7 | github.com/hashicorp/go-version v1.7.0 8 | golang.org/x/oauth2 v0.28.0 9 | ) 10 | 11 | require github.com/google/go-querystring v1.1.0 // indirect 12 | -------------------------------------------------------------------------------- /tools/release/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 2 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 3 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 4 | github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE= 5 | github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM= 6 | github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= 7 | github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 8 | github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= 9 | github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= 10 | golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= 11 | golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 12 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 13 | -------------------------------------------------------------------------------- /tools/release/release-note.md: -------------------------------------------------------------------------------- 1 | ## What's Changed 2 | 3 | ### Enhancements 4 | * Update Magic Modules by @github-actions in https://github.com/terraform-linters/tflint-ruleset-google/pull/405 5 | 6 | ### Chores 7 | * Fix broken GitHub Actions badge by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/399 8 | * Enable Dependabot auto-merge by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/400 9 | * Bump github.com/google/go-cmp from 0.6.0 to 0.7.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/394 10 | * Bump actions/attest-build-provenance from 1 to 2 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/397 11 | * Bump github.com/hashicorp/terraform-plugin-sdk/v2 from 2.34.0 to 2.36.1 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/395 12 | * Bump google.golang.org/api from 0.201.0 to 0.223.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/398 13 | * Add make release for release automation by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/401 14 | * Automating Magic Modules Updates by GitHub Actions by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/402 15 | * Install goimports for Magic Modules update by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/403 16 | * Update submodules in automated maintenance action by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/404 17 | * Bump google.golang.org/api from 0.223.0 to 0.224.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/406 18 | * Bump golang.org/x/net from 0.35.0 to 0.36.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/407 19 | * Pin GitHub Action versions by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/408 20 | * Bump actions/setup-go from 5.3.0 to 5.4.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/409 21 | * Bump google.golang.org/api from 0.224.0 to 0.227.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/410 22 | * Bump google.golang.org/api from 0.227.0 to 0.228.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/411 23 | * Bump goreleaser/goreleaser-action from 6.2.1 to 6.3.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/412 24 | * Bump google.golang.org/api from 0.228.0 to 0.229.0 by @dependabot in https://github.com/terraform-linters/tflint-ruleset-google/pull/414 25 | * Go 1.24.2 by @wata727 in https://github.com/terraform-linters/tflint-ruleset-google/pull/415 26 | 27 | ## New Contributors 28 | * @github-actions made their first contribution in https://github.com/terraform-linters/tflint-ruleset-google/pull/405 29 | 30 | **Full Changelog**: https://github.com/terraform-linters/tflint-ruleset-google/compare/v0.31.0...v0.32.0 31 | --------------------------------------------------------------------------------