Skip to content
Open
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
2 changes: 1 addition & 1 deletion dropkit/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def create_droplet(
name: Droplet name
region: Region slug (e.g., 'nyc3')
size: Size slug (e.g., 's-2vcpu-4gb')
image: Image slug (e.g., 'ubuntu-25-04-x64')
image: Image slug (e.g., 'ubuntu-25-10-x64')
user_data: Cloud-init user data
tags: List of tags to apply
ssh_keys: List of SSH key IDs for root access (optional)
Expand Down
11 changes: 8 additions & 3 deletions dropkit/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
from cryptography.hazmat.primitives import serialization
from pydantic import BaseModel, ConfigDict, Field, field_validator

# Default slugs for droplet creation
DEFAULT_REGION = "nyc3"
DEFAULT_SIZE = "s-2vcpu-4gb"
DEFAULT_IMAGE = "ubuntu-25-10-x64"


class DigitalOceanConfig(BaseModel):
"""DigitalOcean API configuration."""
Expand Down Expand Up @@ -296,9 +301,9 @@ def create_default_config(
self,
token: str,
username: str, # noqa: ARG002 - kept for API compatibility, username derived from DO API
region: str = "nyc3",
size: str = "s-2vcpu-4gb",
image: str = "ubuntu-25-04-x64",
region: str = DEFAULT_REGION,
size: str = DEFAULT_SIZE,
image: str = DEFAULT_IMAGE,
ssh_keys: list[str] | None = None,
ssh_key_ids: list[int] | None = None,
extra_tags: list[str] | None = None,
Expand Down
14 changes: 7 additions & 7 deletions dropkit/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from dropkit.api import DigitalOceanAPI, DigitalOceanAPIError
from dropkit.cloudinit import render_cloud_init
from dropkit.config import Config, DropkitConfig
from dropkit.config import DEFAULT_IMAGE, DEFAULT_REGION, DEFAULT_SIZE, Config, DropkitConfig
from dropkit.lock import requires_lock
from dropkit.ssh_config import (
add_ssh_host,
Expand Down Expand Up @@ -1686,42 +1686,42 @@ def init(
if regions:
region = prompt_with_help(
"Default region",
default="nyc3",
default=DEFAULT_REGION,
display_func=display_regions,
data=regions,
)
else:
region = Prompt.ask(
"[cyan]Default region[/cyan]",
default="nyc3",
default=DEFAULT_REGION,
)

# Prompt for default size
if sizes:
size = prompt_with_help(
"Default droplet size",
default="s-2vcpu-4gb",
default=DEFAULT_SIZE,
display_func=display_sizes,
data=sizes,
)
else:
size = Prompt.ask(
"[cyan]Default droplet size[/cyan]",
default="s-2vcpu-4gb",
default=DEFAULT_SIZE,
)

# Prompt for default image
if images:
image = prompt_with_help(
"Default image",
default="ubuntu-25-04-x64",
default=DEFAULT_IMAGE,
display_func=display_images,
data=images,
)
else:
image = Prompt.ask(
"[cyan]Default image[/cyan]",
default="ubuntu-25-04-x64",
default=DEFAULT_IMAGE,
)

# Prompt for extra tags
Expand Down
57 changes: 30 additions & 27 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from pydantic import ValidationError

from dropkit.config import (
DEFAULT_IMAGE,
DEFAULT_REGION,
DEFAULT_SIZE,
CloudInitConfig,
Config,
DefaultsConfig,
Expand All @@ -32,9 +35,9 @@ def valid_config_dict():
"api_base": "https://api.digitalocean.com/v2",
},
"defaults": {
"region": "nyc3",
"size": "s-2vcpu-4gb",
"image": "ubuntu-25-04-x64",
"region": DEFAULT_REGION,
"size": DEFAULT_SIZE,
"image": DEFAULT_IMAGE,
"extra_tags": ["custom-tag"],
},
"cloudinit": {
Expand Down Expand Up @@ -96,59 +99,59 @@ class TestDefaultsConfig:
def test_valid_config(self):
"""Test valid defaults config."""
config = DefaultsConfig(
region="nyc3",
size="s-2vcpu-4gb",
image="ubuntu-25-04-x64",
region=DEFAULT_REGION,
size=DEFAULT_SIZE,
image=DEFAULT_IMAGE,
extra_tags=["tag1", "tag2"],
)
assert config.region == "nyc3"
assert config.size == "s-2vcpu-4gb"
assert config.image == "ubuntu-25-04-x64"
assert config.region == DEFAULT_REGION
assert config.size == DEFAULT_SIZE
assert config.image == DEFAULT_IMAGE
assert config.extra_tags == ["tag1", "tag2"]

def test_empty_region_fails(self):
"""Test that empty region fails validation."""
with pytest.raises(ValidationError):
DefaultsConfig(
region="",
size="s-2vcpu-4gb",
image="ubuntu-25-04-x64",
size=DEFAULT_SIZE,
image=DEFAULT_IMAGE,
)

def test_empty_size_fails(self):
"""Test that empty size fails validation."""
with pytest.raises(ValidationError):
DefaultsConfig(
region="nyc3",
region=DEFAULT_REGION,
size="",
image="ubuntu-25-04-x64",
image=DEFAULT_IMAGE,
)

def test_empty_image_fails(self):
"""Test that empty image fails validation."""
with pytest.raises(ValidationError):
DefaultsConfig(
region="nyc3",
size="s-2vcpu-4gb",
region=DEFAULT_REGION,
size=DEFAULT_SIZE,
image="",
)

def test_empty_extra_tags_allowed(self):
"""Test that empty extra_tags list is allowed."""
config = DefaultsConfig(
region="nyc3",
size="s-2vcpu-4gb",
image="ubuntu-25-04-x64",
region=DEFAULT_REGION,
size=DEFAULT_SIZE,
image=DEFAULT_IMAGE,
extra_tags=[],
)
assert config.extra_tags == []

def test_missing_extra_tags_defaults_to_empty(self):
"""Test that missing extra_tags defaults to empty list."""
config = DefaultsConfig(
region="nyc3",
size="s-2vcpu-4gb",
image="ubuntu-25-04-x64",
region=DEFAULT_REGION,
size=DEFAULT_SIZE,
image=DEFAULT_IMAGE,
)
assert config.extra_tags == []

Expand Down Expand Up @@ -236,7 +239,7 @@ def test_valid_full_config(self, valid_config_dict):
"""Test valid full configuration."""
config = DropkitConfig(**valid_config_dict)
assert config.digitalocean.token == "dop_v1_test_token_12345"
assert config.defaults.region == "nyc3"
assert config.defaults.region == DEFAULT_REGION
assert config.cloudinit.ssh_keys[0] == "/home/user/.ssh/id_ed25519.pub"
assert config.ssh.auto_update is True

Expand Down Expand Up @@ -295,17 +298,17 @@ def test_create_default_config(self):
config.create_default_config(
token="test_token",
username="testuser",
region="nyc3",
size="s-2vcpu-4gb",
image="ubuntu-25-04-x64",
region=DEFAULT_REGION,
size=DEFAULT_SIZE,
image=DEFAULT_IMAGE,
ssh_keys=["/path/to/key.pub"],
ssh_key_ids=[12345],
extra_tags=["tag1", "tag2"],
)

# Should be able to access config now
assert config.config.digitalocean.token == "test_token"
assert config.config.defaults.region == "nyc3"
assert config.config.defaults.region == DEFAULT_REGION
assert config.config.defaults.extra_tags == ["tag1", "tag2"]
assert config.config.cloudinit.ssh_key_ids == [12345]

Expand Down Expand Up @@ -345,7 +348,7 @@ def test_save_and_load_config(self, temp_config_dir, valid_config_dict, monkeypa
username="testuser",
region="sfo3",
size="s-1vcpu-1gb",
image="ubuntu-25-04-x64",
image=DEFAULT_IMAGE,
ssh_keys=["/path/to/key.pub"],
ssh_key_ids=[98765],
extra_tags=["test_tag"],
Expand Down
Loading