diff --git a/cloud-build-go b/cloud-build-go index f523b9633a3ed3ee132800bda68f581060b59dcc..d30c1287f0d1d1b5ff6d6122af2c0f2b25ef34ba 100755 Binary files a/cloud-build-go and b/cloud-build-go differ diff --git a/main b/main index ded941c47b4fdff50b6a706ba95472d9edfbd893..d631209c8e2f313551939a865b25d83337b0e856 100755 Binary files a/main and b/main differ diff --git a/main.go b/main.go index fa1ccc81a595883d773d47b027478a03e45a39de..f80d87cd1f0b5fca86fcc29f9285a1c276d91f0f 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "fmt" "log" "os" - "path/filepath" "github.com/niveus/cloud-build-go/cloudbuild" "github.com/niveus/cloud-build-go/config" @@ -14,188 +13,99 @@ import ( func main() { // Define command-line flags - projectID := flag.String("project", "", "Google Cloud Project ID") - location := flag.String("location", "global", "Location for the connection (e.g., global, us-central1)") + configPath := flag.String("config", "config/config.json", "Path to config file") + action := flag.String("action", "list-connections", "Action to perform: list-connections, create-gitlab, delete-connection, list-linkable-repos, inspect") connectionName := flag.String("name", "", "Name for the connection") - connectionType := flag.String("type", "GITHUB", "Type of connection (e.g., GITHUB, GITLAB)") - action := flag.String("action", "create", "Action to perform: create, get, list, delete, create-gitlab") - configPath := flag.String("config", "", "Path to config file (optional)") - token := flag.String("token", "", "Access token for authentication (optional)") flag.Parse() - // Project ID can come from config file or command line + // Project ID, location, connection type will come from config file var projectIDValue, locationValue, connTypeValue string - // Load config file if specified - if *configPath != "" { - cfg, err := config.LoadConfig(*configPath) - if err != nil { - log.Printf("Warning: Failed to load config file: %v", err) - } else { - log.Printf("Loaded configuration from %s (Project: %s, Location: %s)", - *configPath, cfg.ProjectID, cfg.Location) - - // Set defaults from config file - projectIDValue = cfg.ProjectID - locationValue = cfg.Location - connTypeValue = cfg.DefaultConnType - - // Log the values that will be used - log.Printf("Config values initially set to: Project=%s, Location=%s, Type=%s", - projectIDValue, locationValue, connTypeValue) - } - } - - // Command line arguments take precedence ONLY if they have non-default values - if *projectID != "" { - projectIDValue = *projectID - log.Printf("Using command-line project ID: '%s'", projectIDValue) - } - - if *location != "" && *location != "global" { - locationValue = *location - log.Printf("Using command-line location: '%s'", locationValue) + // Load config file + cfg, err := config.LoadConfig(*configPath) + if err != nil { + log.Fatalf("Failed to load config file: %v", err) } + // Set values from config file + projectIDValue = cfg.ProjectID + locationValue = cfg.Location + connTypeValue = cfg.DefaultConnType - if *connectionType != "" && *connectionType != "GITHUB" { - connTypeValue = *connectionType - log.Printf("Using command-line connection type: '%s'", connTypeValue) - } + // Log the values that will be used + log.Printf("Config values set to: Project=%s, Location=%s, Type=%s", + projectIDValue, locationValue, connTypeValue) - // Check for required values after potentially loading from config + // Check for required values after loading from config if projectIDValue == "" { - log.Fatal("project ID is required (provide via --project flag or config file)") + log.Fatal("project ID is required in the config file") } - // Additional validation based on the action - if (*action == "create" || *action == "get" || *action == "delete" || *action == "listrepos" || *action == "inspect") && *connectionName == "" { - log.Fatal("name flag is required for create, get, delete, listrepos, and inspect actions") - } + // We no longer need this validation because each case will handle missing connection names by + // automatically using values from the config file + // Validation still happens in each case for more specific handling ctx := context.Background() // Create a Cloud Build client using our package var client *cloudbuild.Client - var err error - // Authentication approach - // If a token is provided via command line, use that - // Otherwise, rely on Application Default Credentials - if *token != "" { - log.Printf("Using provided access token for authentication") - client, err = cloudbuild.NewClientWithToken(ctx, *token) - } else { - // Use Application Default Credentials - log.Printf("Using Application Default Credentials for authentication") - client, err = cloudbuild.NewClient(ctx) - } - + // Authentication approach Application Default Credentials + client, err = cloudbuild.NewClient(ctx) if err != nil { log.Fatalf("Failed to create Cloud Build client: %v", err) } // Perform the requested action switch *action { - case "create": - err = client.CreateConnection(projectIDValue, locationValue, *connectionName, connTypeValue) - if err != nil { - log.Fatalf("Failed to create connection: %v", err) - } - fmt.Printf("Successfully created connection: %s\n", fmt.Sprintf("projects/%s/locations/%s/connections/%s", projectIDValue, locationValue, *connectionName)) - + case "create-gitlab": - // Check if we have a configuration for GitLab + // Find the connection config for the given name var connConfig *config.ConnectionConfig - if *configPath != "" { - cfg, err := config.LoadConfig(*configPath) - if err != nil { - log.Fatalf("Failed to load config file: %v", err) - } - - // Find the connection config for the given name - for _, conn := range cfg.Connections { - if conn.Name == *connectionName || *connectionName == "" && len(cfg.Connections) == 1 { - connConfig = &conn - break - } - } - - if connConfig == nil { - log.Fatalf("Connection configuration not found for '%s'", *connectionName) + for _, conn := range cfg.Connections { + if conn.Name == *connectionName || *connectionName == "" && len(cfg.Connections) == 1 { + connConfig = &conn + break } - - if connConfig.GitlabConfig == nil { - log.Fatalf("GitLab configuration not found for connection '%s'", connConfig.Name) - } - - // For GitLab connections, we'll use the values directly from the config file - // This is the most reliable way to ensure we're using the right values - projectIDValue = cfg.ProjectID - locationValue = cfg.Location - - log.Printf("For GitLab connection, using config values: Project='%s', Location='%s'", - projectIDValue, locationValue) - - fmt.Printf("Creating GitLab connection '%s' in project '%s' (location: '%s')\n", - connConfig.Name, projectIDValue, locationValue) - - // Create the GitLab connection using the Cloud Build SDK - // This uses the official SDK methods, not manual URL construction - err = client.CreateGitLabConnection( - projectIDValue, - locationValue, - connConfig.Name, - connConfig.GitlabConfig, - connConfig.Annotations, - ) - if err != nil { - log.Fatalf("Failed to create GitLab connection: %v", err) - } - - fmt.Printf("Successfully created GitLab connection: %s\n", - fmt.Sprintf("projects/%s/locations/%s/connections/%s", projectIDValue, locationValue, connConfig.Name)) - } else { - log.Fatal("Config file is required for creating GitLab connections") } - - // Save example config if it doesn't exist - if *configPath == "" { - defaultConfigPath := filepath.Join("config", "config.json") - _, err := os.Stat(defaultConfigPath) - if os.IsNotExist(err) { - cfg := &config.Config{ - ProjectID: projectIDValue, - Location: locationValue, - DefaultConnType: connTypeValue, - } - err = config.SaveConfig(cfg, defaultConfigPath) - if err != nil { - log.Printf("Note: Failed to save example config file: %v", err) - } else { - log.Printf("Note: Created example config file at %s", defaultConfigPath) - } + + if connConfig == nil { + if *connectionName == "" { + log.Fatalf("No connection configuration found in config file. Please add connections to your config file.") + } else { + log.Fatalf("No connection configuration found for name '%s' in config file", *connectionName) } } - - case "get": - connection, err := client.GetConnection(projectIDValue, locationValue, *connectionName) - if err != nil { - log.Fatalf("Failed to get connection: %v", err) + + // Check if the connection config has GitLab configuration + if connConfig.GitlabConfig == nil { + log.Fatalf("Connection '%s' does not have GitLab configuration", connConfig.Name) } - fmt.Printf("Connection details:\nName: %s\nDisabled: %t\n", connection.Name, connection.Disabled) - // Show type-specific details - if connection.GithubConfig != nil { - fmt.Printf("Type: GitHub\n") - if connection.GithubConfig.AppInstallationId > 0 { - fmt.Printf("App Installation ID: %d\n", connection.GithubConfig.AppInstallationId) - } - } else if connection.GitlabConfig != nil { - fmt.Printf("Type: GitLab\n") - fmt.Printf("Host URI: %s\n", connection.GitlabConfig.HostUri) + log.Printf("Creating GitLab connection using config: ProjectID=%s, Location=%s, Name=%s", + projectIDValue, locationValue, connConfig.Name) + + fmt.Printf("Creating GitLab connection '%s' in project '%s' (location: '%s')\n", + connConfig.Name, projectIDValue, locationValue) + + // Create the GitLab connection using the Cloud Build SDK + err = client.CreateGitLabConnection( + projectIDValue, + locationValue, + connConfig.Name, + connConfig.GitlabConfig, + connConfig.Annotations, + ) + if err != nil { + log.Fatalf("Failed to create GitLab connection: %v", err) } + + fmt.Printf("Successfully created GitLab connection: %s\n", + fmt.Sprintf("projects/%s/locations/%s/connections/%s", projectIDValue, locationValue, connConfig.Name)) - case "list": + case "list-connections": + // Use project ID and location from config + log.Printf("Listing connections in project %s (location: %s)", projectIDValue, locationValue) + connections, err := client.ListConnections(projectIDValue, locationValue) if err != nil { log.Fatalf("Failed to list connections: %v", err) @@ -213,20 +123,64 @@ func main() { fmt.Printf("%d. %s (Type: %s)\n", i+1, conn.Name, connType) } - case "delete": - err := client.DeleteConnection(projectIDValue, locationValue, *connectionName) + case "delete-connection": + // If connection name not provided via command line, get it from config + connNameToDelete := *connectionName + if connNameToDelete == "" { + // If there's only one connection in config, use that + if len(cfg.Connections) == 1 { + connNameToDelete = cfg.Connections[0].Name + fmt.Printf("Using connection name from config: %s\n", connNameToDelete) + } else if len(cfg.Connections) > 1 { + // If multiple connections, show the available options + fmt.Println("Multiple connections found in config. Please specify which one to delete with --name flag:") + for i, conn := range cfg.Connections { + fmt.Printf("%d. %s\n", i+1, conn.Name) + } + os.Exit(1) + } else { + log.Fatalf("No connections found in config file") + } + } + + log.Printf("Deleting connection %s in project %s (location: %s)", + connNameToDelete, projectIDValue, locationValue) + + err := client.DeleteConnection(projectIDValue, locationValue, connNameToDelete) if err != nil { log.Fatalf("Failed to delete connection: %v", err) } - fmt.Printf("Successfully deleted connection: %s\n", *connectionName) + fmt.Printf("Successfully deleted connection: %s\n", connNameToDelete) - case "listrepos": - repositories, err := client.ListLinkableRepositories(projectIDValue, locationValue, *connectionName) + case "list-linkable-repos": + // If connection name not provided via command line, get it from config + connNameToList := *connectionName + if connNameToList == "" { + // If there's only one connection in config, use that + if len(cfg.Connections) == 1 { + connNameToList = cfg.Connections[0].Name + fmt.Printf("Using connection name from config: %s\n", connNameToList) + } else if len(cfg.Connections) > 1 { + // If multiple connections, show the available options + fmt.Println("Multiple connections found in config. Please specify which one to use with --name flag:") + for i, conn := range cfg.Connections { + fmt.Printf("%d. %s\n", i+1, conn.Name) + } + os.Exit(1) + } else { + log.Fatalf("No connections found in config file") + } + } + + log.Printf("Listing linkable repositories for connection %s in project %s (location: %s)", + connNameToList, projectIDValue, locationValue) + + repositories, err := client.ListLinkableRepositories(projectIDValue, locationValue, connNameToList) if err != nil { log.Fatalf("Failed to list linkable repositories: %v", err) } fmt.Printf("Found %d linkable repositories for connection %s:\n", - len(repositories), *connectionName) + len(repositories), connNameToList) for i, repo := range repositories { fmt.Printf("%d. %s\n", i+1, repo.Name) if repo.RemoteUri != "" { @@ -240,14 +194,36 @@ func main() { case "inspect": // This action provides detailed inspection of a connection's configuration and status + // If connection name not provided via command line, get it from config + connNameToInspect := *connectionName + if connNameToInspect == "" { + // If there's only one connection in config, use that + if len(cfg.Connections) == 1 { + connNameToInspect = cfg.Connections[0].Name + fmt.Printf("Using connection name from config: %s\n", connNameToInspect) + } else if len(cfg.Connections) > 1 { + // If multiple connections, show the available options + fmt.Println("Multiple connections found in config. Please specify which one to inspect with --name flag:") + for i, conn := range cfg.Connections { + fmt.Printf("%d. %s\n", i+1, conn.Name) + } + os.Exit(1) + } else { + log.Fatalf("No connections found in config file") + } + } + + log.Printf("Inspecting connection %s in project %s (location: %s)", + connNameToInspect, projectIDValue, locationValue) + fmt.Printf("Inspecting connection %s in project %s (location: %s)...\n\n", - *connectionName, projectIDValue, locationValue) - err := client.InspectConnection(projectIDValue, locationValue, *connectionName) + connNameToInspect, projectIDValue, locationValue) + err := client.InspectConnection(projectIDValue, locationValue, connNameToInspect) if err != nil { log.Fatalf("Failed to inspect connection: %v", err) } default: - log.Fatalf("Unknown action: %s. Supported actions are: create, get, list, delete, listrepos, inspect", *action) + log.Fatalf("Unknown action: %s. Supported actions are: list-connections, create-gitlab, delete-connection, list-linkable-repos, inspect", *action) } }