Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion components/public-api-server/BUILD.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ packages:
deps:
- components/common-go:lib
- components/public-api/go:lib
- components/usage-api/go:lib
- components/gitpod-protocol/go:lib
env:
- CGO_ENABLED=0
Expand All @@ -29,4 +30,4 @@ packages:
helm-component: public-api-server
image:
- ${imageRepoBase}/public-api-server:${version}
- ${imageRepoBase}/public-api-server:commit-${__git_commit}
- ${imageRepoBase}/public-api-server:commit-${__git_commit}
5 changes: 4 additions & 1 deletion components/public-api-server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000
github.com/gitpod-io/gitpod/gitpod-protocol v0.0.0-00010101000000-000000000000
github.com/gitpod-io/gitpod/public-api v0.0.0-00010101000000-000000000000
github.com/gitpod-io/gitpod/usage-api v0.0.0-00010101000000-000000000000
github.com/golang/mock v1.6.0
github.com/google/go-cmp v0.5.7
github.com/gorilla/handlers v1.5.1
Expand All @@ -17,7 +18,7 @@ require (
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.0
github.com/stripe/stripe-go/v72 v72.122.0
google.golang.org/grpc v1.45.0
google.golang.org/grpc v1.47.0
google.golang.org/protobuf v1.28.0
)

Expand Down Expand Up @@ -57,6 +58,8 @@ replace github.com/gitpod-io/gitpod/gitpod-protocol => ../gitpod-protocol/go //

replace github.com/gitpod-io/gitpod/public-api => ../public-api/go // leeway

replace github.com/gitpod-io/gitpod/usage-api => ../usage-api/go // leeway

replace k8s.io/api => k8s.io/api v0.23.5 // leeway indirect from components/common-go:lib

replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.23.5 // leeway indirect from components/common-go:lib
Expand Down
11 changes: 7 additions & 4 deletions components/public-api-server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand All @@ -70,7 +70,7 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
Expand Down Expand Up @@ -129,6 +129,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down Expand Up @@ -385,6 +386,7 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -523,8 +525,8 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand All @@ -537,6 +539,7 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY=
Expand Down
40 changes: 40 additions & 0 deletions components/public-api-server/pkg/billingservice/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package billingservice

import (
"context"
"fmt"

"github.com/gitpod-io/gitpod/usage-api/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)

type Interface interface {
FinalizeInvoice(ctx context.Context, invoiceId string) error
}

type Client struct {
b v1.BillingServiceClient
}

func New(billingServiceAddress string) (*Client, error) {
conn, err := grpc.Dial(billingServiceAddress, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, fmt.Errorf("failed to dial billing service gRPC server: %w", err)
}

return &Client{b: v1.NewBillingServiceClient(conn)}, nil
}

func (c *Client) FinalizeInvoice(ctx context.Context, invoiceId string) error {
_, err := c.b.FinalizeInvoice(ctx, &v1.FinalizeInvoiceRequest{InvoiceId: invoiceId})
if err != nil {
return fmt.Errorf("failed RPC to billing service: %s", err)
}

return nil
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions components/public-api-server/pkg/billingservice/noop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License-AGPL.txt in the project root for license information.

package billingservice

import "context"

type NoOpClient struct{}

func (c *NoOpClient) FinalizeInvoice(ctx context.Context, invoiceId string) error {
return nil
}
11 changes: 10 additions & 1 deletion components/public-api-server/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/gitpod-io/gitpod/common-go/baseserver"
"github.com/gitpod-io/gitpod/public-api-server/pkg/apiv1"
"github.com/gitpod-io/gitpod/public-api-server/pkg/billingservice"
"github.com/gitpod-io/gitpod/public-api-server/pkg/proxy"
"github.com/gitpod-io/gitpod/public-api-server/pkg/webhooks"
v1 "github.com/gitpod-io/gitpod/public-api/v1"
Expand All @@ -39,8 +40,16 @@ func Start(logger *logrus.Entry, cfg *config.Configuration) error {
return fmt.Errorf("failed to initialize public api server: %w", err)
}

var billingService billingservice.Interface = &billingservice.NoOpClient{}
if cfg.BillingServiceAddress != "" {
billingService, err = billingservice.New(cfg.BillingServiceAddress)
if err != nil {
return fmt.Errorf("failed to initialize billing service client: %w", err)
}
}

srv.HTTPMux().Handle("/stripe/invoices/webhook",
handlers.ContentTypeHandler(webhooks.NewStripeWebhookHandler(), "application/json"),
handlers.ContentTypeHandler(webhooks.NewStripeWebhookHandler(billingService), "application/json"),
)

if registerErr := register(srv, gitpodAPI, registry); registerErr != nil {
Expand Down
16 changes: 12 additions & 4 deletions components/public-api-server/pkg/webhooks/stripe.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import (
"net/http"

"github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/public-api-server/pkg/billingservice"
"github.com/stripe/stripe-go/v72"
)

type webhookHandler struct{}
type webhookHandler struct {
billingService billingservice.Interface
}

func NewStripeWebhookHandler() *webhookHandler {
return &webhookHandler{}
func NewStripeWebhookHandler(billingService billingservice.Interface) *webhookHandler {
return &webhookHandler{billingService: billingService}
}

func (h *webhookHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -52,5 +55,10 @@ func (h *webhookHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusBadRequest)
}

log.Infof("finalizing invoice for invoice id: %s", invoiceId)
err = h.billingService.FinalizeInvoice(req.Context(), invoiceId)
if err != nil {
log.WithError(err).Error("Failed to finalize invoice")
w.WriteHeader(http.StatusInternalServerError)
return
}
}
32 changes: 28 additions & 4 deletions components/public-api-server/pkg/webhooks/stripe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
"testing"

"github.com/gitpod-io/gitpod/common-go/baseserver"
"github.com/gitpod-io/gitpod/public-api-server/pkg/billingservice"
mockbillingservice "github.com/gitpod-io/gitpod/public-api-server/pkg/billingservice/mock_billingservice"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -41,7 +44,7 @@ func TestWebhookAcceptsPostRequests(t *testing.T) {
},
}

srv := baseServerWithStripeWebhook(t)
srv := baseServerWithStripeWebhook(t, &billingservice.NoOpClient{})

payload := payloadForStripeEvent(t, invoiceFinalizedEventType)

Expand Down Expand Up @@ -79,7 +82,7 @@ func TestWebhookIgnoresIrrelevantEvents(t *testing.T) {
},
}

srv := baseServerWithStripeWebhook(t)
srv := baseServerWithStripeWebhook(t, &billingservice.NoOpClient{})

url := fmt.Sprintf("%s%s", srv.HTTPAddress(), "/webhook")

Expand All @@ -97,15 +100,36 @@ func TestWebhookIgnoresIrrelevantEvents(t *testing.T) {
}
}

