diff --git a/.gitignore b/.gitignore index b02e2bc..8847302 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,10 @@ Desktop.ini .env .env.* !.env.example + +# ── Temp / backups ──────────────────────────────────────────────────────────── +*.bak +*~ +Dockerfile.registry-fix +wheel-config.yaml +.kube-* diff --git a/.kube-iot-naeel b/.kube-iot-naeel deleted file mode 100644 index cfe5e72..0000000 --- a/.kube-iot-naeel +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJMk1EUXdOekE0TURRME0xb1hEVE0yTURRd05EQTRNRGswTTFvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTUZECm5ZQjRQaHBxQWZ2cU9uTlMzYXp2b1hzc29uRTlYTHQ0Z2xXM216RHpEWHU4NVZlRGp2a2phUHRnTFcvaXhnN2wKKzN3VDZ0YXpHUkxSNDNrcE00ZHA2czNXYkh5blVuZHRMVHhNaVBrbXZNMk0rVVdUaHpCTGc1VHRHUXhKaTRvVwpnZTNMTy9lS1RYNjhYTTl0Y3lsc0JoM2ZLTFVaL3c3OHNaelM0QVB4WWh4aVV4My9YcnM0YVNTdXk4aS9OWGVpCnIySlBWMnI5VzM4OEhPQzRnM0xWM2RLeEdKdW14dVdXcC9wRTUvWmo2Rk9XRExGTFBnV1Z2T3pTRFkvN2RtSHIKQjZ5REFzd1VpM01ob091ckVvSlNZYTNib3FJL0JGZklFSW9sNFVETlVqYVMvTnMrUks5MWpyU1dsOHVEMmhWSgp5WXFPc2dnZklKTi9xTWNsS0k4Q0F3RUFBYU5GTUVNd0RnWURWUjBQQVFIL0JBUURBZ0trTUJJR0ExVWRFd0VCCi93UUlNQVlCQWY4Q0FRQXdIUVlEVlIwT0JCWUVGSTZHUnBYTVkyMjJ6d1ltT1lNWXN5TmhLVm5ITUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQ1ZiK2kwa1hrRjBwSlBiREJCdXJHc0licFFyMFBuL2EvUWtKRVlmbGVqS0c2WAozL2d0d3dOL0lxY1NMRzMyU2JBbHZ6c2xrbmY1c1pBQmhibWJRWHIvQ2JybjRiZWVxTExyYUxQS3JuUVd2ZVZHCkN1a0ViV2dKU3EyS1BIaStKS0JPZ0RPT1FGa1ZZZlR3ek5JYjI5eTRqU1o1R3dRL0xiZU1NaEQ0ZUV6c1lYS0QKWWF6S0JmaGZsZWVKT0VDZWlWTXMrUDRPMC81TEV1ZVNWVkZwYndIeCtRSncyVDlZUGJ1dEkvMGoxQjNKT3lxbQptRG9JN1RIM3NWdVorNTRHT3kwRXlhQUdiQmVETmduQlRxM0djdUJBbjJSNDErMzJzdHk5V0lIb1RvNnhZZ0lsCjBUaVI5N3lDZ25rejZlNFE3UTFCT29Ib0JFNmVFNk1YSkJNUFJvTHEKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://185.247.187.149:6443 - name: iot-naeel -contexts: -- context: - cluster: iot-naeel - user: tazetdinovn@gmail.com - name: tazetdinovn@gmail.com@iot-naeel -current-context: tazetdinovn@gmail.com@iot-naeel -kind: Config -preferences: {} -users: -- name: tazetdinovn@gmail.com - user: - token: eyJhbGciOiJSUzI1NiIsImtpZCI6InNoIiwidHlwIjoiSldUIn0.eyJhdWQiOiJiYWNrZW5kIiwiZXhwIjoxNzc1OTAwNzI4LCJqdGkiOiIwOWMwZjJmOC02MDcyLTRkMTctOWEzNC1lZTQ4MzMzMjE3ODUiLCJpYXQiOjE3NzU4MTQzMjgsImlzcyI6Imh0dHBzOi8vYXV0aC5rOHMubmdjbG91ZC5ydSIsInN1YiI6InRhemV0ZGlub3ZuQGdtYWlsLmNvbSIsImNsYWltcyI6WyIiLCIiLCJ3ejAzNzA5LXNodHVydmFsLWFkbWluLWlvdC1uYWVlbCIsInd6MDM3MDktc2h0dXJ2YWwtYWRtaW4tbmFlZWwtdGVzdC0zIl0sIm5hbWUiOiLQndCw0LjQu9GMINCi0LDQt9C10YLQtNC40L3QvtCyIiwiZW1haWwiOiJ0YXpldGRpbm92bkBnbWFpbC5jb20iLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0YXpldGRpbm92bkBnbWFpbC5jb20ifQ.v14knWeokzb7-MegHj2XY8X20Z9eEcEhQA2MBBZNTX_eHtctC3lOAk7RU8VgBkyr_yX-kpaw9gW1k0GPmDoOZg-sH8brmjfHTIahEUN0ui3cUOq-KN7yTAof3ZfZWVRaVvScDD_cDI90NFEeNhO5uPZs7zvVSpKflKQQJlZNbH69gjdRvScpDp0m0BTuhRxMoYyVhTxP2RfJdYcT6179xyfbevUQkC8bkX1fOXrnD7mkLXpXG0v0ClYvFaq8VNY9_MejhEoA4P01lEMbl8NkDw04JhhSjHJ2ZXViwswYsit5T8JYezhFrKQ1HeDnkRkrh5fwsoii_9Lm4PHUGPDYEw diff --git a/.kube-wheel b/.kube-wheel deleted file mode 100644 index 9038a11..0000000 --- a/.kube-wheel +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -clusters: -- cluster: - insecure-skip-tls-verify: true - server: https://5.172.178.181:6443 - name: wheel -contexts: -- context: - cluster: wheel - user: tazet@narod.ru - name: tazet@narod.ru@wheel -current-context: tazet@narod.ru@wheel -kind: Config -preferences: {} -users: -- name: tazet@narod.ru - user: - token: eyJhbGciOiJSUzI1NiIsImtpZCI6InNoIiwidHlwIjoiSldUIn0.eyJhdWQiOiJiYWNrZW5kIiwiZXhwIjoxNzc1ODk5ODc2LCJqdGkiOiI5NjE4Yzg4NC05NjQ5LTQ1NjQtYjNjMi03Njc0Zjg5ZDAzMDciLCJpYXQiOjE3NzU4MTM0NzYsImlzcyI6Imh0dHBzOi8vYXV0aC5rOHMubmdjbG91ZC5ydSIsInN1YiI6InRhemV0QG5hcm9kLnJ1IiwiY2xhaW1zIjpbIiIsIiIsIiIsIjU1YzQ5MTRlLTdiYzUtNGJjYy1iYzcxLTI0NDQwMjViYzZmY19BRE1JTiIsIldaMDEzMjUtc2h0dXJ2YWwtYWRtaW4tdGVzdGVyIiwiV1owMTMyNS1zaHR1cnZhbC1hZG1pbi13aGVlbCJdLCJuYW1lIjoi0KLQsNC30LXRgtC00LjQvdC-0LIg0J3QsNC40LvRjCIsImVtYWlsIjoidGF6ZXRAbmFyb2QucnUiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0YXpldEBuYXJvZC5ydSJ9.GiPjJonDXxxu4U6QE4LVPc7rMV8I_0Ubr8dugNo8g4HeCwh5Y0MtWYsPhQ4GOB2A2Fy_43ItVIlMypmG9ZwVzhaRxfmNIAuNlSV-N49x_C9zGqIOagL2Us6UVr30XCYdfgcSiN2fQGx5F-LYxCMOyePA_vxyAl8dYFKT2lZmH4poOxJjgkwclZ9tej7NKcfFy31PmJu26li6LE_8TzaNN130woO0Rat3bvHfHRLk_eKj-0iAlXD5a_rt3QEli2wyhxi7DZo5ohaJ0PjhNIrdqkghBLM0KjUERRHXVyhSBUEWjsz8OAXwItmaMb6iOH_Wv50vPPLmZ_KVm8FdkQD1Qg diff --git a/Dockerfile.registry-fix b/Dockerfile.registry-fix deleted file mode 100644 index 3867917..0000000 --- a/Dockerfile.registry-fix +++ /dev/null @@ -1,14 +0,0 @@ -FROM golang:1.24-alpine AS builder -WORKDIR /app -COPY operator/go.mod operator/go.sum ./ -RUN go mod download -COPY operator/cmd/registry ./cmd/registry -COPY registrykeys ./registrykeys -RUN CGO_ENABLED=0 GOOS=linux go build -o /registry-server ./cmd/registry -FROM alpine:3.19 -WORKDIR /app -COPY --from=builder /registry-server /app/registry-server -RUN apk add --no-cache ca-certificates -USER 1000:1000 -EXPOSE 8080 -CMD ["/app/registry-server"] diff --git a/operator/build/Dockerfile.registry.bak b/operator/build/Dockerfile.registry.bak deleted file mode 100644 index 07f00b1..0000000 --- a/operator/build/Dockerfile.registry.bak +++ /dev/null @@ -1,23 +0,0 @@ -# Build Stage -FROM golang:1.24-alpine AS builder - -WORKDIR /app -# Only copy what's needed for the registry server -COPY go.mod go.sum ./ -RUN go mod download - -COPY cmd/registry ./cmd/registry -# Build statically -RUN CGO_ENABLED=0 GOOS=linux go build -o /registry-server ./cmd/registry - -# Run Stage -FROM alpine:3.19 -WORKDIR /app -COPY --from=builder /registry-server /app/registry-server -# Registry server uses HTTPS for S3, so CA certs are good to have -RUN apk add --no-cache ca-certificates - -USER 1000:1000 -EXPOSE 8080 - -CMD ["/app/registry-server"] diff --git a/operator/cmd/registry/main.go.bak b/operator/cmd/registry/main.go.bak deleted file mode 100644 index f8b3b82..0000000 --- a/operator/cmd/registry/main.go.bak +++ /dev/null @@ -1,281 +0,0 @@ -package main - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "io" - "log" - "net/http" - "net/url" - "os" - "strings" - - s3 "github.com/minio/minio-go/v7" - "github.com/minio/minio-go/v7/pkg/credentials" -) - -var ( - s3Client *s3.Client - bucketName = "terraform-registry" // Default - hostname = os.Getenv("REGISTRY_HOSTNAME") -) - -// Terraform Registry Protocol Structs -type Discovery struct { - ProvidersV1 string `json:"providers.v1"` -} - -type VersionList struct { - ID string `json:"id"` - Versions []Version `json:"versions"` - Warnings []string `json:"warnings"` -} - -type Version struct { - Version string `json:"version"` - Protocols []string `json:"protocols"` - Platforms []Platform `json:"platforms"` -} - -type Platform struct { - OS string `json:"os"` - Arch string `json:"arch"` -} - -type DownloadResponse struct { - Protocols []string `json:"protocols"` - OS string `json:"os"` - Arch string `json:"arch"` - Filename string `json:"filename"` - DownloadURL string `json:"download_url"` - ShasumsURL string `json:"shasums_url"` - ShasumsSignatureURL string `json:"shasums_signature_url"` - Shasum string `json:"shasum"` - SigningKeys SigningKeys `json:"signing_keys"` -} - -type SigningKeys struct { - GPGPublicKeys []GPGPublicKey `json:"gpg_public_keys"` -} - -type GPGPublicKey struct { - KeyID string `json:"key_id"` - ASCIIArmor string `json:"ascii_armor"` -} - -func main() { - // 1. Init S3 Connection - if hostname == "" { - hostname = "localhost:8080" - } - - endpoint := os.Getenv("S3_ENDPOINT") - accessKeyID := os.Getenv("S3_ACCESS_KEY") - secretAccessKey := os.Getenv("S3_SECRET_KEY") - - if os.Getenv("S3_BUCKET") != "" { - bucketName = os.Getenv("S3_BUCKET") - } - - var err error - s3Client, err = s3.New(endpoint, &s3.Options{ - Creds: credentials.NewStaticV4(accessKeyID, secretAccessKey, ""), - Secure: true, // Force secure for cloud S3 - }) - if err != nil { - log.Fatalln(err) - } - - // 2. HTTP Handlers - http.HandleFunc("/.well-known/terraform.json", discoveryHandler) - http.HandleFunc("/v1/providers/", router) - http.HandleFunc("/v1/proxy", proxyHandler) - http.HandleFunc("/docs/", docsHandler) - http.Handle("/", http.HandlerFunc(rootHandler)) - - log.Printf("Starting Registry Service on :8080 (Bucket: %s, Endpoint: %s)\n", bucketName, endpoint) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func rootHandler(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/" { - http.NotFound(w, r) - return - } - w.Header().Set("Content-Type", "text/html; charset=utf-8") - fmt.Fprint(w, ` - - -Terra Registry - -

