Skip to content

Commit 7cc0959

Browse files
authored
Merge pull request #10 from onkernel/fix/wait-for-image-ready
fix(run): wait for image to be ready before creating instance
2 parents 9d7cf81 + fdd215c commit 7cc0959

File tree

2 files changed

+76
-4
lines changed

2 files changed

+76
-4
lines changed

pkg/cmd/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ func init() {
9898
&instancesList,
9999
&instancesPutInStandby,
100100
&instancesRestoreFromStandby,
101+
&instancesLogs,
102+
&instancesDelete,
101103
},
102104
},
103105
{

pkg/cmd/run.go

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"os"
77
"strings"
8+
"time"
89

910
"github.com/onkernel/hypeman-go"
1011
"github.com/onkernel/hypeman-go/option"
@@ -65,25 +66,29 @@ func handleRun(ctx context.Context, cmd *cli.Command) error {
6566

6667
client := hypeman.NewClient(getDefaultRequestOptions(cmd)...)
6768

68-
// Check if image exists, pull if not
69-
_, err := client.Images.Get(ctx, image)
69+
// Check if image exists and is ready
70+
imgInfo, err := client.Images.Get(ctx, image)
7071
if err != nil {
7172
// Image not found, try to pull it
7273
var apiErr *hypeman.Error
7374
if ok := isNotFoundError(err, &apiErr); ok {
7475
fmt.Fprintf(os.Stderr, "Image not found locally. Pulling %s...\n", image)
75-
_, err = client.Images.New(ctx, hypeman.ImageNewParams{
76+
imgInfo, err = client.Images.New(ctx, hypeman.ImageNewParams{
7677
Name: image,
7778
})
7879
if err != nil {
7980
return fmt.Errorf("failed to pull image: %w", err)
8081
}
81-
fmt.Fprintf(os.Stderr, "Pull complete.\n")
8282
} else {
8383
return fmt.Errorf("failed to check image: %w", err)
8484
}
8585
}
8686

87+
// Wait for image to be ready (build is asynchronous)
88+
if err := waitForImageReady(ctx, &client, image, imgInfo); err != nil {
89+
return err
90+
}
91+
8792
// Generate name if not provided
8893
name := cmd.String("name")
8994
if name == "" {
@@ -139,3 +144,68 @@ func isNotFoundError(err error, target **hypeman.Error) bool {
139144
return false
140145
}
141146

147+
// waitForImageReady polls image status until it becomes ready or failed
148+
func waitForImageReady(ctx context.Context, client *hypeman.Client, imageName string, img *hypeman.Image) error {
149+
if img.Status == hypeman.ImageStatusReady {
150+
return nil
151+
}
152+
if img.Status == hypeman.ImageStatusFailed {
153+
if img.Error != "" {
154+
return fmt.Errorf("image build failed: %s", img.Error)
155+
}
156+
return fmt.Errorf("image build failed")
157+
}
158+
159+
// Poll until ready
160+
ticker := time.NewTicker(1 * time.Second)
161+
defer ticker.Stop()
162+
163+
// Show initial status
164+
showImageStatus(img)
165+
166+
for {
167+
select {
168+
case <-ctx.Done():
169+
return ctx.Err()
170+
case <-ticker.C:
171+
updated, err := client.Images.Get(ctx, imageName)
172+
if err != nil {
173+
return fmt.Errorf("failed to check image status: %w", err)
174+
}
175+
176+
// Show status update if changed
177+
if updated.Status != img.Status {
178+
showImageStatus(updated)
179+
img = updated
180+
}
181+
182+
switch updated.Status {
183+
case hypeman.ImageStatusReady:
184+
return nil
185+
case hypeman.ImageStatusFailed:
186+
if updated.Error != "" {
187+
return fmt.Errorf("image build failed: %s", updated.Error)
188+
}
189+
return fmt.Errorf("image build failed")
190+
}
191+
}
192+
}
193+
}
194+
195+
// showImageStatus prints image build status to stderr
196+
func showImageStatus(img *hypeman.Image) {
197+
switch img.Status {
198+
case hypeman.ImageStatusPending:
199+
if img.QueuePosition > 0 {
200+
fmt.Fprintf(os.Stderr, "Queued (position %d)...\n", img.QueuePosition)
201+
} else {
202+
fmt.Fprintf(os.Stderr, "Queued...\n")
203+
}
204+
case hypeman.ImageStatusPulling:
205+
fmt.Fprintf(os.Stderr, "Pulling image...\n")
206+
case hypeman.ImageStatusConverting:
207+
fmt.Fprintf(os.Stderr, "Converting to disk image...\n")
208+
case hypeman.ImageStatusReady:
209+
fmt.Fprintf(os.Stderr, "Image ready.\n")
210+
}
211+
}

0 commit comments

Comments
 (0)