Skip to content

Commit a9cf3d6

Browse files
committed
feat/Add OCI Regisrty repo smurf selm
1 parent eeafe45 commit a9cf3d6

File tree

1 file changed

+85
-81
lines changed

1 file changed

+85
-81
lines changed

internal/helm/install.go

Lines changed: 85 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"path/filepath"
7+
"sort"
78
"strings"
89
"time"
910

@@ -139,27 +140,6 @@ func LoadOCIChart(chartRef, version string, settings *cli.EnvSettings, debug boo
139140
return nil, fmt.Errorf("failed to create registry client: %w", err)
140141
}
141142

142-
// Extract chart name and reference
143-
ref := strings.TrimPrefix(chartRef, "oci://")
144-
chartName := filepath.Base(ref)
145-
146-
// Handle tag/version in the reference
147-
var tag string
148-
if idx := strings.LastIndex(chartName, ":"); idx != -1 {
149-
tag = chartName[idx+1:]
150-
chartName = chartName[:idx]
151-
}
152-
153-
// Use provided version if not in the reference
154-
if version != "" {
155-
tag = version
156-
}
157-
158-
// Update the reference with the proper tag
159-
if tag != "" {
160-
chartRef = fmt.Sprintf("oci://%s:%s", strings.TrimSuffix(ref, ":"+tag), tag)
161-
}
162-
163143
// Create action configuration with registry client
164144
actionConfig := &action.Configuration{
165145
RegistryClient: registryClient,
@@ -169,87 +149,111 @@ func LoadOCIChart(chartRef, version string, settings *cli.EnvSettings, debug boo
169149
pull := action.NewPullWithOpts(action.WithConfig(actionConfig))
170150
pull.Settings = settings
171151
pull.Version = version
172-
pull.Untar = true
173-
pull.UntarDir = settings.RepositoryCache
152+
pull.Untar = false // DO NOT untar - we want the .tgz file
153+
pull.DestDir = settings.RepositoryCache
174154

175155
// Run the pull command
176156
fmt.Printf("⬇️ Pulling OCI chart: %s...\n", chartRef)
177-
output, err := pull.Run(chartRef)
157+
downloadedFile, err := pull.Run(chartRef)
178158
if err != nil {
179159
return nil, fmt.Errorf("failed to pull OCI chart: %w", err)
180160
}
181161

182-
if debug {
183-
pterm.Printf("Pull output: %s\n", output)
184-
}
185-
186-
// Parse the output to find the downloaded file
187-
// The output typically looks like: "Pulled: oci://registry/path/chart:tag"
188-
// or gives us the file path
189-
chartPath := ""
190-
if strings.Contains(output, "Pulled:") {
191-
// Extract path from output
192-
parts := strings.Split(output, "Pulled:")
193-
if len(parts) > 1 {
194-
chartPath = strings.TrimSpace(parts[1])
195-
// Remove the OCI prefix if present
196-
chartPath = strings.TrimPrefix(chartPath, "oci://")
197-
}
198-
}
162+
// The downloadedFile path is returned by pull.Run()
163+
// In newer Helm versions, it returns the actual file path
164+
chartPath := downloadedFile
199165

200-
// If we couldn't parse from output, try to find the chart file
201-
if chartPath == "" {
202-
// Look for the chart file in the cache directory
203-
pattern := filepath.Join(settings.RepositoryCache, fmt.Sprintf("%s-*.tgz", chartName))
204-
if version != "" {
205-
pattern = filepath.Join(settings.RepositoryCache, fmt.Sprintf("%s-%s.tgz", chartName, version))
206-
}
207-
208-
matches, err := filepath.Glob(pattern)
209-
if err != nil || len(matches) == 0 {
210-
// Last resort: try to find any .tgz file with chart name
211-
allFiles, _ := os.ReadDir(settings.RepositoryCache)
212-
for _, file := range allFiles {
213-
if strings.Contains(file.Name(), chartName) && strings.HasSuffix(file.Name(), ".tgz") {
214-
chartPath = filepath.Join(settings.RepositoryCache, file.Name())
215-
break
216-
}
217-
}
218-
} else {
219-
chartPath = matches[0]
220-
}
166+
// If the path is not absolute, make it relative to cache dir
167+
if !filepath.IsAbs(chartPath) {
168+
chartPath = filepath.Join(settings.RepositoryCache, chartPath)
221169
}
222170

223-
if chartPath == "" {
224-
// Try direct path construction as fallback
225-
expectedName := chartName
226-
if tag != "" {
227-
expectedName = fmt.Sprintf("%s-%s.tgz", chartName, tag)
171+
// Verify the file exists
172+
if _, err := os.Stat(chartPath); os.IsNotExist(err) {
173+
// Try to find the chart file in the cache directory
174+
foundPath := findChartFileInCache(settings.RepositoryCache, chartRef, debug)
175+
if foundPath != "" {
176+
chartPath = foundPath
228177
} else {
229-
expectedName = fmt.Sprintf("%s.tgz", chartName)
178+
// Debug: list all files in cache
179+
if debug {
180+
listCacheFiles(settings.RepositoryCache)
181+
}
182+
return nil, fmt.Errorf("chart file not found at: %s", chartPath)
230183
}
231-
chartPath = filepath.Join(settings.RepositoryCache, expectedName)
232184
}
233185

234186
if debug {
235-
pterm.Printf("Loading OCI chart from: %s\n", chartPath)
187+
pterm.Printf("OCI chart located at: %s\n", chartPath)
236188
}
237189

238-
// Verify the file exists
239-
if _, err := os.Stat(chartPath); os.IsNotExist(err) {
240-
// List files in cache directory for debugging
241-
if debug {
242-
files, _ := os.ReadDir(settings.RepositoryCache)
243-
pterm.Printf("Files in cache directory:\n")
244-
for _, file := range files {
245-
pterm.Printf(" - %s\n", file.Name())
190+
fmt.Printf("📦 Loading OCI chart into memory...\n")
191+
return loader.Load(chartPath)
192+
}
193+
194+
// Helper function to find chart file in cache
195+
func findChartFileInCache(cacheDir, chartRef string, debug bool) string {
196+
// Extract chart name from OCI reference
197+
ref := strings.TrimPrefix(chartRef, "oci://")
198+
chartName := filepath.Base(ref)
199+
200+
// Remove tag if present
201+
if idx := strings.LastIndex(chartName, ":"); idx != -1 {
202+
chartName = chartName[:idx]
203+
}
204+
205+
// List files in cache directory
206+
files, err := os.ReadDir(cacheDir)
207+
if err != nil {
208+
return ""
209+
}
210+
211+
// Look for files matching our chart
212+
var possibleMatches []string
213+
for _, file := range files {
214+
filename := file.Name()
215+
216+
// Check if file contains chart name and ends with .tgz
217+
if strings.Contains(filename, chartName) && strings.HasSuffix(filename, ".tgz") {
218+
fullPath := filepath.Join(cacheDir, filename)
219+
possibleMatches = append(possibleMatches, fullPath)
220+
221+
if debug {
222+
pterm.Printf("Found possible chart file: %s\n", fullPath)
246223
}
247224
}
248-
return nil, fmt.Errorf("chart file not found at expected location: %s", chartPath)
249225
}
250226

251-
fmt.Printf("📦 Loading OCI chart into memory...\n")
252-
return loader.Load(chartPath)
227+
// Return the most recent file if multiple found
228+
if len(possibleMatches) > 0 {
229+
// Sort by modification time (newest first)
230+
sort.Slice(possibleMatches, func(i, j int) bool {
231+
infoI, _ := os.Stat(possibleMatches[i])
232+
infoJ, _ := os.Stat(possibleMatches[j])
233+
return infoI.ModTime().After(infoJ.ModTime())
234+
})
235+
return possibleMatches[0]
236+
}
237+
238+
return ""
239+
}
240+
241+
// Helper to list cache files for debugging
242+
func listCacheFiles(cacheDir string) {
243+
fmt.Println("📁 Contents of cache directory:")
244+
files, err := os.ReadDir(cacheDir)
245+
if err != nil {
246+
fmt.Printf("Error reading cache directory: %v\n", err)
247+
return
248+
}
249+
250+
for _, file := range files {
251+
info, _ := file.Info()
252+
fmt.Printf(" - %s (size: %d, mod: %s)\n",
253+
file.Name(),
254+
info.Size(),
255+
info.ModTime().Format("15:04:05"))
256+
}
253257
}
254258

255259
// newRegistryClient creates a registry client for OCI operations

0 commit comments

Comments
 (0)