Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ junos-ops <subcommand> [options] [hostname ...]
| `ls [-l]` | リモートパスのファイル一覧 |
| `show COMMAND [--retry N]` / `show -f FILE` | 任意の CLI コマンド(またはコマンドファイル)を複数ホストで実行 |
| `check [--connect\|--local\|--remote\|--all] [--model M]` | Pre-flight チェック: NETCONF 疎通・ローカル/リモート firmware ハッシュ |
| `config -f FILE` | set コマンドファイルを適用(`--confirm` / `--timeout` / `--no-confirm` / `--intent-rollback` / `--health-check` / `--no-health-check` の詳細は [docs/config.md](docs/config.md) を参照) |
| `config -f FILE` | set コマンドファイルを適用(`--confirm` / `--timeout` / `--no-confirm` / `--no-commit` / `--health-check` / `--no-health-check` の詳細は [docs/config.md](docs/config.md) を参照) |
| `rsi` | RSI/SCF を並列収集 |
| (なし) | デバイスファクト(device facts)を表示 |

Expand Down Expand Up @@ -337,7 +337,7 @@ flowchart TD

`config` サブコマンドは安全なコミットフローを採用しています。`commit confirmed`(自動ロールバックタイマー) → **ヘルスチェック** → `commit`(確定)の順に実行します。ヘルスチェックが失敗した場合、最終 `commit` を送信せず、タイマー満了時に JUNOS が自動的にロールバックします。

ヘルスチェック(`uptime`、ping、CLI コマンド)、commit confirmed フロー、`--no-confirm`、`--intent-rollback`、並列実行などの詳細は [docs/config.ja.md](docs/config.ja.md) を参照してください。
ヘルスチェック(`uptime`、ping、CLI コマンド)、commit confirmed フロー、`--no-confirm`、`--no-commit`、並列実行などの詳細は [docs/config.ja.md](docs/config.ja.md) を参照してください。

```
1. dry-run で差分を確認
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ junos-ops <subcommand> [options] [hostname ...]
| `ls [-l]` | List files on the remote path |
| `show COMMAND [--retry N]` / `show -f FILE` | Run an arbitrary CLI command (or file of commands) across devices |
| `check [--connect\|--local\|--remote\|--all] [--model M]` | Pre-flight checks: NETCONF reachability, local/remote firmware hash |
| `config -f FILE` | Push a set command file (see [docs/config.md](docs/config.md) for `--confirm`, `--timeout`, `--no-confirm`, `--intent-rollback`, `--health-check`, `--no-health-check`) |
| `config -f FILE` | Push a set command file (see [docs/config.md](docs/config.md) for `--confirm`, `--timeout`, `--no-confirm`, `--no-commit`, `--health-check`, `--no-health-check`) |
| `rsi` | Collect RSI/SCF in parallel |
| (none) | Show device facts |

Expand Down Expand Up @@ -337,7 +337,7 @@ flowchart TD

The `config` subcommand uses a safe commit flow: `commit confirmed` (auto-rollback timer) → **health check** → `commit` (permanent). If the health check fails, the final `commit` is withheld and JUNOS automatically rolls back when the timer expires.

See [docs/config.md](docs/config.md) for full details including health check options (`uptime`, ping, CLI commands), commit confirmed flow, `--no-confirm`, `--intent-rollback`, and parallel execution.
See [docs/config.md](docs/config.md) for full details including health check options (`uptime`, ping, CLI commands), commit confirmed flow, `--no-confirm`, `--no-commit`, and parallel execution.

```
1. Preview changes with dry-run
Expand Down
8 changes: 4 additions & 4 deletions docs/config.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ flowchart TD
| `--no-health-check` | ヘルスチェックをスキップ |
| `--timeout N` | RPC タイムアウト(秒、デフォルト: 120、config.ini の `timeout` でも設定可能) |
| `--no-confirm` | commit confirmed とヘルスチェックをスキップし直接 commit |
| `--intent-rollback` | commit confirmed を送信するが最終 commit をスキップ(`--confirm` 分後に JUNOS が自動ロールバック) |
| `--no-commit` | commit confirmed を送信するが最終 commit をスキップ(`--confirm` 分後に JUNOS が自動ロールバック) |
| `--workers N` | 並列実行数(デフォルト: 1) |

## ヘルスチェック
Expand Down Expand Up @@ -140,15 +140,15 @@ junos-ops config -f commands.set --no-confirm rt1.example.jp

> **注意:** commit confirmed なしでは自動ロールバックの安全ネットがありません。慎重に使用してください。

## 意図的なロールバック(--intent-rollback
## 意図的なロールバック(--no-commit

`commit confirmed N` を送信するが最終 `commit` を意図的にスキップします。`N` 分後(デフォルト: 1分)に JUNOS が自動ロールバックします。

`request system processes restart` に対応していないプロセスを「設定バウンス」で再起動したい場合に便利です。たとえば、ファームウェアアップグレード後に syslog 転送が止まった EX3400 の回復などに使えます。

