package talos import ( "bytes" "encoding/json" "fmt" "net/http" "strings" "time" ) const ( defaultPlatform = "nocloud" defaultTarget = "cloud" ) var defaultExtensions = []string{ "siderolabs/iscsi-tools", "siderolabs/nfs-utils", "siderolabs/qemu-guest-agent", "siderolabs/util-linux-tools", } type releaseResponse struct { TagName string `json:"tag_name"` } type schematicRequest struct { Customization struct { SystemExtensions struct { OfficialExtensions []string `json:"officialExtensions"` } `json:"systemExtensions"` } `json:"customization"` } type schematicResponse struct { ID string `json:"id"` } func LatestVersion() string { client := http.Client{Timeout: 10 * time.Second} request, err := http.NewRequest(http.MethodGet, "https://api.github.com/repos/siderolabs/talos/releases/latest", nil) if err != nil { return "v1.13.6" } request.Header.Set("Accept", "application/vnd.github+json") response, err := client.Do(request) if err != nil { return "v1.13.6" } defer response.Body.Close() if response.StatusCode != http.StatusOK { return "v1.13.6" } var release releaseResponse if err := json.NewDecoder(response.Body).Decode(&release); err != nil || release.TagName == "" { return "v1.13.6" } return release.TagName } func NormalizeVersion(version string) string { if strings.HasPrefix(version, "v") { return version } return "v" + version } func FactoryURL(version, arch string) string { version = NormalizeVersion(version) return fmt.Sprintf("https://factory.talos.dev/?arch=%s&extensions=-&extensions=%s&extensions=%s&extensions=%s&extensions=%s&platform=%s&target=%s&version=%s", arch, "siderolabs%2Fiscsi-tools", "siderolabs%2Fnfs-utils", "siderolabs%2Fqemu-guest-agent", "siderolabs%2Futil-linux-tools", defaultPlatform, defaultTarget, strings.TrimPrefix(version, "v"), ) } func ResolveSchematicID() (string, error) { requestBody := schematicRequest{} requestBody.Customization.SystemExtensions.OfficialExtensions = defaultExtensions payload, err := json.Marshal(requestBody) if err != nil { return "", err } client := http.Client{Timeout: 15 * time.Second} request, err := http.NewRequest(http.MethodPost, "https://factory.talos.dev/schematics", bytes.NewReader(payload)) if err != nil { return "", err } request.Header.Set("Content-Type", "application/json") response, err := client.Do(request) if err != nil { return "", err } defer response.Body.Close() if response.StatusCode >= 300 { return "", fmt.Errorf("talos factory returned %s", response.Status) } var schematic schematicResponse if err := json.NewDecoder(response.Body).Decode(&schematic); err != nil { return "", err } if schematic.ID == "" { return "", fmt.Errorf("talos factory returned empty schematic id") } return schematic.ID, nil }