שימוש בדגלי תכונות של App Lifecycle Manager עם Go

במדריך הזה מוסבר איך לשלב את אפליקציות Go עם תכונת הדגלים של App Lifecycle Manager. במאמר הזה נסביר איך להשתמש ב-OpenFeature SDK עם ספק flagd כדי להעריך דגלים שמנוהלים על ידי App Lifecycle Manager. כך תוכלו לשלוט באופן דינמי בזמינות של תכונות ובהתנהגות שלהן בשירותי Go.

במדריך הזה אנחנו יוצאים מנקודת הנחה שכבר הגדרתם את המשאבים הדרושים ב-App Lifecycle Manager (כמו מוצרי SaaS, סוגי יחידות, יחידות, דגלים והשקות) על ידי השלמת אחד מהמדריכים הבאים להפעלה מהירה:

דרישות מוקדמות

לפני שמתחילים, חשוב לוודא שיש לכם:

  1. Go installed: גרסה 1.23 ואילך.
  2. השלמתם את המדריך למתחילים בנושא דגלים של תכונות ב-App Lifecycle Manager:
    • השלמתם בהצלחה את ההתחלה המהירה של דגלי התכונות המשולבים או של דגלי התכונות העצמאיים כדי להקצות את יחידת היעד.
    • צריכים להיות לכם משתני סביבה או ערכים מהמדריך לתחילת העבודה, כמו PROJECT_ID,‏ LOCATION_1 (האזור של היחידה שלכם), UNIT_ID ו-FLAG_KEY.
  3. מאומת gcloud עבור Application Default Credentials ‏ (ADC): אפליקציית Go משתמשת ב-ADC כדי לבצע אימות לשירותי Google Cloud . אם מריצים את הכלי באופן מקומי (לשימוש עצמאי או לבדיקת Docker מקומית), צריך לוודא שביצעתם אימות בסביבה שלכם:

    gcloud auth application-default login
    
  4. הרשאות IAM: לזהות שמריצה את אפליקציית Go צריך להיות תפקיד של ניהול זהויות והרשאות גישה (IAM) ב Google Cloud פרויקט כדי לקרוא את הגדרות הדגלים:roles/saasconfig.viewer

    gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
        --member="user:YOUR_EMAIL_ADDRESS" \
        --role="roles/saasconfig.viewer"
    

    מחליפים את YOUR_PROJECT_ID ואת YOUR_EMAIL_ADDRESS בהתאם.

הסבר על משתני סביבה מרכזיים

אפליקציית Go שלכם מסתמכת על משתני סביבה כדי להתחבר להגדרת הדגל הנכונה ולהעריך את הדגל הרצוי.

  • FLAGD_SOURCE_PROVIDER_ID: מציין איזו הגדרה של feature flag צריך לאחזר משירות App Lifecycle Manager. זה צריך להיות שם המשאב המלא של FeatureFlagConfig שמשויך ליחידה.
    • פורמט: projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID
    • דוגמה: projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01

הגדרת פרויקט Go

