scripts/main.go
Rama main · réplica de lectura del repositorio original.
package main
import (
"flag"
"fmt"
"log"
"os"
"github.com/flexprice/flexprice/scripts/internal"
"github.com/flexprice/flexprice/scripts/local"
)
// Command represents a script that can be run
type Command struct {
Name string
Description string
Run func() error
}
var commands = []Command{
{
Name: "seed-events",
Description: "Seed events data into Clickhouse",
Run: internal.SeedEventsClickhouse,
},
{
Name: "seed-events-by-meters",
Description: "Seed events data into Clickhouse by meters",
Run: internal.SeedEventsFromMeters,
},
{
Name: "generate-apikey",
Description: "Generate a new API key",
Run: internal.GenerateNewAPIKey,
},
{
Name: "generate-dev-token",
Description: "Generate a short-lived JWT for internal developer testing",
Run: internal.GenerateDevToken,
},
{
Name: "assign-tenant",
Description: "Assign tenant to user",
Run: internal.AssignTenantToUser,
},
{
Name: "onboard-tenant",
Description: "Onboard a new tenant",
Run: internal.OnboardNewTenant,
},
{
Name: "migrate-subscription-line-items",
Description: "Migrate subscription line items",
Run: local.MigrateSubscriptionLineItems,
},
{
Name: "migrate-environments",
Description: "Migrate entities to use environment_id",
Run: internal.MigrateEnvironments,
},
{
Name: "sync-billing-customers",
Description: "Sync billing customers",
Run: internal.SyncBillingCustomers,
},
{
Name: "import-pricing",
Description: "Import pricing",
Run: internal.ImportPricing,
},
{
Name: "assign-plan",
Description: "Assign a specific plan to customers who don't already have it",
Run: internal.AssignPlanToCustomers,
},
{
Name: "add-new-user",
Description: "Add a new user to a tenant",
Run: internal.AddNewUserToTenant,
},
{
Name: "add-environment",
Description: "Add an environment to an existing tenant",
Run: internal.AddEnvironmentToTenant,
},
{
Name: "migrate-invoice-sequences",
Description: "Migrate invoice sequences to include environment isolation",
Run: internal.MigrateInvoiceSequences,
},
{
Name: "migrate-to-addon",
Description: "Migrate to addon",
Run: internal.CopyPlanChargesToAddons,
},
{
Name: "process-csv-features",
Description: "Process CSV file to create features and prices for serverless plan",
Run: internal.ProcessCSVFeatures,
},
{
Name: "credit-usage-report",
Description: "Generate credit usage report for customers in a tenant/environment",
Run: internal.GenerateCreditUsageReport,
},
{
Name: "import-features",
Description: "Import features from a CSV file",
Run: internal.ImportFeatures,
},
{
Name: "migrate-cga",
Description: "Migrate existing Credit Grant Applications to new structure (ensure environment_id is set)",
Run: internal.MigrateCGA,
},
{
Name: "sync-price-to-subscriptions",
Description: "Sync a price to all subscriptions with the same plan and start date by creating new line items",
Run: internal.SyncPriceToSubscriptions,
},
{
Name: "fix-line-item-price-end-dates",
Description: "End plan line items of live subscriptions at their price's end date (dry run unless APPLY=true)",
Run: internal.FixLineItemPriceEndDates,
},
{
Name: "setup-draft-invoices",
Description: "Create draft invoices for subscriptions from a JSON file and trigger processing workflows",
Run: internal.SetupDraftInvoices,
},
{
Name: "setup-dummy-billing-customer",
Description: "Create CUSTOMER_COUNT demo customers (default 1), each with subscription, $100 wallet top-up, and 500 meter events (Postgres + Kafka)",
Run: internal.SetupDummyBillingCustomer,
},
{
Name: "replay-events-csv",
Description: "Replay events from a CSV via POST /v1/events/bulk in batches of -batch-size (preserves event_id, timestamp, event_name, source, properties)",
Run: internal.ReplayEventsFromCSV,
},
}
func main() {
// Define command line flags
var (
listCommands bool
cmdName string
email string
tenant string
metersFile string
plansFile string
tenantID string
userID string
password string
environmentID string
filePath string
apiKey string
externalCustomerID string
eventName string
startTime string
endTime string
batchSize string
dryRun string
planID string
meterID string
startDate string
billingCycle string
customerCount string
environmentName string
environmentType string
addonID string
workerCount string
effectiveDate string
failedOutput string
successOutput string
apiBaseURL string
expiryHours string
)
flag.BoolVar(&listCommands, "list", false, "List all available commands")
flag.StringVar(&cmdName, "cmd", "", "Command to run")
flag.StringVar(&email, "user-email", "", "Email for tenant operations")
flag.StringVar(&tenant, "tenant-name", "", "Tenant name for operations")
flag.StringVar(&metersFile, "meters-file", "", "Path to meters JSON file")
flag.StringVar(&plansFile, "plans-file", "", "Path to plans JSON file")
flag.StringVar(&tenantID, "tenant-id", "", "Tenant ID for operations")
flag.StringVar(&userID, "user-id", "", "User ID for operations")
flag.StringVar(&password, "user-password", "", "password for setting up new user")
flag.StringVar(&environmentID, "environment-id", "", "Environment ID for operations")
flag.StringVar(&environmentName, "environment-name", "", "Environment name for add-environment command")
flag.StringVar(&environmentType, "environment-type", "", "Environment type for add-environment (development or production)")
flag.StringVar(&filePath, "file-path", "", "File path for operations")
flag.StringVar(&planID, "plan-id", "", "Plan ID for operations")
flag.StringVar(&meterID, "meter-id", "", "Meter ID (for setup-dummy-billing-customer)")
flag.StringVar(&startDate, "start-date", "", "Subscription start date RFC3339 or YYYY-MM-DD")
flag.StringVar(&billingCycle, "billing-cycle", "", "Billing cycle: anniversary or calendar")
flag.StringVar(&customerCount, "customer-count", "", "Number of customers to create (setup-dummy-billing-customer); default 1")
flag.StringVar(&apiKey, "api-key", "", "API key for operations")
flag.StringVar(&externalCustomerID, "external-customer-id", "", "External customer ID for reprocessing events")
flag.StringVar(&eventName, "event-name", "", "Event name filter for reprocessing")
flag.StringVar(&startTime, "start-time", "", "Start time for reprocessing (ISO-8601 format)")
flag.StringVar(&endTime, "end-time", "", "End time for reprocessing (ISO-8601 format)")
flag.StringVar(&batchSize, "batch-size", "100", "Batch size for reprocessing and event replay (max 1000)")
flag.StringVar(&dryRun, "dry-run", "false", "Dry run mode (true/false)")
flag.StringVar(&addonID, "addon-id", "", "Addon ID for operations")
flag.StringVar(&workerCount, "worker-count", "", "Concurrent workers (sets WORKER_COUNT when non-empty; migrate-calendar-billing-csv defaults to 3 if unset)")
flag.StringVar(&effectiveDate, "effective-date", "", "Effective date for calendar billing migration (RFC3339 or YYYY-MM-DD)")
flag.StringVar(&failedOutput, "failed-output", "", "Path for failed rows CSV (migrate-calendar-billing-csv)")
flag.StringVar(&successOutput, "success-output", "", "Path for successful rows CSV (migrate-calendar-billing-csv)")
flag.StringVar(&apiBaseURL, "api-base-url", "", "Flexprice API base URL including /v1 (migrate-calendar-billing-csv); default https://api.cloud.flexprice.io/v1")
flag.StringVar(&expiryHours, "expiry-hours", "", "Token expiry in hours (generate-dev-token; default 1)")
flag.Parse()
if listCommands {
fmt.Println("Available commands:")
for _, cmd := range commands {
fmt.Printf(" %-20s %s\n", cmd.Name, cmd.Description)
}
return
}
if cmdName == "" {
log.Fatal("Please specify a command to run using -cmd flag. Use -list to see available commands.")
}
// Set command-specific environment variables
if email != "" {
os.Setenv("USER_EMAIL", email) // #nosec G104 -- seed tooling, non-prod
}
if tenant != "" {
os.Setenv("TENANT_NAME", tenant) // #nosec G104 -- seed tooling, non-prod
}
if metersFile != "" {
os.Setenv("METERS_FILE", metersFile) // #nosec G104 -- seed tooling, non-prod
}
if plansFile != "" {
os.Setenv("PLANS_FILE", plansFile) // #nosec G104 -- seed tooling, non-prod
}
if tenantID != "" {
os.Setenv("TENANT_ID", tenantID) // #nosec G104 -- seed tooling, non-prod
}
if userID != "" {
os.Setenv("USER_ID", userID) // #nosec G104 -- seed tooling, non-prod
}
if password != "" {
os.Setenv("USER_PASSWORD", password) // #nosec G104 -- seed tooling, non-prod
}
if environmentID != "" {
os.Setenv("ENVIRONMENT_ID", environmentID) // #nosec G104 -- seed tooling, non-prod
}
if environmentName != "" {
os.Setenv("ENVIRONMENT_NAME", environmentName) // #nosec G104 -- seed tooling, non-prod
}
if environmentType != "" {
os.Setenv("ENVIRONMENT_TYPE", environmentType) // #nosec G104 -- seed tooling, non-prod
}
if filePath != "" {
os.Setenv("FILE_PATH", filePath) // #nosec G104 -- seed tooling, non-prod
}
if planID != "" {
os.Setenv("PLAN_ID", planID) // #nosec G104 -- seed tooling, non-prod
}
if meterID != "" {
os.Setenv("METER_ID", meterID) // #nosec G104 -- seed tooling, non-prod
}
if startDate != "" {
os.Setenv("START_DATE", startDate) // #nosec G104 -- seed tooling, non-prod
}
if billingCycle != "" {
os.Setenv("BILLING_CYCLE", billingCycle) // #nosec G104 -- seed tooling, non-prod
}
if customerCount != "" {
os.Setenv("CUSTOMER_COUNT", customerCount) // #nosec G104 -- seed tooling, non-prod
}
if addonID != "" {
os.Setenv("ADDON_ID", addonID) // #nosec G104 -- seed tooling, non-prod
}
if apiKey != "" {
os.Setenv("SCRIPT_FLEXPRICE_API_KEY", apiKey) // #nosec G104 -- seed tooling, non-prod
os.Setenv("FLEXPRICE_API_KEY", apiKey) // #nosec G104 -- seed tooling, non-prod
}
if externalCustomerID != "" {
os.Setenv("EXTERNAL_CUSTOMER_ID", externalCustomerID) // #nosec G104 -- seed tooling, non-prod
}
if eventName != "" {
os.Setenv("EVENT_NAME", eventName) // #nosec G104 -- seed tooling, non-prod
}
if startTime != "" {
os.Setenv("START_TIME", startTime) // #nosec G104 -- seed tooling, non-prod
}
if endTime != "" {
os.Setenv("END_TIME", endTime) // #nosec G104 -- seed tooling, non-prod
}
if batchSize != "" {
os.Setenv("BATCH_SIZE", batchSize) // #nosec G104 -- seed tooling, non-prod
}
if dryRun != "" {
os.Setenv("DRY_RUN", dryRun) // #nosec G104 -- seed tooling, non-prod
}
if workerCount != "" {
os.Setenv("WORKER_COUNT", workerCount) // #nosec G104 -- seed tooling, non-prod
}
if apiBaseURL != "" {
os.Setenv("API_BASE_URL", apiBaseURL) // #nosec G104 -- seed tooling, non-prod
}
if effectiveDate != "" {
os.Setenv("EFFECTIVE_DATE", effectiveDate) // #nosec G104 -- seed tooling, non-prod
}
if failedOutput != "" {
os.Setenv("FAILED_OUTPUT_PATH", failedOutput) // #nosec G104 -- seed tooling, non-prod
}
if successOutput != "" {
os.Setenv("SUCCESS_OUTPUT_PATH", successOutput) // #nosec G104 -- seed tooling, non-prod
}
if expiryHours != "" {
os.Setenv("EXPIRY_HOURS", expiryHours) // #nosec G104 -- seed tooling, non-prod
}
// Find and run the command
for _, cmd := range commands {
if cmd.Name == cmdName {
if err := cmd.Run(); err != nil {
log.Fatalf("Error running command %s: %v", cmdName, err)
}
return
}
}
log.Fatalf("Unknown command: %s. Use -list to see available commands.", cmdName)
}