Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove the dependency of github_personal_token #61

Merged
merged 3 commits into from
Jun 3, 2021
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
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,11 @@ you need to register a target that repository or organization.
- example: `ubuntu`
- resource_type: set instance size for a runner.
- please check a document of shoes-providers.
- github_personal_token: set token of GitHub Personal.
- please check a document of [GPT](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token).

create target example:

```bash
$ curl -XPOST -d '{"scope": "octocat/hello-world", "ghe_domain": "https://github.example.com", "github_personal_token": "xxx", "resource_type": "micro", "runner_user": "ubuntu"}' ${your_shoes_host}/target
$ curl -XPOST -d '{"scope": "octocat/hello-world", "ghe_domain": "https://github.example.com", "resource_type": "micro", "runner_user": "ubuntu"}' ${your_shoes_host}/target
```

### Create an offline runner (only one)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ go 1.16
require (
github.com/bradleyfalzon/ghinstallation v1.1.1
github.com/go-sql-driver/mysql v1.5.0
github.com/golang/protobuf v1.5.0
github.com/google/go-cmp v0.5.5
github.com/google/go-github/v32 v32.1.0
github.com/google/go-github/v35 v35.2.0
github.com/hashicorp/go-plugin v1.4.0
github.com/jmoiron/sqlx v1.2.0
github.com/lestrrat-go/jwx v1.2.0 // indirect
github.com/ory/dockertest/v3 v3.6.2
github.com/prometheus/client_golang v1.10.0 // indirect
github.com/satori/go.uuid v1.2.0
Expand Down
57 changes: 57 additions & 0 deletions go.sum

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package config

import "crypto/rsa"

// Config is config value
var Config conf

type conf struct {
GitHub struct {
AppID int64
AppSecret []byte
PEM []byte
PEMByte []byte
PEM *rsa.PrivateKey
}

MySQLDSN string
Expand Down
15 changes: 13 additions & 2 deletions internal/config/init.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package config

import (
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"io"
"log"
Expand All @@ -25,11 +27,20 @@ func Load() {
if pemBase64ed == "" {
log.Panicf("%s must be set", EnvGitHubAppPrivateKeyBase64)
}
pem, err := base64.StdEncoding.DecodeString(pemBase64ed)
pemByte, err := base64.StdEncoding.DecodeString(pemBase64ed)
if err != nil {
log.Panicf("failed to decode base64 %s: %+v", EnvGitHubAppPrivateKeyBase64, err)
}
Config.GitHub.PEM = pem
Config.GitHub.PEMByte = pemByte
block, _ := pem.Decode(pemByte)
if block == nil {
log.Panicf("%s is invalid format, please input private key ", EnvGitHubAppPrivateKeyBase64)
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
log.Panicf("%s is invalid format, failed to parse private key: %+v", EnvGitHubAppPrivateKeyBase64, err)
}
Config.GitHub.PEM = key

appSecret := os.Getenv(EnvGitHubAppSecret)
if appSecret == "" {
Expand Down
2 changes: 1 addition & 1 deletion internal/testutils/testutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func IntegrationTestRunner(m *testing.M) int {
log.Fatalf("failed to create datastore instance: %s", err)
}

testDB, err = sqlx.Open("mysql", fmt.Sprintf("root:%s@(localhost:%s)/mysql?parseTime=true", mysqlRootPassword, resource.GetPort("3306/tcp")))
testDB, err = sqlx.Open("mysql", fmt.Sprintf("root:%s@(localhost:%s)/mysql?parseTime=true&loc=Local", mysqlRootPassword, resource.GetPort("3306/tcp")))
if err != nil {
return err
}
Expand Down
26 changes: 14 additions & 12 deletions pkg/datastore/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Datastore interface {

// Deprecated: Use datastore.UpdateTargetStatus.
UpdateTargetStatus(ctx context.Context, targetID uuid.UUID, newStatus TargetStatus, description string) error
UpdateToken(ctx context.Context, targetID uuid.UUID, newToken string, newExpiredAt time.Time) error

EnqueueJob(ctx context.Context, job Job) error
ListJobs(ctx context.Context) ([]Job, error)
Expand All @@ -42,18 +43,19 @@ type Datastore interface {

// Target is a target repository that will add auto-scaling runner.
type Target struct {
UUID uuid.UUID `db:"uuid" json:"id"`
Scope string `db:"scope" json:"scope"` // repo (:owner/:repo) or org (:organization)
GitHubPersonalToken string `db:"github_personal_token" json:"github_personal_token"` // TODO: encrypt
GHEDomain sql.NullString `db:"ghe_domain" json:"ghe_domain"`
ResourceType ResourceType `db:"resource_type" json:"resource_type"`
RunnerUser sql.NullString `db:"runner_user" json:"runner_user"`
RunnerVersion sql.NullString `db:"runner_version" json:"runner_version"`
ProviderURL sql.NullString `db:"provider_url" json:"provider_url"`
Status TargetStatus `db:"status" json:"status"`
StatusDescription sql.NullString `db:"status_description" json:"status_description"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
UUID uuid.UUID `db:"uuid" json:"id"`
Scope string `db:"scope" json:"scope"` // repo (:owner/:repo) or org (:organization)
GitHubToken string `db:"github_token" json:"github_token"`
TokenExpiredAt time.Time `db:"token_expired_at" json:"token_expired_at"`
GHEDomain sql.NullString `db:"ghe_domain" json:"ghe_domain"`
ResourceType ResourceType `db:"resource_type" json:"resource_type"`
RunnerUser sql.NullString `db:"runner_user" json:"runner_user"`
RunnerVersion sql.NullString `db:"runner_version" json:"runner_version"`
ProviderURL sql.NullString `db:"provider_url" json:"provider_url"`
Status TargetStatus `db:"status" json:"status"`
StatusDescription sql.NullString `db:"status_description" json:"status_description"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}

// RepoURL return repository URL.
Expand Down
16 changes: 16 additions & 0 deletions pkg/datastore/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,22 @@ func (m *Memory) UpdateTargetStatus(ctx context.Context, targetID uuid.UUID, new
return nil
}

// UpdateToken update token in target
func (m *Memory) UpdateToken(ctx context.Context, targetID uuid.UUID, newToken string, newExpiredAt time.Time) error {
m.mu.Lock()
defer m.mu.Unlock()

t, ok := m.targets[targetID]
if !ok {
return fmt.Errorf("not found")
}
t.GitHubToken = newToken
t.TokenExpiredAt = newExpiredAt

m.targets[targetID] = t
return nil
}

// EnqueueJob add a job
func (m *Memory) EnqueueJob(ctx context.Context, job datastore.Job) error {
m.mu.Lock()
Expand Down
27 changes: 15 additions & 12 deletions pkg/datastore/mysql/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ func TestMySQL_EnqueueJob(t *testing.T) {
testDB, _ := testutils.GetTestDB()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -78,10 +79,11 @@ func TestMySQL_ListJobs(t *testing.T) {
defer teardown()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -144,10 +146,11 @@ func TestMySQL_DeleteJob(t *testing.T) {
testDB, _ := testutils.GetTestDB()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down
45 changes: 25 additions & 20 deletions pkg/datastore/mysql/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ func TestMySQL_CreateRunner(t *testing.T) {
testDB, _ := testutils.GetTestDB()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -76,10 +77,11 @@ func TestMySQL_ListRunners(t *testing.T) {
defer teardown()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -131,10 +133,11 @@ func TestMySQL_ListRunnersNotReturnDeleted(t *testing.T) {
defer teardown()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -182,10 +185,11 @@ func TestMySQL_GetRunner(t *testing.T) {
defer teardown()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down Expand Up @@ -228,10 +232,11 @@ func TestMySQL_DeleteRunner(t *testing.T) {
testDB, _ := testutils.GetTestDB()

if err := testDatastore.CreateTarget(context.Background(), datastore.Target{
UUID: testTargetID,
Scope: testScopeRepo,
GitHubPersonalToken: testGitHubPersonalToken,
ResourceType: datastore.ResourceTypeNano,
UUID: testTargetID,
Scope: testScopeRepo,
GitHubToken: testGitHubToken,
TokenExpiredAt: testTime,
ResourceType: datastore.ResourceTypeNano,
}); err != nil {
t.Fatalf("failed to create target: %+v", err)
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/datastore/mysql/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ CREATE TABLE `targets` (
`uuid` VARCHAR(36) NOT NULL PRIMARY KEY,
`scope` VARCHAR(255) NOT NULL,
`ghe_domain` VARCHAR(255),
`github_personal_token` VARCHAR(255) NOT NULL,
`github_token` VARCHAR(255) NOT NULL,
`token_expired_at` TIMESTAMP NOT NULL,
`resource_type` ENUM('nano', 'micro', 'small', 'medium', 'large', 'xlarge', '2xlarge', '3xlarge', '4xlarge') NOT NULL,
`runner_user` VARCHAR(255),
`runner_version` VARCHAR(255),
Expand Down
24 changes: 19 additions & 5 deletions pkg/datastore/mysql/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,25 @@ import (
"database/sql"
"errors"
"fmt"
"time"

uuid "github.com/satori/go.uuid"
"github.com/whywaita/myshoes/pkg/datastore"
)

// CreateTarget create a target
func (m *MySQL) CreateTarget(ctx context.Context, target datastore.Target) error {
query := `INSERT INTO targets(uuid, scope, ghe_domain, github_personal_token, resource_type, runner_user, runner_version, provider_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
expiredAtRFC3339 := target.TokenExpiredAt.Format("2006-01-02 15:04:05")

query := `INSERT INTO targets(uuid, scope, ghe_domain, github_token, token_expired_at, resource_type, runner_user, runner_version, provider_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
if _, err := m.Conn.ExecContext(
ctx,
query,
target.UUID,
target.Scope,
target.GHEDomain,
target.GitHubPersonalToken,
target.GitHubToken,
expiredAtRFC3339,
target.ResourceType,
target.RunnerUser,
target.RunnerVersion,
Expand All @@ -34,7 +38,7 @@ func (m *MySQL) CreateTarget(ctx context.Context, target datastore.Target) error
// GetTarget get a target
func (m *MySQL) GetTarget(ctx context.Context, id uuid.UUID) (*datastore.Target, error) {
var t datastore.Target
query := fmt.Sprintf(`SELECT uuid, scope, ghe_domain, github_personal_token, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets WHERE uuid = ?`)
query := fmt.Sprintf(`SELECT uuid, scope, ghe_domain, github_token, token_expired_at, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets WHERE uuid = ?`)
if err := m.Conn.GetContext(ctx, &t, query, id.String()); err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, datastore.ErrNotFound
Expand All @@ -49,7 +53,7 @@ func (m *MySQL) GetTarget(ctx context.Context, id uuid.UUID) (*datastore.Target,
// GetTargetByScope get a target from scope
func (m *MySQL) GetTargetByScope(ctx context.Context, gheDomain, scope string) (*datastore.Target, error) {
var t datastore.Target
query := fmt.Sprintf(`SELECT uuid, scope, ghe_domain, github_personal_token, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets WHERE scope = "%s"`, scope)
query := fmt.Sprintf(`SELECT uuid, scope, ghe_domain, github_token, token_expired_at, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets WHERE scope = "%s"`, scope)
if gheDomain != "" {
query = fmt.Sprintf(`%s AND ghe_domain = "%s"`, query, gheDomain)
}
Expand All @@ -67,7 +71,7 @@ func (m *MySQL) GetTargetByScope(ctx context.Context, gheDomain, scope string) (
// ListTargets get a all target
func (m *MySQL) ListTargets(ctx context.Context) ([]datastore.Target, error) {
var ts []datastore.Target
query := `SELECT uuid, scope, ghe_domain, github_personal_token, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets`
query := `SELECT uuid, scope, ghe_domain, github_token, token_expired_at, resource_type, runner_user, runner_version, provider_url, status, status_description, created_at, updated_at FROM targets`
if err := m.Conn.SelectContext(ctx, &ts, query); err != nil {
return nil, fmt.Errorf("failed to SELECT query: %w", err)
}
Expand All @@ -94,3 +98,13 @@ func (m *MySQL) UpdateTargetStatus(ctx context.Context, targetID uuid.UUID, newS

return nil
}

// UpdateToken update token in target
func (m *MySQL) UpdateToken(ctx context.Context, targetID uuid.UUID, newToken string, newExpiredAt time.Time) error {
query := `UPDATE targets SET github_token = ?, token_expired_at = ? WHERE uuid = ?`
if _, err := m.Conn.ExecContext(ctx, query, newToken, newExpiredAt, targetID.String()); err != nil {
return fmt.Errorf("failed to execute UPDATE query: %w", err)
}

return nil
}
Loading