כדי להריץ את האפליקציה, צריך לאתחל את המודול ולהוסיף את הלוגיקה הנדרשת לאתחול ולהערכה.

  1. יוצרים ספריית פרויקט:

    mkdir go-featureflag-app
    cd go-featureflag-app
    go mod init go-featureflag-app
    
  2. יצירת קוד האפליקציה: מוסיפים קובץ בשם main.go עם התוכן הבא כדי לאתחל את הספק ולהעריך דגל.

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "os"
    
        flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg"
        "github.com/open-feature/go-sdk/openfeature"
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials"
        "google.golang.org/grpc/credentials/oauth"
        "google.golang.org/grpc/metadata"
    )
    
    // GetNewFlagdProvider initializes a flagd provider configured for  App Lifecycle Manager
    func GetNewFlagdProvider(ctx context.Context) (*flagd.Provider, error) {
        providerID := os.Getenv("FLAGD_SOURCE_PROVIDER_ID")
        if providerID == "" {
            return nil, fmt.Errorf("FLAGD_SOURCE_PROVIDER_ID environment variable is not set")
        }
    
        creds, err := oauth.NewApplicationDefault(ctx)
        if err != nil {
            return nil, err
        }
    
        // Interceptor to inject the Unit name into headers for regional routing
        routingInterceptor := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
            md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("name=%s", providerID))
            ctx = metadata.NewOutgoingContext(ctx, md)
            return streamer(ctx, desc, cc, method, opts...)
        }
    
        options := []flagd.ProviderOption{
            flagd.WithHost("saasconfig.googleapis.com"),
            flagd.WithPort(443),
            flagd.WithInProcessResolver(),
            flagd.WithProviderID(providerID),
            flagd.WithGrpcDialOptionsOverride([]grpc.DialOption{
                grpc.WithTransportCredentials(credentials.NewTLS(nil)),
                grpc.WithPerRPCCredentials(creds),
                grpc.WithStreamInterceptor(routingInterceptor),
            }),
        }
    
        return flagd.NewProvider(options...)
    }
    
    // InitializeFeatureManagement registers the provider globally
    func InitializeFeatureManagement(ctx context.Context) error {
        provider, err := GetNewFlagdProvider(ctx)
        if err != nil {
            return err
        }
        openfeature.SetProvider(provider)
        return nil
    }
    
    func main() {
    ctx := context.Background()
    InitializeFeatureManagement(ctx);
    
    // 1. Get Client
    client := openfeature.NewClient("simple-api")
    
    // 2. Create Evaluation Context
    evalCtx := openfeature.NewEvaluationContext()
    
    // 3. Evaluate Flag
    // Default to false if evaluation fails
    isEnhanced, err := client.BooleanValue(context.Background(), "enhanced-search", false, evalCtx)
    if err != nil {
    log.Printf("Flag evaluation failed: %v", err)
    }
    
    // 4. Return response
    if isEnhanced {
    fmt.Println("Enhanced search feature is enabled.")
    } else {
    fmt.Println("Enhanced search feature is disabled.")
    }
    
    }
    
  3. יצירת go.mod: שימוש בגרסאות ספציפיות מבטיח יציבות.

    module go-featureflag-app
    
    go 1.23
    
    require (
        github.com/open-feature/go-sdk v1.15.1
        github.com/open-feature/go-sdk-contrib/providers/flagd v0.3.0
        google.golang.org/grpc v1.74.2
        golang.org/x/oauth2 v0.22.0
    )
    
  4. הורדת יחסי תלות:

    go mod tidy
    go mod download
    

הרצת אפליקציית Go

אפשר להריץ את האפליקציה באופן מקומי באמצעות התצורה העצמאית שלכם, או לפרוס אותה כקונטיינר.

הפעלה עצמאית (באופן מקומי)

  1. הגדרה של משתני סביבה:

    export PROJECT_ID="your-gcp-project-id"
    export LOCATION_1="us-central1"
    export UNIT_ID="my-app-instance-01"
    export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"
    
  2. מריצים את האפליקציה:

    go run main.go
    

הפעלה משולבת (בקונטיינר)

  1. יוצרים קובץ Dockerfile:

    FROM golang:1.23 as builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY . .
    RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /go-featureflag-app .
    
    FROM gcr.io/distroless/static-debian11
    WORKDIR /
    COPY --from=builder /go-featureflag-app /go-featureflag-app
    ENTRYPOINT ["/go-featureflag-app"]
    
  2. יוצרים את קובץ האימג' ושולחים אותו:

    export PROJECT_ID="your-gcp-project-id"
    docker build -t gcr.io/${PROJECT_ID}/my-go-app:latest .
    docker push gcr.io/${PROJECT_ID}/my-go-app:latest
    
  3. פריסת השירות: מעדכנים את התוכנית של היחידה כדי להפנות אל gcr.io/${PROJECT_ID}/my-go-app:latest ופורסים את הגרסה החדשה באמצעות השקה של App Lifecycle Manager.

אימות שינויים בדגלים

אחרי שהאפליקציה פועלת, צריך לוודא שהיא מעריכה את ההגדרות של התכונות בצורה נכונה.

  1. בודקים את הערך הראשוני: מוודאים שהערך שמתאים למצב הראשוני מתועד ביומני הפלט.
  2. עדכון הדגל ב-App Lifecycle Manager: משנים את התנהגות הדגל באמצעות Google Cloud console או gcloud.
  3. מאמתים את הערך המעודכן: מריצים מחדש את הקומפילציה המקומית או בודקים את יומני המאגר כדי לראות את התוצאה המעודכנת.

המאמרים הבאים