Skip to content

Commit 73901d3

Browse files
Add ability to create free services (#27)
1 parent 02d1784 commit 73901d3

File tree

11 files changed

+595
-175
lines changed

11 files changed

+595
-175
lines changed

internal/tiger/api/types.go

Lines changed: 20 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/tiger/cmd/service.go

Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -217,52 +217,62 @@ func buildServiceListCmd() *cobra.Command {
217217
// serviceCreateCmd represents the create command under service
218218
func buildServiceCreateCmd() *cobra.Command {
219219
var createServiceName string
220-
var createServiceType string
220+
var createAddons []string
221221
var createRegionCode string
222222
var createCpuMillis int
223-
var createMemoryGbs float64
223+
var createMemoryGbs int
224224
var createReplicaCount int
225225
var createNoWait bool
226226
var createWaitTimeout time.Duration
227227
var createNoSetDefault bool
228+
var createFree bool
228229

229230
cmd := &cobra.Command{
230231
Use: "create",
231232
Short: "Create a new database service",
232233
Long: `Create a new database service in the current project.
233234
234-
By default, the newly created service will be set as your default service for future
235+
By default, the newly created service will be set as your default service for future
235236
commands. Use --no-set-default to prevent this behavior.
236237
237238
Examples:
238239
# Create a TimescaleDB service with all defaults (0.5 CPU, 2GB, us-east-1, auto-generated name)
239240
tiger service create
240-
241-
# Create a TimescaleDB service with custom name
242-
tiger service create --name my-db
243241
244-
# Create a PostgreSQL service with more resources (waits for ready by default)
245-
tiger service create --name prod-db --type postgres --cpu 2000 --memory 8 --replicas 2
242+
# Create a free TimescaleDB service
243+
tiger service create --name free-db --free
244+
245+
# Create a TimescaleDB service with AI add-ons
246+
tiger service create --name hybrid-db --addons time-series,ai
247+
248+
# Create a plain Postgres service
249+
tiger service create --name postgres-db --addons none
250+
251+
# Create a service with more resources (waits for ready by default)
252+
tiger service create --name resources-db --cpu 2000 --memory 8 --replicas 2
246253
247254
# Create service in a different region
248-
tiger service create --name eu-db --region google-europe-west1
255+
tiger service create --name eu-db --region eu-central-1
249256
250257
# Create service without setting it as default
251258
tiger service create --name temp-db --no-set-default
252259
253260
# Create service specifying only CPU (memory will be auto-configured to 8GB)
254-
tiger service create --name auto-memory --type postgres --cpu 2000
261+
tiger service create --name auto-memory --cpu 2000
255262
256263
# Create service specifying only memory (CPU will be auto-configured to 4000m)
257-
tiger service create --name auto-cpu --type timescaledb --memory 16
264+
tiger service create --name auto-cpu --memory 16
258265
259266
# Create service without waiting for completion
260-
tiger service create --name quick-db --type postgres --cpu 1000 --memory 4 --replicas 1 --no-wait
267+
tiger service create --name quick-db --no-wait
261268
262269
# Create service with custom wait timeout
263-
tiger service create --name patient-db --type timescaledb --cpu 2000 --memory 8 --replicas 2 --wait-timeout 1h
270+
tiger service create --name patient-db --wait-timeout 1h
271+
272+
Free Tier:
273+
When using --free, resource flags (--cpu, --memory, --replicas, --addons, --region) cannot be specified
264274
265-
Allowed CPU/Memory Configurations:
275+
Allowed CPU/Memory Configurations (non-free services):
266276
0.5 CPU (500m) / 2GB | 1 CPU (1000m) / 4GB | 2 CPU (2000m) / 8GB | 4 CPU (4000m) / 16GB
267277
8 CPU (8000m) / 32GB | 16 CPU (16000m) / 64GB | 32 CPU (32000m) / 128GB
268278
@@ -283,29 +293,50 @@ Note: You can specify both CPU and memory together, or specify only one (the oth
283293
if createServiceName == "" {
284294
createServiceName = util.GenerateServiceName()
285295
}
286-
if createServiceType == "" {
287-
return fmt.Errorf("service type is required (--type)")
288-
}
289-
if createRegionCode == "" {
290-
return fmt.Errorf("region code cannot be empty (--region)")
291-
}
292-
if createReplicaCount < 0 {
293-
return fmt.Errorf("replica count must be non-negative (--replicas)")
294-
}
295296

296-
// Check which flags were explicitly set
297-
cpuFlagSet := cmd.Flags().Changed("cpu")
298-
memoryFlagSet := cmd.Flags().Changed("memory")
297+
// Validate free tier restrictions
298+
var addons []string
299+
if createFree {
300+
// Check which flags were explicitly set by the user
301+
if cmd.Flags().Changed("addons") {
302+
return fmt.Errorf("--addons cannot be specified with --free")
303+
}
304+
if cmd.Flags().Changed("region") {
305+
return fmt.Errorf("--region cannot be specified with --free")
306+
}
307+
if cmd.Flags().Changed("cpu") {
308+
return fmt.Errorf("--cpu cannot be specified with --free")
309+
}
310+
if cmd.Flags().Changed("memory") {
311+
return fmt.Errorf("--memory cannot be specified with --free")
312+
}
313+
if cmd.Flags().Changed("replicas") {
314+
return fmt.Errorf("--replicas cannot be specified with --free")
315+
}
316+
} else {
317+
// For non-free services, validate addons and resources
318+
addons, err = util.ValidateAddons(createAddons)
319+
if err != nil {
320+
return err
321+
}
322+
if createRegionCode == "" {
323+
return fmt.Errorf("region code cannot be empty (--region)")
324+
}
325+
if createReplicaCount < 0 {
326+
return fmt.Errorf("replica count must be non-negative (--replicas)")
327+
}
299328

300-
// Validate and normalize CPU/Memory configuration
301-
cpuMillis, memoryGbs, err := util.ValidateAndNormalizeCPUMemory(
302-
createCpuMillis, createMemoryGbs, cpuFlagSet, memoryFlagSet,
303-
)
304-
if err != nil {
305-
return err
329+
cpuFlagSet := cmd.Flags().Changed("cpu")
330+
memoryFlagSet := cmd.Flags().Changed("memory")
331+
332+
// Validate and normalize CPU/Memory configuration
333+
createCpuMillis, createMemoryGbs, err = util.ValidateAndNormalizeCPUMemory(
334+
createCpuMillis, createMemoryGbs, cpuFlagSet, memoryFlagSet,
335+
)
336+
if err != nil {
337+
return err
338+
}
306339
}
307-
createCpuMillis = cpuMillis
308-
createMemoryGbs = memoryGbs
309340

310341
// Validate wait timeout (Cobra handles parsing automatically)
311342
if createWaitTimeout <= 0 {
@@ -314,12 +345,6 @@ Note: You can specify both CPU and memory together, or specify only one (the oth
314345

315346
cmd.SilenceUsage = true
316347

317-
// Validate service type
318-
if !util.IsValidServiceType(createServiceType) {
319-
return fmt.Errorf("invalid service type '%s'. Valid types: %s", createServiceType, strings.Join(util.ValidServiceTypes(), ", "))
320-
}
321-
serviceTypeUpper := strings.ToUpper(createServiceType)
322-
323348
// Get API key for authentication
324349
apiKey, err := getAPIKeyForService()
325350
if err != nil {
@@ -334,12 +359,19 @@ Note: You can specify both CPU and memory together, or specify only one (the oth
334359

335360
// Prepare service creation request
336361
serviceCreateReq := api.ServiceCreate{
337-
Name: createServiceName,
338-
ServiceType: api.ServiceType(serviceTypeUpper),
339-
RegionCode: createRegionCode,
340-
ReplicaCount: createReplicaCount,
341-
CpuMillis: createCpuMillis,
342-
MemoryGbs: float32(createMemoryGbs),
362+
Name: createServiceName,
363+
}
364+
365+
// Set free flag if specified
366+
if createFree {
367+
serviceCreateReq.Free = &createFree
368+
serviceCreateReq.RegionCode = "us-east-1"
369+
} else {
370+
serviceCreateReq.Addons = util.ConvertAddonsToAPI(addons)
371+
serviceCreateReq.RegionCode = createRegionCode
372+
serviceCreateReq.ReplicaCount = createReplicaCount
373+
serviceCreateReq.CpuMillis = createCpuMillis
374+
serviceCreateReq.MemoryGbs = createMemoryGbs
343375
}
344376

345377
// Make API call to create service
@@ -414,14 +446,15 @@ Note: You can specify both CPU and memory together, or specify only one (the oth
414446

415447
// Add flags
416448
cmd.Flags().StringVar(&createServiceName, "name", "", "Service name (auto-generated if not provided)")
417-
cmd.Flags().StringVar(&createServiceType, "type", util.ServiceTypeTimescaleDB, fmt.Sprintf("Service type (%s)", strings.Join(util.ValidServiceTypes(), ", ")))
449+
cmd.Flags().StringSliceVar(&createAddons, "addons", []string{util.AddonTimeSeries}, fmt.Sprintf("Addons to enable (%s, or 'none' for PostgreSQL-only)", strings.Join(util.ValidAddons(), ", ")))
418450
cmd.Flags().StringVar(&createRegionCode, "region", "us-east-1", "Region code")
419451
cmd.Flags().IntVar(&createCpuMillis, "cpu", 500, "CPU allocation in millicores")
420-
cmd.Flags().Float64Var(&createMemoryGbs, "memory", 2.0, "Memory allocation in gigabytes")
452+
cmd.Flags().IntVar(&createMemoryGbs, "memory", 2, "Memory allocation in gigabytes")
421453
cmd.Flags().IntVar(&createReplicaCount, "replicas", 0, "Number of high-availability replicas")
422454
cmd.Flags().BoolVar(&createNoWait, "no-wait", false, "Don't wait for operation to complete")
423455
cmd.Flags().DurationVar(&createWaitTimeout, "wait-timeout", 30*time.Minute, "Wait timeout duration (e.g., 30m, 1h30m, 90s)")
424456
cmd.Flags().BoolVar(&createNoSetDefault, "no-set-default", false, "Don't set this service as the default service")
457+
cmd.Flags().BoolVar(&createFree, "free", false, "Create a free tier service (limitations apply)")
425458

426459
return cmd
427460
}
@@ -607,10 +640,16 @@ func outputServiceTable(cmd *cobra.Command, service api.Service) error {
607640
} else {
608641
table.Append("CPU", fmt.Sprintf("%.1f cores (%dm)", cpuCores, *resource.Spec.CpuMillis))
609642
}
643+
} else {
644+
// CPU is null - this indicates a free tier service
645+
table.Append("CPU", "shared")
610646
}
611647

612648
if resource.Spec.MemoryGbs != nil {
613649
table.Append("Memory", fmt.Sprintf("%d GB", *resource.Spec.MemoryGbs))
650+
} else {
651+
// Memory is null - this indicates a free tier service
652+
table.Append("Memory", "shared")
614653
}
615654
}
616655
}

0 commit comments

Comments
 (0)