Skip to content

Latest commit

 

History

History
319 lines (263 loc) · 7.14 KB

File metadata and controls

319 lines (263 loc) · 7.14 KB

Output Format Guide

This guide explains the JSON output structure produced by the energy-dependency-inspector.

JSON Structure Overview

The energy-dependency-inspector outputs a JSON object where each key represents a detector (package manager) and contains information about detected dependencies:

{
  "source": { ... },
  "dpkg": { ... },
  "pip": { ... },
  "composer": { ... },
  "pecl": { ... },
  "npm": { ... }
}

Source Information

When analyzing environments, the source section provides metadata about where the scan was performed:

{
  "source": {
    "type": "container",
    "name": "nginx-container",
    "image": "nginx:latest",
    "hash": "sha256:2cd1d97f893f..."
  }
}

Fields

  • type - Source type ("container" for Docker containers, "host" for host scans)
  • name - Container name (for container sources)
  • image - Docker image used (for container sources)
  • hash - Container image hash (for container sources)

Package Manager Sections

Each package manager detector produces a section with this structure:

System-Scoped Packages

System-wide package managers (dpkg, apk) output:

{
  "dpkg": {
    "scope": "system",
    "dependencies": {
      "package-name": {
        "version": "1.2.3 amd64",
        "hash": "abc123..."
      },
      "another-package": {
        "version": "2.0.0 amd64",
        "hash": "def456..."
      }
    }
  }
}

Project-Scoped Packages

Project-specific package managers (pip, npm, composer) output:

{
  "pip": {
    "scope": "project",
    "location": "/path/to/venv/lib/python3.12/site-packages",
    "hash": "def456...",
    "dependencies": {
      "package-name": {
        "version": "1.2.3"
      },
      "another-package": {
        "version": "2.0.0"
      }
    }
  }
}

Mixed-Scope Packages (Multi-Location Detection)

When a detector finds packages in multiple locations (e.g. pip, npm, and composer support this):

{
  "pip": {
    "scope": "mixed",
    "locations": {
      "/root/venv/lib/python3.12/site-packages": {
        "scope": "project",
        "hash": "abc123...",
        "dependencies": {
          "venv-package": {
            "version": "1.0.0"
          }
        }
      },
      "/usr/local/lib/python3.12/dist-packages": {
        "scope": "system",
        "hash": "def456...",
        "dependencies": {
          "system-package": {
            "version": "2.0.0"
          }
        }
      }
    }
  }
}

Field Definitions

Common Fields

  • scope - Either "system", "project", or "mixed"

    • system: System-wide packages affecting the entire environment
    • project: Project-specific packages in a local scope
    • mixed: Packages from multiple locations
  • dependencies - Object containing all detected packages

    • Keys: Package names
    • Values: Objects with version and optional hash information

Project-Scoped Fields

  • location - Absolute path where project dependencies are installed
  • hash - Hash of the dependency location/environment
  • python_version - Python runtime version reported by the pip detector, when available
  • node_version - Node.js runtime version reported by the npm detector, when available
  • php_version - PHP runtime version reported by the Composer detector, when available

Package Fields

  • version - Package version string (format varies by package manager)
  • hash - Package-specific hash (when available)

Hash Strategy

The energy-dependency-inspector implements a tiered hash strategy:

Tier 1: Authentic Hashes

Package managers that provide authentic hashes use them directly:

{
  "package-name": {
    "version": "1.2.3",
    "hash": "sha256:authentic-hash-from-package-manager"
  }
}

Tier 2: Location-Based Hashes

For project-scoped package managers, a location hash is provided:

{
  "pip": {
    "scope": "project",
    "location": "/path/to/venv/lib/python3.12/site-packages",
    "hash": "sha256:location-based-hash",
    "dependencies": { ... }
  }
}

Tier 3: No Hashes

Some package managers don't provide hash information:

{
  "package-name": {
    "version": "1.2.3"
  }
}

Complete Example

Here's a complete example showing multiple package managers:

{
  "source": {
    "type": "container",
    "name": "web-app",
    "image": "python:3.12-slim",
    "hash": "sha256:a1b2c3d4e5f6..."
  },
  "dpkg": {
    "scope": "system",
    "dependencies": {
      "libc6": {
        "version": "2.36-9+deb12u4 amd64",
        "hash": "abc123..."
      },
      "python3": {
        "version": "3.11.2-1+b1 amd64",
        "hash": "def456..."
      }
    }
  },
  "pip": {
    "scope": "project",
    "location": "/app/venv/lib/python3.12/site-packages",
    "hash": "sha256:xyz789...",
    "dependencies": {
      "flask": {
        "version": "2.3.3"
      },
      "requests": {
        "version": "2.31.0"
      }
    }
  },
  "composer": {
    "scope": "project",
    "php_version": "PHP 8.3.7 (cli)",
    "location": "/app/vendor",
    "hash": "sha256:composer123...",
    "dependencies": {
      "monolog/monolog": {
        "version": "3.5.0"
      },
      "guzzlehttp/guzzle": {
        "version": "7.9.2"
      }
    }
  },
  "pecl": {
    "scope": "system",
    "php_version": "PHP 8.3.7 (cli)",
    "dependencies": {
      "apcu": {
        "version": "5.1.24"
      }
    }
  },
  "npm": {
    "scope": "project",
    "node_version": "v22.11.0",
    "location": "/app/node_modules",
    "hash": "sha256:npm456...",
    "dependencies": {
      "express": {
        "version": "4.18.2"
      },
      "lodash": {
        "version": "4.17.21"
      }
    }
  }
}

Processing the Output

Python Processing Example

import json
import energy_dependency_inspector

# Get dependencies as dictionary
deps = energy_dependency_inspector.resolve_dependencies_as_dict("host")

# Process each detector
for detector_name, result in deps.items():
    if detector_name.startswith("_"):
        continue  # Skip metadata sections

    print(f"\n{detector_name.upper()} ({result['scope']} scope):")

    if "location" in result:
        print(f"  Location: {result['location']}")

    dependencies = result.get("dependencies", {})
    print(f"  Packages: {len(dependencies)}")

    for package, info in dependencies.items():
        version = info.get("version", "unknown")
        has_hash = "hash" in info
        print(f"    {package}: {version} {'✓' if has_hash else ''}")

Filtering Examples

# Get only system packages
system_packages = {k: v for k, v in deps.items()
                  if not k.startswith("_") and v.get("scope") == "system"}

# Get only project packages
project_packages = {k: v for k, v in deps.items()
                   if not k.startswith("_") and v.get("scope") == "project"}

# Handle mixed-scope packages (pip multi-location)
def count_dependencies(result):
    if result.get("scope") == "mixed":
        return sum(len(loc.get("dependencies", {})) for loc in result.get("locations", {}).values())
    return len(result.get("dependencies", {}))

# Count total packages (including mixed-scope)
total = sum(count_dependencies(v) for k, v in deps.items() if not k.startswith("_"))