diff --git a/devops-mcp-server/cloudrun/client/cloudrunclient.go b/devops-mcp-server/cloudrun/client/cloudrunclient.go index 2b11664..be9a550 100644 --- a/devops-mcp-server/cloudrun/client/cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/cloudrunclient.go @@ -54,6 +54,7 @@ type CloudRunClient interface { DeployFromSource(ctx context.Context, projectID, location, serviceName, source string, port int32, allowPublicAccess bool) error DeleteService(ctx context.Context, projectID, location, serviceName string) error SetServiceAccess(ctx context.Context, serviceName string, allowPublicAccess bool) error + GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) } // NewCloudRunClient creates a new CloudRunClient. @@ -144,6 +145,18 @@ func (c *CloudRunClientImpl) GetService(ctx context.Context, projectID, location return service, nil } +func (c *CloudRunClientImpl) GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { + service, err := c.GetService(ctx, projectID, location, serviceName) + if err != nil { + return nil, fmt.Errorf("failed to get service: %w", err) + } + terminalCondition := service.GetTerminalCondition() + if terminalCondition == nil { + return nil, fmt.Errorf("service %q does not have a terminal condition", service.Name) + } + return &terminalCondition.State, nil +} + func (c *CloudRunClientImpl) GetRevision(ctx context.Context, service *cloudrunpb.Service) (*cloudrunpb.Revision, error) { // Get the latest revision latestRevision, err := c.revisionsClient.GetRevision(ctx, &cloudrunpb.GetRevisionRequest{Name: service.LatestReadyRevision}) diff --git a/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go b/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go index fdb6cd1..f2d9f03 100644 --- a/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go +++ b/devops-mcp-server/cloudrun/client/mocks/mock_cloudrunclient.go @@ -30,6 +30,7 @@ type MockCloudRunClient struct { DeployFromSourceFunc func(ctx context.Context, projectID, location, serviceName, source string, port int32, allowPublicAccess bool) error DeleteServiceFunc func(ctx context.Context, projectID, location, serviceName string) error SetServiceAccessFunc func(ctx context.Context, serviceName string, allowPublicAccess bool) error + GetServiceStatusFunc func(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) } // DeleteService mocks the DeleteService method. @@ -70,3 +71,8 @@ func (m *MockCloudRunClient) DeployFromSource(ctx context.Context, projectID, lo func (m *MockCloudRunClient) SetServiceAccess(ctx context.Context, serviceName string, allowPublicAccess bool) error { return m.SetServiceAccessFunc(ctx, serviceName, allowPublicAccess) } + +// GetServiceStatus mocks the GetServiceStatus method. +func (m *MockCloudRunClient) GetServiceStatus(ctx context.Context, projectID, location, serviceName string) (*cloudrunpb.Condition_State, error) { + return m.GetServiceStatusFunc(ctx, projectID, location, serviceName) +} diff --git a/devops-mcp-server/cloudrun/cloudrun.go b/devops-mcp-server/cloudrun/cloudrun.go index a174223..1f5761f 100644 --- a/devops-mcp-server/cloudrun/cloudrun.go +++ b/devops-mcp-server/cloudrun/cloudrun.go @@ -36,6 +36,7 @@ func (h *Handler) Register(server *mcp.Server) { addListServicesTool(server, h.CrClient) addDeployToCloudRunFromImageTool(server, h.CrClient) addDeployToCloudRunFromSourceTool(server, h.CrClient) + addGetServiceStatusTool(server, h.CrClient) } type ListServicesArgs struct { @@ -134,3 +135,22 @@ func addDeployToCloudRunFromSourceTool(server *mcp.Server, crClient cloudrunclie } mcp.AddTool(server, &mcp.Tool{Name: "cloudrun.deploy_to_cloud_run_from_source", Description: "Creates a new Cloud Run service or updates an existing one from source. This tool may take a couple minutes to finish running."}, deployToCloudRunFromSourceToolFunc) } + +type GetServiceStatusArgs struct{ + ProjectID string `json:"project_id" jsonschema:"The Google Cloud project ID."` + Location string `json:"location" jsonschema:"The Google Cloud location."` + ServiceName string `json:"service_name" jsonschema:"The Cloud Run service name"` +} + +var getServiceStatusToolFunc func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) + +func addGetServiceStatusTool(server *mcp.Server, crClient cloudrunclient.CloudRunClient) { + getServiceStatusToolFunc = func(ctx context.Context, req *mcp.CallToolRequest, args GetServiceStatusArgs) (*mcp.CallToolResult, any, error) { + state, err := crClient.GetServiceStatus(ctx, args.ProjectID, args.Location, args.ServiceName) + if err != nil { + return &mcp.CallToolResult{}, nil, fmt.Errorf("failed to get service state: %w", err) + } + return &mcp.CallToolResult{}, state, nil + } + mcp.AddTool(server, &mcp.Tool{Name: "cloudrun.service_status", Description: "Gets the current status of a Cloud Run service."}, getServiceStatusToolFunc) +}