Metadata-Version: 2.4
Name: ssm-run-cli
Version: 0.1.2
Summary: Run commands/scripts on EC2 via AWS SSM Run Command
Project-URL: Homepage, https://wwwin-github.cisco.com/skumble/ssm-cli
Project-URL: Repository, https://wwwin-github.cisco.com/skumble/ssm-cli
Project-URL: Issues, https://wwwin-github.cisco.com/skumble/ssm-cli/issues
Keywords: aws,ssm,ec2,run-command,cli
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: System Administrators
Classifier: Environment :: Console
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: boto3>=1.28

# ssm-run-cli

Run shell commands or scripts on EC2 instances via AWS Systems Manager (SSM) Run Command.

PyPI package name: `ssm-run-cli`  
Installed command: `ssm-run-cli`

## Features

- Resolve targets by:
  - EC2 instance ID (`i-...`)
  - Name tag / hostname / FQDN
  - Private/Public IPv4
- Target expansion:
  - `myserver{600..605}`
- Run:
  - Inline command (`-- "uptime"`)
  - Local script file (`--file ./cmd.sh`)
- SSM online filtering (with opt-out)
- Parallel result collection for faster output fetch
- Optional S3-backed full output (`--s3-bucket`) to avoid API truncation
- Debug mode to inspect exact remote command (`--debug-command`)

## Installation

### From PyPI

```bash
pip install ssm-run-cli
```

### Upgrade

```bash
pip install --upgrade ssm-run-cli
```

### From source (repo)

```bash
git clone https://wwwin-github.cisco.com/skumble/ssm-cli.git
cd ssm-cli
pip install .
```

## Requirements

- Python 3.9+
- AWS credentials configured (profile/role/SSO)
- IAM permissions for:
  - `ec2:DescribeInstances`
  - `ssm:DescribeInstanceInformation`
  - `ssm:SendCommand`
  - `ssm:ListCommandInvocations`
  - `ssm:GetCommandInvocation`
- If using `--s3-bucket`:
  - instance role needs `s3:PutObject`
  - caller credentials need `s3:GetObject`

## CLI Usage

```bash
ssm-run-cli [OPTIONS] <target> [<target> ...] -- "<command>"
ssm-run-cli [OPTIONS] <target> [<target> ...] --file ./script.sh
ssm-run-cli [OPTIONS] -f hosts.txt -- "<command>"
ssm-run-cli [OPTIONS] -f hosts.txt --file ./script.sh
```

## Options

- `-r, --region <region>` AWS region (supports shortcuts: `use1`, `euw1`, `aps1`)
- `-f, --hosts-file <file>` Read targets from file (one per line, `#` comments allowed)
- `--file <script.sh>` Run local script file instead of inline command
- `--batch-size <1..50>` Instances per `SendCommand` call
- `--timeout-seconds <sec>` Global wait timeout
- `--poll-interval <sec>` Poll interval
- `--no-online-filter` Skip SSM online filtering
- `--only-failed` Print output only for failed instances
- `--s3-bucket <bucket>` Store/fetch full output from S3
- `--s3-prefix <prefix>` Optional S3 key prefix
- `--debug-command` Print decoded command and exit
- `--max-workers <n>` Parallel workers for output fetching
- `-h, --help` Help

## Examples

### 1. Simple inline command

```bash
ssm-run-cli --region euw1 myserver{600..605} -- 'uptime'
```

### 2. From hosts file

```bash
ssm-run-cli -r use1 -f hosts.txt -- 'df -h'
```

### 3. Complex command using script file (recommended)

```bash
echo 'sudo grep -m1 "HUMIDITY" /mnt/logs/webex-api-streams.log' > cmd.sh
ssm-run-cli --region euw1 myserver{600..605} --file cmd.sh
```

### 4. Long-running command with higher timeout

```bash
ssm-run-cli --region euw1 --timeout-seconds 300 myserver{600..605} --file cmd.sh
```

### 5. Avoid output truncation using S3

```bash
ssm-run-cli --region euw1 --s3-bucket my-ssm-logs myserver{600..605} --file cmd.sh
```

### 6. Validate what would run (no execution)

```bash
ssm-run-cli --region euw1 --debug-command myserver601 -- 'uptime'
```

## Notes on Quoting

For commands with JSON, nested quotes, pipes, or shell special characters, prefer `--file` instead of inline `-- "<command>"`.
This avoids local shell quoting issues before the command reaches the instance.

## Exit Behavior

- Returns non-zero on major failures (for example: AWS API errors, no valid targets).
- Prints per-instance status and summary with success/failed/skipped/timeout counts.

## Development

Build wheel/sdist:

```bash
python -m pip install --upgrade build
python -m build
```

Install local build:

```bash
python -m pip install --force-reinstall dist/*.whl
```

## Publishing (maintainers)

```bash
python -m pip install --upgrade twine
python -m twine check dist/*
python -m twine upload dist/*
```

## Versioning and Release Notes

- Versioning follows Semantic Versioning (`MAJOR.MINOR.PATCH`).
- Update version in `pyproject.toml` before each release.
- Add release notes in `CHANGELOG.md`.

### First Public Release Checklist

1. Confirm package name availability on PyPI (`ssm-run-cli`).
2. Verify metadata in `pyproject.toml` (name/version/urls/classifiers).
3. Build artifacts:

```bash
python -m pip install --upgrade build
python -m build
python -m twine check dist/*
```

4. Test local install from built wheel:

```bash
python -m pip install --force-reinstall dist/*.whl
ssm-run-cli --help
```

5. Publish:

```bash
python -m twine upload dist/*
```

6. Tag release in git (example):

```bash
git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0
```

## License

Add your project license here (for example: MIT, Apache-2.0, or internal Cisco license).