Terra Registry & Documentation Server

-

Status: ONLINE

-
-

Powered by Nubes Cloud S3 Storage

- - -`) -} - -func proxyHandler(w http.ResponseWriter, r *http.Request) { - bucket := r.URL.Query().Get("bucket") - key := r.URL.Query().Get("key") - - if bucket == "" || key == "" { - http.Error(w, "Missing bucket or key params", http.StatusBadRequest) - return - } - - obj, err := s3Client.GetObject(context.Background(), bucket, key, s3.GetObjectOptions{}) - if err != nil { - log.Printf("Error getting object %s/%s: %v", bucket, key, err) - http.Error(w, "File not found", http.StatusNotFound) - return - } - defer obj.Close() - - stat, err := obj.Stat() - if err != nil { - log.Printf("Error stating object %s/%s: %v", bucket, key, err) - http.Error(w, "File not found or not accessible", http.StatusNotFound) - return - } - - w.Header().Set("Content-Length", fmt.Sprintf("%d", stat.Size)) - w.Header().Set("Content-Type", "application/octet-stream") - w.Header().Set("Last-Modified", stat.LastModified.Format(http.TimeFormat)) - - if _, err := io.Copy(w, obj); err != nil { - log.Printf("Error streaming object: %v", err) - } -} - -func discoveryHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(Discovery{ProvidersV1: "/v1/providers/"}) -} - -func router(w http.ResponseWriter, r *http.Request) { - path := strings.TrimPrefix(r.URL.Path, "/v1/providers/") - parts := strings.Split(path, "/") - - if len(parts) == 3 && parts[2] == "versions" { - listVersions(w, r, parts[0], parts[1]) - return - } - - if len(parts) == 6 && parts[3] == "download" { - downloadVersion(w, r, parts[0], parts[1], parts[2], parts[4], parts[5]) - return - } - - http.Error(w, "Not Found", http.StatusNotFound) -} - -func listVersions(w http.ResponseWriter, r *http.Request, namespace, pType string) { - prefix := fmt.Sprintf("%s/%s/%s/", hostname, namespace, pType) - ctx := context.Background() - versions := []Version{} - seenVersions := map[string]*Version{} - - objectCh := s3Client.ListObjects(ctx, bucketName, s3.ListObjectsOptions{ - Prefix: prefix, - Recursive: true, - }) - - for object := range objectCh { - if object.Err != nil { - continue - } - parts := strings.Split(object.Key, "/") - if len(parts) < 5 { - continue - } - verStr := parts[3] - fileName := parts[4] - - if _, ok := seenVersions[verStr]; !ok { - seenVersions[verStr] = &Version{ - Version: verStr, - Protocols: []string{"5.0"}, - Platforms: []Platform{}, - } - } - - if strings.Contains(fileName, "_linux_amd64.zip") { - seenVersions[verStr].Platforms = append(seenVersions[verStr].Platforms, Platform{OS: "linux", Arch: "amd64"}) - } - if strings.Contains(fileName, "_windows_amd64.zip") { - seenVersions[verStr].Platforms = append(seenVersions[verStr].Platforms, Platform{OS: "windows", Arch: "amd64"}) - } - if strings.Contains(fileName, "_darwin_amd64.zip") { - seenVersions[verStr].Platforms = append(seenVersions[verStr].Platforms, Platform{OS: "darwin", Arch: "amd64"}) - } - if strings.Contains(fileName, "_darwin_arm64.zip") { - seenVersions[verStr].Platforms = append(seenVersions[verStr].Platforms, Platform{OS: "darwin", Arch: "arm64"}) - } - } - - for _, v := range seenVersions { - versions = append(versions, *v) - } - - resp := VersionList{ - ID: fmt.Sprintf("%s/%s", namespace, pType), - Versions: versions, - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) -} - -func downloadVersion(w http.ResponseWriter, r *http.Request, namespace, pType, version, osType, arch string) { - basePath := fmt.Sprintf("%s/%s/%s/%s", hostname, namespace, pType, version) - filename := fmt.Sprintf("terraform-provider-%s_%s_%s_%s.zip", pType, version, osType, arch) - fullKey := fmt.Sprintf("%s/%s", basePath, filename) - shasumsKey := fmt.Sprintf("%s/terraform-provider-%s_%s_SHA256SUMS", basePath, pType, version) - sigKey := fmt.Sprintf("%s/terraform-provider-%s_%s_SHA256SUMS.sig", basePath, pType, version) - - var shasumValue string - shasumsObj, err := s3Client.GetObject(context.Background(), bucketName, shasumsKey, s3.GetObjectOptions{}) - if err == nil { - defer shasumsObj.Close() - scanner := bufio.NewScanner(shasumsObj) - for scanner.Scan() { - line := scanner.Text() - if strings.Contains(line, filename) { - fields := strings.Fields(line) - if len(fields) >= 1 { - shasumValue = fields[0] - } - break - } - } - } - - baseURL := "https://" + hostname - downloadLink := fmt.Sprintf("%s/v1/proxy?bucket=%s&key=%s", baseURL, bucketName, url.QueryEscape(fullKey)) - shasumsLink := fmt.Sprintf("%s/v1/proxy?bucket=%s&key=%s", baseURL, bucketName, url.QueryEscape(shasumsKey)) - sigLink := fmt.Sprintf("%s/v1/proxy?bucket=%s&key=%s", baseURL, bucketName, url.QueryEscape(sigKey)) - - gpgKey := gpgPublicKey - - resp := DownloadResponse{ - Protocols: []string{"5.0"}, - OS: osType, - Arch: arch, - Filename: filename, - DownloadURL: downloadLink, - ShasumsURL: shasumsLink, - ShasumsSignatureURL: sigLink, - Shasum: shasumValue, - SigningKeys: SigningKeys{ - GPGPublicKeys: []GPGPublicKey{gpgKey}, - }, - } - - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(resp) -} diff --git a/wheel-config.yaml b/wheel-config.yaml deleted file mode 100644 index 20f2efa..0000000 --- a/wheel-config.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJMU1UQXlNREV5TVRVMU5Wb1hEVE0xTVRBeE9ERXlNakExTlZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBUGsvClp2SXFlTWY5cEM0V0YvZW4yVVpNVWV6bHdWYTB5Wm9XMlFWWXdQM1dubHZDNDB4Vld2aXlNSEFtWmxKZzdkdzgKK1ZUbEZSRVA5YVRZS3czSk10QnZlOVM1RXU1MnZ3ZW1FSGxCZDFOWFlVNHB3U08xNDhieCtzWnQrNWlkNk9BbAp6ck9UaUhKQXJzcTFvc0sxTEFmTXh6K0lvR015SG5WUjNlaXI5SnQxSWdPYTNWemJvN01qWGFhOHg0bG1MRlllCnpiN0R6dHBqdTdyYzlKZVdMRVdkbkNWL2NjVzVmTzBXU3RKZzlTVUVDZHc3MUs4VVBYQ2FxUmRKMTB4SDJoVGwKjalVFVDlJYjk0emgvL0dkMUp3RFlsNFJkWUZKR2FSYW5mQlFVRzhBck1iUmVDWmdrYTJIY0ZtUDJtdnBidGYxUQo3ZEtQdElsb3ZqSVRWblBGNURzQ0F3RUFBYU5GTUVNd0RnWURWUjBQQVFIL0JBUURBZ0trTUJJR0ExVWRFd0VCCi93UUlNQVlCQWY4Q0FRQXdIUVlEVlIwT0JCWUVGTWdTamRrd3lMOFhNVkdvbU1FV1ZOT2hEYzBCTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQnkvTDZPTTFZK0JUWUJGRVY3TDRLeHNWaHFzZVk3UGZidnhiQWhObVFleEJlSQpYMmRxVDVyQlFaa1NXS3E3cEk3d1Q0Ny81QkN0UUtZQnpNSzRzR2NKQXVza2NHM09UejFRSzIxdEczMXp4N2lMCngrT0dDYzV0ZTR4Vydila3VCczdnN0RkNmlLRFFrbjZia1FTKzhvcFJ6SC9FU0pHUm5adXFlYTBGRW8wc1BuaW0KSGZlV3JTRm5OUk1YQ1J6dkRFY2V5cThjZ21WVEhHRGhOd2tJSTRrQ0F3ZWRnVi9vYlhjSEluZVl6SGhZVVpmbgpkbWhVSjNNVDNHZVErYkhsZFZoNjQyTXB6R2VQRTdPVzNvdjN5aFV4WUpaZ3BWZUU4a2VLTGc3YTcvd2FmeG5jCngxRWY2ekRNdlgrV2gwUjIyM3hPTldWUElPYUNyWUxoM0lHYkxCMTUKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://5.172.178.181:6443 - name: wheel -contexts: -- context: - cluster: wheel - user: tazet@narod.ru - name: tazet@narod.ru@wheel -current-context: tazet@narod.ru@wheel -kind: Config -preferences: {} -users: -- name: tazet@narod.ru - user: - token: eyJhbGciOiJSUzI1NiIsImtpZCI6InNoIiwidHlwIjoiSldUIn0.eyJhdWQiOiJiYWNrZW5kIiwiZXhwIjoxNzc1ODk5ODc2LCJqdGkiOiI5NjE4Yzg4NC05NjQ5LTQ1NjQtYjNjMi03Njc0Zjg5ZDAzMDciLCJpYXQiOjE3NzU4MTM0NzYsImlzcyI6Imh0dHBzOi8vYXV0aC5rOHMubmdjbG91ZC5ydSIsInN1YiI6InRhemV0QG5hcm9kLnJ1IiwiY2xhaW1zIjpbIiIsIiIsIiIsIjU1YzQ5MTRlLTdiYzUtNGJjYy1iYzcxLTI0NDQwMjViYzZmY19BRE1JTiIsIldaMDEzMjUtc2h0dXJ2YWwtYWRtaW4tdGVzdGVyIiwiV1owMTMyNS1zaHR1cnZhbC1hZG1pbi13aGVlbCJdLCJuYW1lIjoi0KLQsNC30LXRgtC00LjQvdC-0LIg0J3QsNC40LvRjCIsImVtYWlsIjoidGF6ZXRAbmFyb2QucnUiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0YXpldEBuYXJvZC5ydSJ9.GiPjJonDXxxu4U6QE4LVPc7rMV8I_0Ubr8dugNo8g4HeCwh5Y0MtWYsPhQ4GOB2A2Fy_43ItVIlMypmG9ZwVzhaRxfmNIAuNlSV-N49x_C9zGqIOagL2Us6UVr30XCYdfgcSiN2fQGx5F-LYxCMOyePA_vxyAl8dYFKT2lZmH4poOxJjgkwclZ9tej7NKcfFy31PmJu26li6LE_8TzaNN130woO0Rat3bvHfHRLk_eKj-0iAlXD5a_rt3QEli2wyhxi7DZo5ohaJ0PjhNIrdqkghBLM0KjUERRHXVyhSBUEWjsz8OAXwItmaMb6iOH_Wv50vPPLmZ_KVm8FdkQD1Qg