package router import ( "fmt" "github.com/go-chi/chi/v5" "github.com/porter-dev/porter/api/server/handlers/porter_app" "github.com/porter-dev/porter/api/server/shared" "github.com/porter-dev/porter/api/server/shared/config" "github.com/porter-dev/porter/api/server/shared/router" "github.com/porter-dev/porter/api/types" ) func NewStackScopedRegisterer(children ...*router.Registerer) *router.Registerer { return &router.Registerer{ GetRoutes: GetStackScopedRoutes, Children: children, } } func GetStackScopedRoutes( r chi.Router, config *config.Config, basePath *types.Path, factory shared.APIEndpointFactory, children ...*router.Registerer, ) []*router.Route { routes, projPath := getStackRoutes(r, config, basePath, factory) if len(children) > 0 { r.Route(projPath.RelativePath, func(r chi.Router) { for _, child := range children { childRoutes := child.GetRoutes(r, config, basePath, factory, child.Children...) routes = append(routes, childRoutes...) } }) } return routes } func getStackRoutes( r chi.Router, config *config.Config, basePath *types.Path, factory shared.APIEndpointFactory, ) ([]*router.Route, *types.Path) { relPath := "/stacks" newPath := &types.Path{ Parent: basePath, RelativePath: relPath, } var routes []*router.Route // GET /api/projects/{project_id}/clusters/{cluster_id}/stacks/{name} -> porter_app.NewPorterAppGetHandler getPorterAppEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbGet, Method: types.HTTPVerbGet, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) getPorterAppHandler := porter_app.NewGetPorterAppHandler( config, factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: getPorterAppEndpoint, Handler: getPorterAppHandler, Router: r, }) // GET /api/projects/{project_id}/clusters/{cluster_id}/stacks/{name} -> porter_app.NewPorterAppListHandler listPorterAppEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbList, Method: types.HTTPVerbGet, Path: &types.Path{ Parent: basePath, RelativePath: relPath, }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) listPorterAppHandler := porter_app.NewPorterAppListHandler( config, factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: listPorterAppEndpoint, Handler: listPorterAppHandler, Router: r, }) // DELETE /api/projects/{project_id}/clusters/{cluster_id}/stacks -> release.NewDeletePorterAppByNameHandler deletePorterAppByNameEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbDelete, Method: types.HTTPVerbDelete, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) deletePorterAppByNameHandler := porter_app.NewDeletePorterAppByNameHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: deletePorterAppByNameEndpoint, Handler: deletePorterAppByNameHandler, Router: r, }) // POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/{stack} -> porter_app.NewCreatePorterAppHandler createPorterAppEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbCreate, Method: types.HTTPVerbPost, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) createPorterAppHandler := porter_app.NewCreatePorterAppHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: createPorterAppEndpoint, Handler: createPorterAppHandler, Router: r, }) // POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/{stack}/rollback -> porter_app.NewRollbackPorterAppHandler rollbackPorterAppEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbCreate, Method: types.HTTPVerbPost, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}/rollback", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) rollbackPorterAppHandler := porter_app.NewRollbackPorterAppHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: rollbackPorterAppEndpoint, Handler: rollbackPorterAppHandler, Router: r, }) // POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/{stack}/pr -> porter_app.NewOpenStackPRHandler createSecretAndOpenGitHubPullRequestEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbCreate, Method: types.HTTPVerbPost, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}/pr", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) createSecretAndOpenGitHubPullRequestHandler := porter_app.NewOpenStackPRHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: createSecretAndOpenGitHubPullRequestEndpoint, Handler: createSecretAndOpenGitHubPullRequestHandler, Router: r, }) // GET /api/projects/{project_id}/clusters/{cluster_id}/stacks/{name}/events -> porter_app.NewPorterAppEventListHandler listPorterAppEventsEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbList, Method: types.HTTPVerbGet, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}/events", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) listPorterAppEventsHandler := porter_app.NewPorterAppEventListHandler( config, factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: listPorterAppEventsEndpoint, Handler: listPorterAppEventsHandler, Router: r, }) // POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/{name}/events -> porter_app.NewCreatePorterAppEventHandler createPorterAppEventEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbCreate, Method: types.HTTPVerbPost, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/{%s}/events", relPath, types.URLParamStackName), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) createPorterAppEventHandler := porter_app.NewCreateUpdatePorterAppEventHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: createPorterAppEventEndpoint, Handler: createPorterAppEventHandler, Router: r, }) // GET /api/projects/{project_id}/clusters/{cluster_id}/events/id -> porter_app.NewGetPorterAppEventHandler getPorterAppEventEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbCreate, Method: types.HTTPVerbGet, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("/events/{%s}", types.URLParamPorterAppEventID), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) getPorterAppEventHandler := porter_app.NewGetPorterAppEventHandler( config, factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: getPorterAppEventEndpoint, Handler: getPorterAppEventHandler, Router: r, }) // POST /api/projects/{project_id}/clusters/{cluster_id}/stacks/analytics -> porter_app.NewPorterAppAnalyticsHandler porterAppAnalyticsEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbUpdate, Method: types.HTTPVerbPost, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/analytics", relPath), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) porterAppAnalyticsHandler := porter_app.NewPorterAppAnalyticsHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: porterAppAnalyticsEndpoint, Handler: porterAppAnalyticsHandler, Router: r, }) // GET /api/projects/{project_id}/clusters/{cluster_id}/stacks/logs -> cluster.NewGetChartLogsWithinTimeRangeHandler getChartLogsWithinTimeRangeEndpoint := factory.NewAPIEndpoint( &types.APIRequestMetadata{ Verb: types.APIVerbGet, Method: types.HTTPVerbGet, Path: &types.Path{ Parent: basePath, RelativePath: fmt.Sprintf("%s/logs", relPath), }, Scopes: []types.PermissionScope{ types.UserScope, types.ProjectScope, types.ClusterScope, }, }, ) getChartLogsWithinTimeRangeHandler := porter_app.NewGetLogsWithinTimeRangeHandler( config, factory.GetDecoderValidator(), factory.GetResultWriter(), ) routes = append(routes, &router.Route{ Endpoint: getChartLogsWithinTimeRangeEndpoint, Handler: getChartLogsWithinTimeRangeHandler, Router: r, }) return routes, newPath }