Skip to content

Commit

Permalink
support cloudsql and rds (#33)
Browse files Browse the repository at this point in the history
* init support for cloudsql

* update cloudsql package

* update cloudsql package

* skip replica instance

* init support for rds instances

* pause rds custom automation

* update docs
  • Loading branch information
jacobnguyenn committed Sep 8, 2023
1 parent f7841b9 commit a2d3dd5
Show file tree
Hide file tree
Showing 19 changed files with 416 additions and 66 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,4 @@ app
volume
.env
local-env.sh
local.sh
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ Scheduler for compute instances across clouds. A Golang port of [Doiintl's Zorya
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://raw.githubusercontent.com/nduyphuong/gorya/dev/LICENSE)
[![Build status](https://github.com/nduyphuong/gorya/actions/workflows/release.yml/badge.svg)](https://github.com/nduyphuong/gorya/actions)

# Support Resources
- AWS:
- [X] EC2
- [X] RDS
- [ ] EKS
- GCP:
- [X] EC2
- [X] CLOUDSQL
- [ ] GKE
## Building Gorya

### Software requirements
Expand Down
30 changes: 15 additions & 15 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ services:
networks:
- gorya

gorya-ui:
# image: ghcr.io/nduyphuong/gorya-ui
container_name: gorya-ui
ports:
- "3000:3000"
build:
context: .
dockerfile: frontend.Dockerfile
environment:
NODE_OPTIONS: --openssl-legacy-provider
GORYA_API_ADDR: http://gorya-backend:9000
depends_on:
- gorya-backend
networks:
- gorya
# gorya-ui:
# # image: ghcr.io/nduyphuong/gorya-ui
# container_name: gorya-ui
# ports:
# - "3000:3000"
# build:
# context: .
# dockerfile: frontend.Dockerfile
# environment:
# NODE_OPTIONS: --openssl-legacy-provider
# GORYA_API_ADDR: http://gorya-backend:9000
# depends_on:
# - gorya-backend
# networks:
# - gorya

keycloak:
image: koolwithk/keycloak-arm:16.0.0
Expand Down
10 changes: 6 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module github.com/nduyphuong/gorya
go 1.20

require (
github.com/aws/aws-sdk-go-v2 v1.20.3
github.com/aws/aws-sdk-go-v2 v1.21.0
github.com/aws/aws-sdk-go-v2/config v1.18.35
github.com/aws/aws-sdk-go-v2/credentials v1.13.34
github.com/aws/aws-sdk-go-v2/service/ec2 v1.113.1
github.com/aws/aws-sdk-go-v2/service/rds v1.54.0
github.com/aws/aws-sdk-go-v2/service/sts v1.21.4
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/go-redis/redis/v8 v8.11.5
Expand All @@ -19,6 +20,7 @@ require (
github.com/stretchr/testify v1.8.4
golang.org/x/net v0.14.0
golang.org/x/oauth2 v0.11.0
golang.org/x/sync v0.2.0
google.golang.org/api v0.126.0
gorm.io/datatypes v1.2.0
gorm.io/driver/mysql v1.5.1
Expand All @@ -30,10 +32,10 @@ require (
cloud.google.com/go/compute v1.20.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.40 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.34 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.41 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.34 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.13.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.4 // indirect
github.com/aws/smithy-go v1.14.2 // indirect
Expand Down
15 changes: 11 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,30 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aws/aws-sdk-go-v2 v1.20.3 h1:lgeKmAZhlj1JqN43bogrM75spIvYnRxqTAh1iupu1yE=
github.com/aws/aws-sdk-go-v2 v1.20.3/go.mod h1:/RfNgGmRxI+iFOB1OeJUyxiU+9s88k3pfHvDagGEp0M=
github.com/aws/aws-sdk-go-v2 v1.21.0 h1:gMT0IW+03wtYJhRqTVYn0wLzwdnK9sRMcxmtfGzRdJc=
github.com/aws/aws-sdk-go-v2 v1.21.0/go.mod h1:/RfNgGmRxI+iFOB1OeJUyxiU+9s88k3pfHvDagGEp0M=
github.com/aws/aws-sdk-go-v2/config v1.18.35 h1:uU9rgCzrW/pVRUUlRULiwKQe8RoEDst1NQu4Qo8kOtk=
github.com/aws/aws-sdk-go-v2/config v1.18.35/go.mod h1:7xF1yr9GBMfYRQI4PLHO8iceqKLM6DpGVEvXI38HB/A=
github.com/aws/aws-sdk-go-v2/credentials v1.13.34 h1:/EYG4lzayDd5PY6HQQ2Qyj/cD6CR3kz96BjTZAO5tNo=
github.com/aws/aws-sdk-go-v2/credentials v1.13.34/go.mod h1:+wgdxCGNulHme6kTMZuDL9KOagLPloemoYkfjpQkSEU=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.10 h1:mgOrtwYfJZ4e3QJe1TrliC/xIkauafGMdLLuCExOqcs=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.10/go.mod h1:wMsSLVM2hRpDVhd+3dtLUzqwm7/fjuhNN+b1aOLDt6g=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.40 h1:CXceCS9BrDInRc74GDCQ8Qyk/Gp9VLdK+Rlve+zELSE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.40/go.mod h1:5kKmFhLeOVy6pwPDpDNA6/hK/d6URC98pqDDqHgdBx4=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.34 h1:B+nZtd22cbko5+793hg7LEaTeLMiZwlgCLUrN5Y0uzg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41 h1:22dGT7PneFMx4+b3pz7lMTRyN8ZKH7M2cW4GP9yUS2g=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.41/go.mod h1:CrObHAuPneJBlfEJ5T3szXOUkLEThaGfvnhTf33buas=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.34/go.mod h1:RZP0scceAyhMIQ9JvFp7HvkpcgqjL4l/4C+7RAeGbuM=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35 h1:SijA0mgjV8E+8G45ltVHs0fvKpTj8xmZJ3VwhGKtUSI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.35/go.mod h1:SJC1nEVVva1g3pHAIdCp7QsRIkMmLAgoDquQ9Rr8kYw=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.41 h1:EcSFdpLdkF3FWizimox0qYLuorn9e4PNMR27mvshGLs=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.41/go.mod h1:mKxUXW+TuwpCKKHVlmHGVVuBi9y9LKW8AiQodg23M5E=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.113.1 h1:2wyKWQM+5+lMaSNU9RCwIVNRYJZjiXdNUJfavh5hCTM=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.113.1/go.mod h1:YBN5ov75u3UBgWKzV9ZlXu+Jb9oLoA2MqrAVJjaHGLc=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.34 h1:JwvXk+1ePAD9xkFHprhHYqwsxLDcbNFsPI1IAT2sPS0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.34/go.mod h1:ytsF+t+FApY2lFnN51fJKPhH6ICKOPXKEcwwgmJEdWI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35 h1:CdzPW9kKitgIiLV1+MHobfR5Xg25iYnyzWZhyQuSlDI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.35/go.mod h1:QGF2Rs33W5MaN9gYdEQOBBFPLwTZkEhRwI33f7KIG0o=
github.com/aws/aws-sdk-go-v2/service/rds v1.54.0 h1:FmExQnV6PXPAwP2DT3nXlWyKtCJ30gCEQIu4MUOuESo=
github.com/aws/aws-sdk-go-v2/service/rds v1.54.0/go.mod h1:UNv1vk1fU1NJefzteykVpVLA88w4WxB05g3vp2kQhYM=
github.com/aws/aws-sdk-go-v2/service/sso v1.13.4 h1:WZPZ7Zf6Yo13lsfTetFrLU/7hZ9CXESDpdIHvmLxQFQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.13.4/go.mod h1:FP05hDXTLouXwAMQ1swqybHy7tHySblMkBMKSumaKg0=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.15.4 h1:pYFM2U/3/4RLrlMSYXwL1XPBCWvaePk2p+0+i/BgHOs=
Expand Down Expand Up @@ -217,6 +223,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
6 changes: 4 additions & 2 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func (s *server) Serve(ctx context.Context, l net.Listener) error {
providers := strings.Split(os.GetEnv("GORYA_ENABLED_PROVIDERS", ""), ",")
ticker := time.NewTicker(30 * time.Second)
for _, provider := range providers {
provider = strings.ToLower(provider)
if provider != constants.PROVIDER_AWS && provider != constants.PROVIDER_GCP && provider != constants.PROVIDER_AZURE {
continue
}
Expand All @@ -89,7 +90,7 @@ func (s *server) Serve(ctx context.Context, l net.Listener) error {
}
}
}
//c.credentialRef["arn:aws:iam::043159268388:role/test"] = true
// c.credentialRef["arn:aws:iam::043159268388:role/test"] = true
s.aws, err = aws.NewPool(
ctx,
c.credentialRef,
Expand Down Expand Up @@ -132,6 +133,7 @@ func (s *server) Serve(ctx context.Context, l net.Listener) error {
}
}
}
c.credentialRef["[email protected]"] = true
s.gcp, err = gcp.NewPool(
ctx,
c.credentialRef,
Expand Down Expand Up @@ -166,7 +168,7 @@ func (s *server) Serve(ctx context.Context, l net.Listener) error {
PopInterval: 2 * time.Second,
},
})
path, svcHandler := svcv1alpha1.NewGoryaServiceHandler(ctx, s.sc, s)
path, svcHandler := svcv1alpha1.NewGoryaServiceHandler(ctx, s)
mux.Handle(path, svcHandler)
srv := &http.Server{
Handler: h2c.NewHandler(mux, &http2.Server{}),
Expand Down
54 changes: 31 additions & 23 deletions internal/api/handler/change_state_v1alpha1.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,38 @@ func ChangeStateV1alpha1(ctx context.Context, awsClientPool *aws.ClientPool, gcp
http.Error(w, pkgerrors.Wrap(err, "decode state change request body").Error(), http.StatusBadRequest)
return
}
if awsClientPool != nil && m.Provider == constants.PROVIDER_AWS {
awsClient, ok := awsClientPool.GetForCredential(m.CredentialRef)
if !ok {
http.Error(w, fmt.Errorf("client not found for credential %v", m.CredentialRef).Error(),
http.StatusBadRequest)
return
switch m.Provider {
case constants.PROVIDER_AWS:
if awsClientPool != nil {
awsClient, ok := awsClientPool.GetForCredential(m.CredentialRef)
if !ok {
http.Error(w, fmt.Errorf("client not found for credential %v", m.CredentialRef).Error(),
http.StatusBadRequest)
return
}
compute := awsClient.EC2()
if err := compute.ChangeStatus(ctx, m.Action, m.TagKey, m.TagValue); err != nil {
http.Error(w, pkgerrors.Wrap(err, "change compute status").Error(), http.StatusInternalServerError)
return
}
}
compute := awsClient.EC2()
if err := compute.ChangeStatus(ctx, m.Action, m.TagKey, m.TagValue); err != nil {
http.Error(w, pkgerrors.Wrap(err, "change compute status").Error(), http.StatusInternalServerError)
return
}
}
if gcpClientPool != nil && m.Provider == constants.PROVIDER_GCP {
gcpClient, ok := gcpClientPool.GetForCredential(m.CredentialRef)
if !ok {
http.Error(w, fmt.Errorf("client not found for credential %v", m.CredentialRef).Error(),
http.StatusBadRequest)
return
}
compute := gcpClient.GCE()
if err := compute.ChangeStatus(ctx, m.Action, m.TagKey, m.TagValue); err != nil {
http.Error(w, pkgerrors.Wrap(err, "change compute status").Error(), http.StatusInternalServerError)
return
case constants.PROVIDER_GCP:
if gcpClientPool != nil {
gcpClient, ok := gcpClientPool.GetForCredential(m.CredentialRef)
if !ok {
http.Error(w, fmt.Errorf("client not found for credential %v", m.CredentialRef).Error(),
http.StatusBadRequest)
return
}
compute := gcpClient.GCE()
if err := compute.ChangeStatus(ctx, m.Action, m.TagKey, m.TagValue); err != nil {
http.Error(w, pkgerrors.Wrap(err, "change compute status").Error(), http.StatusInternalServerError)
}
cloudSql := gcpClient.CloudSQL()
if err := cloudSql.ChangeStatus(ctx, m.Action, m.TagKey, m.TagValue); err != nil {
http.Error(w, pkgerrors.Wrap(err, "change sql instances status").Error(), http.StatusInternalServerError)
return
}
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions internal/constants/const.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package constants

const (
OffStatus int = iota
OnStatus
PROVIDER_AWS = "aws"
PROVIDER_GCP = "gcp"
PROVIDER_AZURE = "azure"
Expand Down
2 changes: 1 addition & 1 deletion internal/worker/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (c *client) Process(ctx context.Context, stop <-chan struct{}, errChan chan
fmt.Println("stop background process")
return
case task := <-resultChan:
fmt.Printf("popped item %v", task)
fmt.Printf("popped item %v \n", task)
var elem QueueElem
err := json.Unmarshal([]byte(task), &elem)
if err != nil {
Expand Down
4 changes: 1 addition & 3 deletions pkg/api/service/v1alpha1/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"net/http"

"github.com/nduyphuong/gorya/internal/api/middleware"

"github.com/nduyphuong/gorya/internal/store"
)

//go:generate mockery --name GoryaServiceHandler
Expand Down Expand Up @@ -43,7 +41,7 @@ const (
// NewGoryaServiceHandler builds an HTTP handler from the service implementation. It returns the
//
// path on which to mount the handler and the handler itself.
func NewGoryaServiceHandler(ctx context.Context, store store.Interface, svc GoryaServiceHandler) (string,
func NewGoryaServiceHandler(ctx context.Context, svc GoryaServiceHandler) (string,
http.Handler) {
mux := http.NewServeMux()
mux.Handle(GoryaGetTimeZoneProcedure, middleware.JWTAuthorization(svc.GetTimeZone(), "get-timezone", ctx))
Expand Down
2 changes: 1 addition & 1 deletion pkg/aws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func (b *ClientPool) GetForCredential(name string) (Interface, bool) {
if !ok {
return nil, false
}
fmt.Printf("got client from pool for %s", name)
fmt.Printf("got client from pool for %s\n", name)
return i, true
}

Expand Down
8 changes: 4 additions & 4 deletions pkg/aws/ec2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ type Interface interface {
ChangeStatus(ctx context.Context, to int, tagKey string, tagValue string) (err error)
}

type Client struct {
type client struct {
ec2 *ec2.Client
}

func NewFromConfig(cfg aws.Config) (*Client, error) {
c := &Client{}
func NewFromConfig(cfg aws.Config) (*client, error) {
c := &client{}
c.ec2 = ec2.NewFromConfig(cfg)
return c, nil
}

func (c *Client) ChangeStatus(ctx context.Context, to int, tagKey string, tagValue string) (err error) {
func (c *client) ChangeStatus(ctx context.Context, to int, tagKey string, tagValue string) (err error) {
if to != 0 && to != 1 {
return errors.New("to must have value of 0 or 1")
}
Expand Down
Loading

0 comments on commit a2d3dd5

Please sign in to comment.