Skip to content

Commit

Permalink
Merge branch 'master' into add-app-name-to-parse-api
Browse files Browse the repository at this point in the history
  • Loading branch information
d-g-town authored Sep 19, 2023
2 parents 1825f68 + e34ed7d commit a250b15
Show file tree
Hide file tree
Showing 30 changed files with 1,722 additions and 314 deletions.
4 changes: 2 additions & 2 deletions api/server/handlers/environment_groups/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ type ListEnvironmentGroupsResponse struct {
type EnvironmentGroupListItem struct {
Name string `json:"name"`
LatestVersion int `json:"latest_version"`
Variables map[string]string `json:"variables"`
SecretVariables map[string]string `json:"secret_variables"`
Variables map[string]string `json:"variables,omitempty"`
SecretVariables map[string]string `json:"secret_variables,omitempty"`
CreatedAtUTC time.Time `json:"created_at"`
LinkedApplications []string `json:"linked_applications,omitempty"`
}
Expand Down
9 changes: 5 additions & 4 deletions api/server/handlers/porter_app/get_app_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ func (c *GetAppEnvHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}

envFromProtoInp := porter_app.AppEnvironmentFromProtoInput{
ProjectID: project.ID,
ClusterID: int(cluster.ID),
App: appProto,
K8SAgent: agent,
ProjectID: project.ID,
ClusterID: int(cluster.ID),
App: appProto,
K8SAgent: agent,
DeploymentTargetRepository: c.Repo().DeploymentTarget(),
}

envGroups, err := porter_app.AppEnvironmentFromProto(ctx, envFromProtoInp, porter_app.WithEnvGroupFilter(request.EnvGroups), porter_app.WithSecrets())
Expand Down
112 changes: 112 additions & 0 deletions api/server/handlers/porter_app/pod_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package porter_app

import (
"net/http"

"connectrpc.com/connect"
porterv1 "github.com/porter-dev/api-contracts/generated/go/porter/v1"
"github.com/porter-dev/porter/api/server/authz"
"github.com/porter-dev/porter/api/server/handlers"
"github.com/porter-dev/porter/api/server/shared"
"github.com/porter-dev/porter/api/server/shared/apierrors"
"github.com/porter-dev/porter/api/server/shared/config"
"github.com/porter-dev/porter/api/types"
"github.com/porter-dev/porter/internal/models"
"github.com/porter-dev/porter/internal/telemetry"
v1 "k8s.io/api/core/v1"
)

// PodStatusHandler is the handler for GET /apps/pods
type PodStatusHandler struct {
handlers.PorterHandlerReadWriter
authz.KubernetesAgentGetter
}

// NewPodStatusHandler returns a new PodStatusHandler
func NewPodStatusHandler(
config *config.Config,
decoderValidator shared.RequestDecoderValidator,
writer shared.ResultWriter,
) *PodStatusHandler {
return &PodStatusHandler{
PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
KubernetesAgentGetter: authz.NewOutOfClusterAgentGetter(config),
}
}

// PodStatusRequest is the expected format for a request body on GET /apps/pods
type PodStatusRequest struct {
DeploymentTargetID string `schema:"deployment_target_id"`
Selectors string `schema:"selectors"`
}

func (c *PodStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx, span := telemetry.NewSpan(r.Context(), "serve-pod-status")
defer span.End()

request := &PodStatusRequest{}
if ok := c.DecodeAndValidate(w, r, request); !ok {
err := telemetry.Error(ctx, span, nil, "invalid request")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
return
}

cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
project, _ := r.Context().Value(types.ProjectScope).(*models.Project)

telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "selectors", Value: request.Selectors})

if request.DeploymentTargetID == "" {
err := telemetry.Error(ctx, span, nil, "must provide deployment target id")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
return
}
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "deployment-target-id", Value: request.DeploymentTargetID})

deploymentTargetDetailsReq := connect.NewRequest(&porterv1.DeploymentTargetDetailsRequest{
ProjectId: int64(project.ID),
DeploymentTargetId: request.DeploymentTargetID,
})

deploymentTargetDetailsResp, err := c.Config().ClusterControlPlaneClient.DeploymentTargetDetails(ctx, deploymentTargetDetailsReq)
if err != nil {
err := telemetry.Error(ctx, span, err, "error getting deployment target details from cluster control plane client")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
return
}