```bash
# deactivate syslog; commit confirmed 1 を適用し、1分後に自動ロールバック
junos-ops config -f bounce-syslog.set --intent-rollback rt1.example.jp
junos-ops config -f bounce-syslog.set --no-commit rt1.example.jp
```

`bounce-syslog.set` の例:
Expand All @@ -159,7 +159,7 @@ deactivate system syslog
設定が 1 分間有効になる間に syslog プロセスが再起動し、その後 JUNOS が自動ロールバックします。

**注意事項:**
- `--intent-rollback` と `--no-confirm` は同時に指定できません
- `--no-commit` と `--no-confirm` は同時に指定できません
- ヘルスチェックは実行しません(ロールバックは意図的なものです)
- タイムアウトを延ばしたい場合は `--confirm N` で指定してください

Expand Down
8 changes: 4 additions & 4 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ This means even if a configuration change breaks NETCONF connectivity, the devic
| `--no-health-check` | Skip health check after commit confirmed |
| `--timeout N` | RPC timeout in seconds (default: 120, also configurable via `timeout` in config.ini) |
| `--no-confirm` | Skip commit confirmed and health check, commit directly |
| `--intent-rollback` | Apply with commit confirmed but skip final commit (JUNOS auto-rolls back after `--confirm` minutes) |
| `--no-commit` | Apply with commit confirmed but skip final commit (JUNOS auto-rolls back after `--confirm` minutes) |
| `--workers N` | Parallel execution (default: 1) |

## Health Check
Expand Down Expand Up @@ -140,15 +140,15 @@ junos-ops config -f commands.set --no-confirm rt1.example.jp

> **Warning:** Without commit confirmed, there is no automatic rollback safety net. Use with caution.

## Intentional Rollback (--intent-rollback)
## Intentional Rollback (--no-commit)

Apply configuration with `commit confirmed N` but intentionally skip the final `commit`. JUNOS will automatically roll back after `N` minutes (default: 1).

This is useful when a "configuration bounce" is needed to restart a service that does not support `request system processes restart` — for example, the syslog process on some EX3400 devices after a firmware upgrade.

```bash
# Apply deactivate syslog; commit confirmed 1; then auto-rollback in 1 minute
junos-ops config -f bounce-syslog.set --intent-rollback rt1.example.jp
junos-ops config -f bounce-syslog.set --no-commit rt1.example.jp
```

Example `bounce-syslog.set`:
Expand All @@ -159,7 +159,7 @@ deactivate system syslog
The config will be active for 1 minute (while syslog restarts) then JUNOS rolls it back automatically.

**Notes:**
- `--intent-rollback` and `--no-confirm` are mutually exclusive
- `--no-commit` and `--no-confirm` are mutually exclusive
- No health check is performed (the rollback is intentional)
- Use `--confirm N` to extend the window beyond 1 minute

Expand Down
10 changes: 5 additions & 5 deletions junos_ops/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ def cmd_show(hostname) -> int:

