Skip to content
Snippets Groups Projects
Select Git revision
  • 125ba11aaf1c272aacd843468a36ae2a745af929
  • master default protected
  • prajwal/develop
  • v1-module-test
4 results

main.go

Blame
  • main.go 12.24 KiB
    package main
    
    import (
    	"context"
    	"flag"
    	"fmt"
    	"log"
    	"os"
    
    	"github.com/niveus/cloud-build-go/cloudbuild"
    	"github.com/niveus/cloud-build-go/config"
    )
    
    func main() {
    	// Define command-line flags
    	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")
    	flag.Parse()
    
    	// Project ID, location, connection type will come from config file
    	var projectIDValue, locationValue, connTypeValue string
    	
    	// 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
    	
    	// 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 loading from config
    	if projectIDValue == "" {
    		log.Fatal("project ID is required in the config file")
    	}
    
    	// 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
    	
    	// 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-gitlab":
    		// Find the connection config for the given name
    		var connConfig *config.ConnectionConfig
    		for _, conn := range cfg.Connections {
    			if conn.Name == *connectionName || *connectionName == "" && len(cfg.Connections) == 1 {
    				connConfig = &conn
    				break
    			}
    		}
    		
    		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)
    			}
    		}
    		
    		// Check if the connection config has GitLab configuration
    		if connConfig.GitlabConfig == nil {
    			log.Fatalf("Connection '%s' does not have GitLab configuration", connConfig.Name)
    		}
    		
    		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-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)
    		}
    		fmt.Printf("Found %d connections in project %s (location: %s):\n", 
    			len(connections), projectIDValue, locationValue)
    		for i, conn := range connections {
    			// Determine connection type based on config
    			connType := "Unknown"
    			if conn.GithubConfig != nil {
    				connType = "GitHub"
    			} else if conn.GitlabConfig != nil {
    				connType = "GitLab"
    			}
    			fmt.Printf("%d. %s (Type: %s)\n", i+1, conn.Name, connType)
    		}
    
    
    
    	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), connNameToList)
    		for i, repo := range repositories {
    			fmt.Printf("%d. %s\n", i+1, repo.Name)
    			if repo.RemoteUri != "" {
    				fmt.Printf("   URI: %s\n", repo.RemoteUri)
    			}
    			// Add a blank line between repositories for better readability
    			if i < len(repositories)-1 {
    				fmt.Println()
    			}
    		}
    		
    	case "link-repository":
    		// If connection name not provided via command line, get it from config
    		connNameToLink := *connectionName
    		if connNameToLink == "" {
    			// If there's only one connection in config, use that
    			if len(cfg.Connections) == 1 {
    				connNameToLink = cfg.Connections[0].Name
    				fmt.Printf("Using connection name from config: %s\n", connNameToLink)
    			} 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")
    			}
    		}
    		
    		// Get the linkable repositories for this connection
    		log.Printf("Finding linkable repositories for connection %s in project %s (location: %s)", 
    			connNameToLink, projectIDValue, locationValue)
    		
    		linkableRepos, err := client.ListLinkableRepositories(projectIDValue, locationValue, connNameToLink)
    		if err != nil {
    			log.Fatalf("Failed to list linkable repositories: %v", err)
    		}
    		
    		if len(linkableRepos) == 0 {
    			log.Fatalf("No linkable repositories found for connection %s", connNameToLink)
    		}
    		
    		// Use the first repository in the list
    		repoToLink := linkableRepos[0]
    		
    		// Extract and use a valid repository name
    		// First check if the repository has a RemoteUri field which usually contains the repo info
    		var repoName string
    		if repoToLink.RemoteUri != "" {
    			// Extract name from the remote URI (e.g., https://gitlab.com/namespace/repo-name)
    			uriParts := strings.Split(repoToLink.RemoteUri, "/")
    			if len(uriParts) > 0 {
    				repoName = uriParts[len(uriParts)-1]
    				// Remove .git suffix if present
    				repoName = strings.TrimSuffix(repoName, ".git")
    			}
    		}
    		
    		// If we still don't have a name, use attributes (which is a more reliable way)
    		if repoName == "" {
    			// For GitLab repositories, the name is in the attributes
    			printRepositoryInfo(repoToLink) // Print debug info
    			
    			// Try common attribute keys that might contain the name
    			if repoToLink.Annotations != nil {
    				if name, ok := repoToLink.Annotations["name"]; ok && name != "" {
    					repoName = name
    				} else if name, ok := repoToLink.Annotations["repository_name"]; ok && name != "" {
    					repoName = name
    				}
    			}
    		}
    		
    		// If we still don't have a name, ask the user to provide one manually
    		if repoName == "" {
    			fmt.Println("Unable to automatically determine repository name. Please provide one manually:")
    			fmt.Print("Repository name: ")
    			fmt.Scanln(&repoName)
    		}
    		
    		// Make sure the repository name is valid
    		if repoName == "" {
    			log.Fatalf("Cannot link repository: No valid repository name provided")
    		}
    		
    		fmt.Printf("Linking repository: %s\n", repoName)
    		
    		// We need to get the remote URI for the repository
    		var remoteURI string
    		if repoToLink.RemoteUri != "" {
    			// Use the remote URI from the repository object if available
    			remoteURI = repoToLink.RemoteUri
    			fmt.Printf("Using remote URI from repository data: %s\n", remoteURI)
    		} else {
    			// Otherwise construct a likely URI based on the connection and repository name
    			// This is a best guess and may need adjustment for different Git providers
    			for _, conn := range cfg.Connections {
    				if conn.Name == connNameToLink && conn.GitlabConfig != nil {
    					// If we have GitLab config, use the host URI to construct a repo URL
    					remoteURI = fmt.Sprintf("%s/%s.git", strings.TrimSuffix(conn.GitlabConfig.HostURI, "/"), repoName)
    					break
    				}
    			}
    			
    			// If we still don't have a remote URI, prompt the user
    			if remoteURI == "" {
    				fmt.Println("Please enter the remote URI for the repository (e.g., https://gitlab.com/namespace/repo.git):")
    				fmt.Print("Remote URI: ")
    				fmt.Scanln(&remoteURI)
    				
    				if remoteURI == "" {
    					log.Fatalf("Remote URI is required to link a repository")
    				}
    			} else {
    				fmt.Printf("Constructed remote URI: %s\n", remoteURI)
    			}
    		}
    		
    		// Link the repository with the remote URI
    		err = client.LinkRepository(projectIDValue, locationValue, connNameToLink, repoName, remoteURI)
    		if err != nil {
    			log.Fatalf("Failed to link repository: %v", err)
    		}
    		
    		fmt.Printf("Successfully linked repository %s to connection %s\n", repoName, connNameToLink)
    
    	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", connNameToDelete)
    	
    	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", 
    			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: list-connections, create-gitlab, delete-connection, list-linkable-repos, inspect", *action)
    	}
    }