if deploymentTargetDetailsResp == nil || deploymentTargetDetailsResp.Msg == nil {
err := telemetry.Error(ctx, span, err, "deployment target details resp is nil")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
return
}

if deploymentTargetDetailsResp.Msg.ClusterId != int64(cluster.ID) {
err := telemetry.Error(ctx, span, err, "deployment target details resp cluster id does not match cluster id")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
return
}

namespace := deploymentTargetDetailsResp.Msg.Namespace
telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "namespace", Value: namespace})

agent, err := c.GetAgent(r, cluster, "")
if err != nil {
err = telemetry.Error(ctx, span, err, "unable to get agent")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
return
}

pods := []v1.Pod{}

podsList, err := agent.GetPodsByLabel(request.Selectors, namespace)
if err != nil {
err = telemetry.Error(ctx, span, err, "unable to get pods by label")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
return
}

pods = append(pods, podsList.Items...)

c.WriteResult(w, r, pods)
}
71 changes: 71 additions & 0 deletions api/server/handlers/porter_app/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package porter_app

import (
"net/http"

"github.com/porter-dev/porter/api/server/authz"
"github.com/porter-dev/porter/api/server/handlers"
"github.com/porter-dev/porter/api/server/shared"
"github.com/porter-dev/porter/api/server/shared/apierrors"
"github.com/porter-dev/porter/api/server/shared/config"
"github.com/porter-dev/porter/api/server/shared/requestutils"
"github.com/porter-dev/porter/api/server/shared/websocket"
"github.com/porter-dev/porter/api/types"
"github.com/porter-dev/porter/internal/models"
"github.com/porter-dev/porter/internal/telemetry"
)

// AppStatusHandler handles the /apps/{kind}/status endpoint
type AppStatusHandler struct {
handlers.PorterHandlerReadWriter
authz.KubernetesAgentGetter
}

// NewAppStatusHandler returns a new AppStatusHandler
func NewAppStatusHandler(
config *config.Config,
decoderValidator shared.RequestDecoderValidator,
writer shared.ResultWriter,
) *AppStatusHandler {
return &AppStatusHandler{
PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
KubernetesAgentGetter: authz.NewOutOfClusterAgentGetter(config),
}
}

// AppStatusRequest represents the accepted fields on a request to the /apps/{kind}/status endpoint
type AppStatusRequest struct {
Selectors string `schema:"selectors"`
}

func (c *AppStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx, span := telemetry.NewSpan(r.Context(), "serve-app-logs")
defer span.End()

safeRW := ctx.Value(types.RequestCtxWebsocketKey).(*websocket.WebsocketSafeReadWriter)
request := &AppStatusRequest{}

if ok := c.DecodeAndValidate(w, r, request); !ok {
err := telemetry.Error(ctx, span, nil, "invalid request")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))
return
}

cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)

agent, err := c.GetAgent(r, cluster, "")
if err != nil {
err = telemetry.Error(ctx, span, err, "unable to get agent")
c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
return
}

kind, _ := requestutils.GetURLParamString(r, types.URLParamKind)

err = agent.StreamControllerStatus(kind, request.Selectors, safeRW)

if err != nil {
c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
return
}
}
2 changes: 2 additions & 0 deletions api/server/handlers/porter_app/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func NewValidatePorterAppHandler(
type Deletions struct {
ServiceNames []string `json:"service_names"`
EnvVariableNames []string `json:"env_variable_names"`
EnvGroupNames []string `json:"env_group_names"`
}

// ValidatePorterAppRequest is the request object for the /apps/validate endpoint
Expand Down Expand Up @@ -128,6 +129,7 @@ func (c *ValidatePorterAppHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
Deletions: &porterv1.Deletions{
ServiceNames: request.Deletions.ServiceNames,
EnvVariableNames: request.Deletions.EnvVariableNames,
EnvGroupNames: request.Deletions.EnvGroupNames,
},
})
ccpResp, err := c.Config().ClusterControlPlaneClient.ValidatePorterApp(ctx, validateReq)
Expand Down
Loading

0 comments on commit a250b15

Please sign in to comment.