def cmd_config(hostname) -> int:
"""Push set command file to device."""
if getattr(common.args, "intent_rollback", False) and getattr(common.args, "no_confirm", False):
if getattr(common.args, "no_commit", False) and getattr(common.args, "no_confirm", False):
display.print_host_block(
hostname, "\t--intent-rollback and --no-confirm are mutually exclusive"
hostname, "\t--no-commit and --no-confirm are mutually exclusive"
)
return 1
dev = _open_connection(hostname)
Expand Down Expand Up @@ -700,7 +700,7 @@ def _run():
help="skip commit confirmed and health check, commit directly",
)
p_config.add_argument(
"--intent-rollback", dest="intent_rollback", action="store_true",
"--no-commit", dest="no_commit", action="store_true",
help="apply with commit confirmed but skip final commit "
"(JUNOS auto-rolls back after --confirm minutes)",
)
Expand Down Expand Up @@ -834,8 +834,8 @@ def _run():
args.rpc_timeout = None
if not hasattr(args, "no_confirm"):
args.no_confirm = False
if not hasattr(args, "intent_rollback"):
args.intent_rollback = False
if not hasattr(args, "no_commit"):
args.no_commit = False
if not hasattr(args, "check_connect"):
args.check_connect = False
if not hasattr(args, "check_local"):
Expand Down
12 changes: 6 additions & 6 deletions junos_ops/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -1943,7 +1943,7 @@ def load_config(hostname, dev, configfile) -> dict:
health check -> confirm -> unlock.
Commit flow (``--no-confirm``):
lock -> load -> diff -> commit_check -> commit -> unlock.
Commit flow (``--intent-rollback``):
Commit flow (``--no-commit``):
lock -> load -> diff -> commit_check -> commit confirmed ->
unlock. (JUNOS auto-rolls back after timeout; no health check.)
On error, rollback + unlock for cleanup.
Expand All @@ -1963,10 +1963,10 @@ def load_config(hostname, dev, configfile) -> dict:
- ``no_changes`` (bool): True iff ``diff is None`` — shortcut
for the common happy path.
- ``commit_mode`` (str): ``"confirmed"`` | ``"no_confirm"`` |
``"intent_rollback"`` | ``"dry_run"`` | ``"none"`` (no commit
``"no_commit"`` | ``"dry_run"`` | ``"none"`` (no commit
happened, e.g. lock failed or no_changes).
- ``confirm_timeout`` (int | None): confirm timeout in minutes
for ``commit_mode in ("confirmed", "intent_rollback")``,
for ``commit_mode in ("confirmed", "no_commit")``,
else None.
- ``health_check`` (dict): health-check outcome, with keys:

Expand Down Expand Up @@ -2066,17 +2066,17 @@ def _step(action: str, message: str, **extra) -> None:
_step("commit_check", "\tcommit check passed")

no_confirm = getattr(common.args, "no_confirm", False)
intent_rollback = getattr(common.args, "intent_rollback", False)
no_commit = getattr(common.args, "no_commit", False)
if no_confirm:
# Direct commit (skip commit confirmed)
cu.commit()
result["commit_mode"] = "no_confirm"
_step("commit", "\tcommit applied (no confirm)")
elif intent_rollback:
elif no_commit:
# commit confirmed without final commit — JUNOS auto-rolls back
confirm_timeout = getattr(common.args, "confirm_timeout", 1)
result["confirm_timeout"] = confirm_timeout
result["commit_mode"] = "intent_rollback"
result["commit_mode"] = "no_commit"
cu.commit(confirm=confirm_timeout)
_step(
"commit_confirmed",
Expand Down
28 changes: 14 additions & 14 deletions tests/test_config_push.py
Original file line number Diff line number Diff line change
Expand Up @@ -965,11 +965,11 @@ def test_confirm_default_still_works(self, junos_upgrade, mock_args, mock_config


class TestIntentRollback:
"""--intent-rollback オプションのテスト"""
"""--no-commit オプションのテスト"""

def test_intent_rollback_skips_final_commit(self, junos_upgrade, mock_args, mock_config):
"""--intent-rollback: commit confirmed のみで最終 commit を送らない"""
mock_args.intent_rollback = True
def test_no_commit_skips_final_commit(self, junos_upgrade, mock_args, mock_config):
"""--no-commit: commit confirmed のみで最終 commit を送らない"""
mock_args.no_commit = True
mock_args.confirm_timeout = 1
dev = MagicMock()
mock_cu = MagicMock()
Expand All @@ -980,15 +980,15 @@ def test_intent_rollback_skips_final_commit(self, junos_upgrade, mock_args, mock
):
result = junos_upgrade.load_config("test-host", dev, "commands.set")
assert result["ok"] is True
assert result["commit_mode"] == "intent_rollback"
assert result["commit_mode"] == "no_commit"
# commit は1回だけ(confirm= あり)、最終 commit は呼ばれない
mock_cu.commit.assert_called_once_with(confirm=1)
# ヘルスチェックは実行されない
dev.cli.assert_not_called()

def test_intent_rollback_message_contains_rollback(self, junos_upgrade, mock_args, mock_config):
"""--intent-rollback: steps に auto-rollback の旨が含まれる"""
mock_args.intent_rollback = True
def test_no_commit_message_contains_rollback(self, junos_upgrade, mock_args, mock_config):
"""--no-commit: steps に auto-rollback の旨が含まれる"""
mock_args.no_commit = True
mock_args.confirm_timeout = 1
dev = MagicMock()
mock_cu = MagicMock()
Expand All @@ -1001,9 +1001,9 @@ def test_intent_rollback_message_contains_rollback(self, junos_upgrade, mock_arg
messages = " ".join(s.get("message", "") for s in result["steps"])
assert "auto-rollback" in messages

def test_intent_rollback_confirm_timeout(self, junos_upgrade, mock_args, mock_config):
"""--intent-rollback --confirm 2: confirm=2 で commit される"""
mock_args.intent_rollback = True
def test_no_commit_confirm_timeout(self, junos_upgrade, mock_args, mock_config):
"""--no-commit --confirm 2: confirm=2 で commit される"""
mock_args.no_commit = True
mock_args.confirm_timeout = 2
dev = MagicMock()
mock_cu = MagicMock()
Expand All @@ -1016,9 +1016,9 @@ def test_intent_rollback_confirm_timeout(self, junos_upgrade, mock_args, mock_co
assert result["confirm_timeout"] == 2
mock_cu.commit.assert_called_once_with(confirm=2)

def test_intent_rollback_and_no_confirm_mutually_exclusive(self, mock_args, mock_config):
"""--intent-rollback + --no-confirm は同時指定不可(exit code 1)"""
mock_args.intent_rollback = True
def test_no_commit_and_no_confirm_mutually_exclusive(self, mock_args, mock_config):
"""--no-commit + --no-confirm は同時指定不可(exit code 1)"""
mock_args.no_commit = True
mock_args.no_confirm = True
with patch("junos_ops.display.print_host_block"):
result = cli.cmd_config("rt1.example.jp")
Expand Down