Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Support creating droplets from snapshots (clone workflow)

オープン
#52 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

@gwpl がすでに取り組んでいます。

2026年3月23日 から。

  • #53 @gwpl による — オープン

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
65/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
静か
技術スタック
python
領域
api, cli, cloud

調査の方向性

create コマンドと、wake で使用されている既存の api.create_droplet_from_snapshot() メソッドから始めます。create が cloud-init をどのようにレンダリング、送信、監視しているかを追跡し、アクティブ状態になるまでの待機、SSH 設定、プロジェクト割り当ては維持したまま、それらの手順をスキップするようにスナップショットのパスを実装します。--from-snapshot で cloud-init なしの droplet が作成され、--image と相互排他的になれば完了です。

索引モデルが issue の本文から書いたものです。

説明

AI Agent with Greg: We wanted to snapshot a perfectly configured droplet and spin up 10 clones from it — like a sysadmin photocopier. Turns out dropkit's create command always injects cloud-init, which re-runs on the snapshot and causes chaos (user creation fails, .zshrc gets overwritten, unconditional reboot). Time to teach dropkit the art of cloning. 🧬🖨️

Use Case

Snapshot → Clone N droplets — a common workflow for:

  • Spinning up pre-configured build/test environments
  • Creating identical workshop/training machines
  • Scaling a known-good configuration quickly
# The dream:
dropkit create my-worker-1 --from-snapshot 12345678 --size s-4vcpu-8gb
dropkit create my-worker-2 --from-snapshot 12345678 --size s-4vcpu-8gb
# ... or even:
for i in $(seq 1 10); do
  dropkit create "worker-$i" --from-snapshot 12345678
done

The Problem

dropkit create always renders and sends cloud-init user_data to the DigitalOcean API. When creating from a snapshot:

  1. Cloud-init re-runs — DO assigns a new droplet ID → instance-ID mismatch → cloud-init treats it as first boot
  2. The template is NOT idempotent — several critical issues:
    • users: directive fails or is skipped if user already exists
    • write_files: overwrites .zshrc (loses user customizations)
    • runcmd: ends with unconditional reboot
    • git config --global resets any user-modified values

Cloud-init is fundamentally a provisioning tool, not an idempotent configuration manager. Making the template fully idempotent is possible but would be a significant effort touching every directive.

Current State

Component Exists? Notes
api.create_droplet_from_snapshot() ✅ Yes Used by wake command, takes snapshot ID, no user_data
dropkit create --image ✅ Yes But always sends cloud-init; image is a slug, not snapshot ID
dropkit wake ✅ Yes Restores from hibernation snapshot only (expects dropkit-<name> naming + metadata tags)
Snapshot-based create without cloud-init ❌ No The missing piece

Proposed Approaches

Option A: --from-snapshot <id> flag on create (Recommended — simplest)

Add a --from-snapshot flag to dropkit create that:

  • Uses api.create_droplet_from_snapshot() instead of api.create_droplet()
  • Skips cloud-init rendering and sending entirely
  • Skips cloud-init completion monitoring
  • Still performs: wait for active, SSH config setup, project assignment
  • Optionally still runs Tailscale setup (snapshot may not have it)
# Mutually exclusive with --image
@app.command()
def create(
    ...
    from_snapshot: int | None = typer.Option(
        None, "--from-snapshot",
        help="Create from snapshot ID (skips cloud-init)"
    ),
    ...
):

Pros: Minimal change (~30 lines), reuses existing API method, clear intent
Cons: Slightly different code path within create, snapshot ID must be known by user

Option B: --no-cloud-init flag (More general)

A flag to skip cloud-init regardless of image source. Combined with --image <snapshot-id>:

dropkit create my-box --image 12345678 --no-cloud-init

Pros: More composable, works with any image scenario
Cons: Two flags needed, easy to forget --no-cloud-init with a snapshot (leading to the reboot-of-doom)

Option C: Make cloud-init template idempotent (Long-term)

Refactor the template to be safe for re-execution:

  • Guard user creation: id {{ username }} || useradd ...
  • Use marker files: [ -f /etc/dropkit/.initialized ] || ...
  • Remove unconditional reboot; use cloud-init-per instance
  • Make write_files conditional or append-only

Pros: dropkit create --image <snapshot-id> "just works"
Cons: Significant template refactor, hard to test all edge cases, changes behavior for fresh installs too

Option D: New dropkit clone command (Most ergonomic)

Dedicated command for the clone workflow:

dropkit clone my-worker --from my-golden-image --count 5 --size s-4vcpu-8gb

Pros: Best UX, can add clone-specific features (auto-naming, parallel creation)
Cons: Largest scope, new command surface area

Recommendation

Start with Option A (--from-snapshot). It's the smallest change, reuses existing infrastructure, and solves the immediate need. Options C and D can follow later as enhancements.

Happy to implement whichever approach the team prefers!

🤖 Generated with Claude Code — your AI that learned the hard way that cloud-init and snapshots are like mixing sudo with optimism

主要言語
Python
スター
129
フォーク
14
平均マージ
5日 9時間
マージ済み PR(30日)
4

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

  • Dockerfile・Docker Compose ファイルなし
  • プルリクエストのテンプレートなし
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

trailofbits/dropkit のほかの issue

trailofbits/dropkit の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。