tfmcp 0.1.9

Terraform Model Context Protocol Tool - A CLI tool to manage Terraform through MCP
Documentation
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct TerraformAnalysis {
    pub project_directory: String,
    pub file_count: usize,
    pub resources: Vec<TerraformResource>,
    pub variables: Vec<TerraformVariable>,
    pub outputs: Vec<TerraformOutput>,
    pub providers: Vec<TerraformProvider>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TerraformResource {
    pub resource_type: String,
    pub name: String,
    pub file: String,
    pub provider: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct TerraformPlan {
    pub changes: TerraformChanges,
    pub raw_output: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct TerraformChanges {
    pub add: usize,
    pub change: usize,
    pub destroy: usize,
}

#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct TerraformState {
    pub resources: Vec<TerraformStateResource>,
    pub version: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct TerraformStateResource {
    pub name: String,
    pub type_: String,
    pub provider: String,
    pub instances: Vec<TerraformResourceInstance>,
}

#[derive(Debug, Serialize, Deserialize)]
#[allow(dead_code)]
pub struct TerraformResourceInstance {
    pub id: String,
    pub attributes: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TerraformValidateOutput {
    pub valid: bool,
    pub error_count: i32,
    pub warning_count: i32,
    pub diagnostics: Vec<TerraformDiagnostic>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TerraformDiagnostic {
    pub severity: String,
    pub summary: String,
    pub detail: Option<String>,
    pub range: Option<DiagnosticRange>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DiagnosticRange {
    pub filename: String,
    pub start: Position,
    pub end: Position,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Position {
    pub line: i32,
    pub column: i32,
    pub byte: i32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DetailedValidationResult {
    pub valid: bool,
    pub error_count: i32,
    pub warning_count: i32,
    pub diagnostics: Vec<TerraformDiagnostic>,
    pub additional_warnings: Vec<String>,
    pub suggestions: Vec<String>,
    pub checked_files: usize,
    /// Future Architect guideline compliance checks
    pub guideline_checks: Option<GuidelineCheckResult>,
}

/// Results from Future Architect Terraform guideline compliance checks
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct GuidelineCheckResult {
    /// Overall compliance score (0-100)
    pub compliance_score: u8,
    /// Variables missing type definition
    pub variables_missing_type: Vec<String>,
    /// Variables missing description
    pub variables_missing_description: Vec<String>,
    /// Outputs missing description
    pub outputs_missing_description: Vec<String>,
    /// Resources using count instead of for_each (not for 0/1 toggle)
    pub count_instead_of_foreach: Vec<CountUsageWarning>,
    /// Variables using 'any' type (discouraged)
    pub any_type_usage: Vec<String>,
    /// Providers missing version constraint
    pub providers_missing_version: Vec<String>,
    /// Resources missing default_tags (AWS)
    pub missing_default_tags: bool,
    /// Detected hardcoded secrets
    pub hardcoded_secrets: Vec<SecretDetection>,
    /// Resources missing lifecycle prevent_destroy for critical resources
    pub missing_lifecycle_protection: Vec<String>,
}

/// Warning for count usage that should be for_each
#[derive(Debug, Serialize, Deserialize)]
pub struct CountUsageWarning {
    pub resource_name: String,
    pub resource_type: String,
    pub suggestion: String,
}

/// Detected potential secret in code
#[derive(Debug, Serialize, Deserialize)]
pub struct SecretDetection {
    pub file: String,
    pub line: usize,
    pub pattern: String,
    pub severity: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TerraformVariable {
    pub name: String,
    pub description: Option<String>,
    pub type_: Option<String>,
    pub default: Option<serde_json::Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TerraformOutput {
    pub name: String,
    pub description: Option<String>,
    pub value: Option<serde_json::Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TerraformProvider {
    pub name: String,
    pub version: Option<String>,
}

// ==================== Module Health Analysis Models ====================
// Based on the whitebox approach to Infrastructure as Code
// Reference: "インフラコードはホワイトボックス的利用が必要"

/// Module health analysis result
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleHealthAnalysis {
    pub module_path: String,
    pub metrics: ModuleMetrics,
    pub health_score: u8, // 0-100
    pub issues: Vec<ModuleIssue>,
    pub recommendations: Vec<String>,
    pub cohesion_analysis: CohesionAnalysis,
    pub coupling_analysis: CouplingAnalysis,
}

/// Quantitative metrics for module analysis
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleMetrics {
    pub variable_count: usize,
    pub output_count: usize,
    pub resource_count: usize,
    pub resource_type_count: usize, // Number of distinct resource types
    pub provider_count: usize,
    pub data_source_count: usize,
    pub local_count: usize,
    pub module_call_count: usize, // Number of module blocks
    pub file_count: usize,
    pub lines_of_code: usize,
    pub hierarchy_depth: usize, // Depth of nested modules
    pub variables_with_defaults: usize,
    pub variables_without_description: usize,
}

/// Issue severity levels
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum IssueSeverity {
    Critical,
    Warning,
    Info,
}

/// Module issue detected during analysis
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleIssue {
    pub severity: IssueSeverity,
    pub category: IssueCategory,
    pub message: String,
    pub file: Option<String>,
    pub line: Option<usize>,
}

/// Categories of module issues
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum IssueCategory {
    LogicalCohesion,      // Too many unrelated resource types
    ExcessiveVariables,   // Too many variables exposed
    DeepHierarchy,        // Too many nested module levels
    MissingDocumentation, // Variables/outputs without descriptions
    ControlCoupling,      // Excessive conditional logic
    ModelCoupling,        // Internal model exposed through variables
    NamingConvention,     // Poor file/resource naming
    PublicModuleRisk,     // Using public registry modules without wrappers
}

/// Cohesion type analysis (based on software engineering principles)
#[derive(Debug, Serialize, Deserialize)]
pub struct CohesionAnalysis {
    pub cohesion_type: CohesionType,
    pub score: u8, // 0-100, higher is better
    pub resource_type_groups: Vec<ResourceTypeGroup>,
    pub explanation: String,
}

/// Types of module cohesion
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CohesionType {
    Functional,      // Best: Single, well-defined purpose
    Sequential,      // Good: Output of one feeds into another
    Communicational, // OK: Operates on same data
    Procedural,      // Weak: Steps that must happen in order
    Temporal,        // Weak: Things that happen at the same time
    Logical,         // Poor: Only related by category (e.g., "network things")
    Coincidental,    // Worst: No meaningful relationship
}

/// Group of related resource types
#[derive(Debug, Serialize, Deserialize)]
pub struct ResourceTypeGroup {
    pub name: String,
    pub resource_types: Vec<String>,
    pub resource_count: usize,
}

/// Coupling analysis between modules
#[derive(Debug, Serialize, Deserialize)]
pub struct CouplingAnalysis {
    pub coupling_type: CouplingType,
    pub score: u8, // 0-100, lower coupling is better
    pub dependencies: Vec<ModuleDependency>,
    pub explanation: String,
}

/// Types of module coupling
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CouplingType {
    Data,    // Best: Only data passed between modules
    Stamp,   // OK: Structured data passed
    Control, // Poor: Flags/conditionals control behavior
    Common,  // Poor: Shared global data
    Content, // Worst: One module modifies another's internal data
}

/// Dependency information between modules
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleDependency {
    pub source_module: String,
    pub target_module: String,
    pub dependency_type: String,
    pub variables_passed: Vec<String>,
}

/// Resource dependency graph for visualization
#[derive(Debug, Serialize, Deserialize)]
pub struct ResourceDependencyGraph {
    pub nodes: Vec<ResourceNode>,
    pub edges: Vec<ResourceEdge>,
    pub module_boundaries: Vec<ModuleBoundary>,
}

/// A node in the resource dependency graph
#[derive(Debug, Serialize, Deserialize)]
pub struct ResourceNode {
    pub id: String,
    pub resource_type: String,
    pub resource_name: String,
    pub module_path: String,
    pub file: String,
    pub provider: String,
}

/// An edge in the resource dependency graph
#[derive(Debug, Serialize, Deserialize)]
pub struct ResourceEdge {
    pub source: String,
    pub target: String,
    pub dependency_type: DependencyType,
    pub attribute: Option<String>,
}

/// Types of resource dependencies
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DependencyType {
    Explicit,     // depends_on
    Implicit,     // Reference to another resource
    DataSource,   // Data source reference
    ModuleOutput, // Reference to module output
}

/// Module boundary for visualization
#[derive(Debug, Serialize, Deserialize)]
pub struct ModuleBoundary {
    pub module_path: String,
    pub resource_ids: Vec<String>,
}

/// Refactoring suggestion
#[derive(Debug, Serialize, Deserialize)]
pub struct RefactoringSuggestion {
    pub suggestion_type: RefactoringType,
    pub priority: IssueSeverity,
    pub description: String,
    pub affected_resources: Vec<String>,
    pub proposed_structure: Option<ProposedModuleStructure>,
    pub migration_steps: Vec<String>,
}

/// Types of refactoring suggestions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RefactoringType {
    SplitModule,           // Extract resources to new module
    MergeModules,          // Combine small modules
    ExtractSubmodule,      // Create submodule for related resources
    FlattenHierarchy,      // Reduce nesting depth
    WrapPublicModule,      // Create wrapper for public module
    RemoveUnusedVariables, // Clean up unused inputs
    AddDescriptions,       // Document variables/outputs
}

/// Proposed new module structure
#[derive(Debug, Serialize, Deserialize)]
pub struct ProposedModuleStructure {
    pub module_name: String,
    pub resources: Vec<String>,
    pub variables: Vec<String>,
    pub outputs: Vec<String>,
}