func baseServerWithStripeWebhook(t *testing.T) *baseserver.Server {
// TestWebhookInvokesFinalizeInvoiceRPC ensures that when the webhook is hit with a
// `invoice.finalized` event, the `FinalizeInvoice` method on the billing service is invoked
// with the invoice id from the event payload.
func TestWebhookInvokesFinalizeInvoiceRPC(t *testing.T) {
ctrl := gomock.NewController(t)
m := mockbillingservice.NewMockInterface(ctrl)
m.EXPECT().FinalizeInvoice(gomock.Any(), gomock.Eq("in_1LUQi7GadRXm50o36jWK7ehs"))

srv := baseServerWithStripeWebhook(t, m)

url := fmt.Sprintf("%s%s", srv.HTTPAddress(), "/webhook")

payload := payloadForStripeEvent(t, invoiceFinalizedEventType)
req, err := http.NewRequest(http.MethodPost, url, payload)
require.NoError(t, err)

resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
}

func baseServerWithStripeWebhook(t *testing.T, billingService billingservice.Interface) *baseserver.Server {
t.Helper()

srv := baseserver.NewForTests(t,
baseserver.WithHTTP(baseserver.MustUseRandomLocalAddress(t)),
)
baseserver.StartServerForTests(t, srv)

srv.HTTPMux().Handle("/webhook", NewStripeWebhookHandler())
srv.HTTPMux().Handle("/webhook", NewStripeWebhookHandler(billingService))

return srv
}
Expand Down
2 changes: 2 additions & 0 deletions components/public-api/go/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@ import "github.com/gitpod-io/gitpod/common-go/baseserver"
type Configuration struct {
GitpodServiceURL string `json:"gitpodServiceUrl"`

BillingServiceAddress string `json:"billingServiceAddress,omitempty"`

Server *baseserver.Configuration `json:"server,omitempty"`
}
1 change: 1 addition & 0 deletions install/installer/pkg/common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const (
ServerComponent = "server"
ServerInstallationAdminPort = 9000
SystemNodeCritical = "system-node-critical"
PublicApiComponent = "public-api-server"
WSManagerComponent = "ws-manager"
WSManagerBridgeComponent = "ws-manager-bridge"
WSProxyComponent = "ws-proxy"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ package public_api_server

import (
"fmt"
"net"
"strconv"

"github.com/gitpod-io/gitpod/common-go/baseserver"
"github.com/gitpod-io/gitpod/public-api/config"

"github.com/gitpod-io/gitpod/installer/pkg/common"
"github.com/gitpod-io/gitpod/installer/pkg/components/usage"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -22,7 +25,8 @@ const (

func configmap(ctx *common.RenderContext) ([]runtime.Object, error) {
cfg := config.Configuration{
GitpodServiceURL: fmt.Sprintf("wss://%s/api/v1", ctx.Config.Domain),
GitpodServiceURL: fmt.Sprintf("wss://%s/api/v1", ctx.Config.Domain),
BillingServiceAddress: net.JoinHostPort(usage.Component, strconv.Itoa(usage.GRPCServicePort)),
Server: &baseserver.Configuration{
Services: baseserver.ServicesConfiguration{
GRPC: &baseserver.ServerConfiguration{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ func TestConfigMap(t *testing.T) {
require.Len(t, objs, 1, "must only render one configmap")

expectedConfiguration := config.Configuration{
GitpodServiceURL: "wss://test.domain.everything.awesome.is/api/v1",
GitpodServiceURL: "wss://test.domain.everything.awesome.is/api/v1",
BillingServiceAddress: "usage:9001",
Server: &baseserver.Configuration{
Services: baseserver.ServicesConfiguration{
GRPC: &baseserver.ServerConfiguration{
Expand Down
7 changes: 7 additions & 0 deletions install/installer/pkg/components/usage/networkpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ func networkpolicy(ctx *common.RenderContext) ([]runtime.Object, error) {
},
},
},
{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"component": common.PublicApiComponent,
},
},
},
},
},
},
Expand Down