| name | containdb |
| description | Development rules and patterns for ContainDB CLI tool |
| version | 1.0.0 |
| tags | ["golang","docker","cli","cross-platform","containers"] |
| author | ContainDB Team |
ContainDB Development Skill
Project Identity
ContainDB - Database Container Management Made Simple
- Go (Golang) ≥1.18
- Cross-platform CLI tool (Linux, macOS, Windows)
- Docker-based database management
- Distribution: npm package + native binaries
Mandatory Workflows
After EVERY Code Change
go build -o containdb src/Core/main.go
go test ./...
go fmt ./...
go vet ./...
For ANY Feature Change
- Test on Linux, macOS, Windows
- Update documentation (README, DESIGN, INSTALLATION)
- Update CHANGELOG.md
- Verify auto-rollback works
- Test error scenarios
Definition of "Done"
A task is NOT complete until ALL are true:
- ✅ Code follows Go standards
- ✅
go build passes
- ✅
go test ./... passes
- ✅
go vet ./... passes
- ✅ Works on Linux, macOS, Windows
- ✅ Documentation updated
- ✅ Backward compatible
- ✅ Auto-rollback implemented
- ✅ Error messages clear and actionable
Architecture
Layered Design
CLI Entry Point (src/Core/main.go)
↓
Base Operations (src/base/)
├── Create.go - Database creation
├── Remove.go - Resource cleanup
├── Export.go - docker-compose export
└── Import.go - docker-compose import
↓
Docker Abstraction (src/Docker/)
├── Container.go - Container operations
├── Volume.go - Volume management
└── Network.go - Network operations
↓
Docker Engine
Module Structure
src/
├── Core/ # main.go - CLI entry point
├── base/ # Business logic
├── Docker/ # Docker SDK wrapper
└── tools/ # Management tools (phpMyAdmin, etc.)
Scripts/
├── BinBuilder.sh # Multi-platform builder
├── PackageBuilder.sh # Debian package builder
└── installer.sh # Linux installer
Go Standards (STRICT)
Error Handling - Descriptive Context
if err != nil {
return fmt.Errorf("failed to create container '%s': %w", name, err)
}
if err != nil {
return err
}
Type Safety - Use Structs
type ContainerOptions struct {
Name string
Image string
Port int
RestartPolicy string
Volumes map[string]string
Environment map[string]string
}
func CreateContainer(opts ContainerOptions) error { }
func CreateContainer(name, image string, port int, restart string, vols map[string]string, env map[string]string) error { }
Package Organization
package docker
import (
"github.com/docker/docker/client"
)
func CreateContainer(opts ContainerOptions) error { }
package main
func CreateContainer() error { }
func RemoveContainer() error { }
func ParseConfig() error { }
Key Patterns
1. Auto-Rollback on Failure (CRITICAL)
func CreateDatabase(opts Options) error {
created := []string{}
defer func() {
if err != nil {
log.Println("Error occurred, rolling back...")
for _, resourceID := range created {
if err := cleanup(resourceID); err != nil {
log.Printf("Failed to cleanup %s: %v", resourceID, err)
}
}
}
}()
container, err := CreateContainer(opts)
if err != nil {
return fmt.Errorf("container creation failed: %w", err)
}
created = append(created, container.ID)
volume, err := CreateVolume(opts.VolumeName)
if err != nil {
return fmt.Errorf("volume creation failed: %w", err)
}
created = append(created, volume.Name)
return nil
}
2. Interactive Prompts for Sensitive Data
import "github.com/manifoldco/promptui"
prompt := promptui.Prompt{
Label: "Enter database password",
Mask: '*',
}
password, err := prompt.Run()
password := "password123"
3. Docker SDK Usage (NOT Commands)
import (
"github.com/docker/docker/client"
"github.com/docker/docker/api/types/container"
)
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return fmt.Errorf("failed to create Docker client: %w", err)
}
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: "mysql:8.0",
}, nil, nil, nil, "my-mysql")
cmd := exec.Command("docker", "run", "-d", "--name", "mysql", "mysql:8.0")
4. Cross-Platform Path Handling
import "path/filepath"
configPath := filepath.Join(homeDir, ".containdb", "config.yaml")
configPath := homeDir + "/.containdb/config.yaml"
Security Standards
1. Credential Handling
log.Printf("Creating database with user: %s", username)
log.Printf("Creating database with password: %s", password)
password := promptSecure("Enter password:")
const DefaultPassword = "admin123"
2. Input Validation
func ValidatePort(port int) error {
if port < 1024 || port > 65535 {
return fmt.Errorf("port must be between 1024 and 65535")
}
return nil
}
func ValidateContainerName(name string) error {
if !regexp.MustCompile(`^[a-zA-Z0-9_-]+$`).MatchString(name) {
return fmt.Errorf("name must contain only alphanumeric, dash, or underscore")
}
return nil
}
3. Privilege Management
if os.Geteuid() != 0 {
log.Println("WARNING: ContainDB requires root/sudo privileges for Docker operations")
log.Println("Please run: sudo containdb")
os.Exit(1)
}
Documentation Requirements
Update when features change:
-
README.md
- Installation instructions
- Usage examples
- Feature list
- Troubleshooting
-
DESIGN.md
- Architecture diagrams
- Technical decisions
- Module descriptions
-
INSTALLATION.md
- Platform-specific guides
- Prerequisites
- Verification steps
-
CHANGELOG.md
- Version changes
- New features
- Bug fixes
-
Code Comments
func CreateDatabase(opts DatabaseOptions) error
Testing Requirements
Unit Tests
func TestCreateContainer(t *testing.T) {
tests := []struct {
name string
opts ContainerOptions
wantErr bool
}{
{"valid MySQL", ContainerOptions{Name: "mysql", Image: "mysql:8.0"}, false},
{"invalid name", ContainerOptions{Name: "my sql", Image: "mysql:8.0"}, true},
{"missing image", ContainerOptions{Name: "mysql"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := CreateContainer(tt.opts)
if (err != nil) != tt.wantErr {
t.Errorf("CreateContainer() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
Integration Tests
- Test full CLI workflows
- Test with real Docker containers
- Test auto-rollback scenarios
- Test on Linux, macOS, Windows
Build & Distribution
Multi-Platform Build
./Scripts/BinBuilder.sh
Debian Package
./Scripts/PackageBuilder.sh
npm Distribution
cd npm/
npm run build
npm publish
Anti-Patterns (FORBIDDEN)
❌ Platform-specific code without fallbacks
❌ Hardcoded credentials or secrets
❌ Direct docker command execution (use SDK)
❌ Breaking changes to CLI interface
❌ Missing error handling
❌ Incomplete auto-rollback
❌ Skipping cross-platform testing
❌ Generic error messages
❌ Missing documentation updates
❌ Logging sensitive data
Workflow Guidelines
When Adding Database Support
- Read
DESIGN.md architecture section
- Add database config to
src/base/Create.go
- Add default ports, images, environment vars
- Implement auto-rollback for new resources
- Add management tool support (if available)
- Update README with usage examples
- Test on all platforms
- Update CHANGELOG.md
When Fixing Bugs
- Write failing test that reproduces bug
- Fix the bug
- Verify test passes
- Test on all platforms
- Check for similar issues elsewhere
- Document in CHANGELOG.md
When Refactoring
- Ensure backward compatibility
- Run all tests before and after
- Test on all platforms
- Update architecture docs if structure changes
- Maintain CLI interface
Success Criteria
Every task must meet ALL:
- ✅ Builds successfully (
go build)
- ✅ Tests pass (
go test ./...)
- ✅ Lints pass (
go vet ./..., go fmt ./...)
- ✅ Works on Linux, macOS, Windows
- ✅ Documentation updated (README, DESIGN, INSTALLATION)
- ✅ Backward compatible (CLI interface unchanged)
- ✅ Auto-rollback implemented and tested
- ✅ Clear, actionable error messages
- ✅ No hardcoded credentials
- ✅ Input validation implemented