Skip to content

Commit

Permalink
Merge pull request #878 from erkanzsy/main
Browse files Browse the repository at this point in the history
New Storage Driver: Etcd
  • Loading branch information
ReneWerner87 authored Jul 4, 2023
2 parents 1f1e7ed + d95d8e9 commit f0e4fda
Show file tree
Hide file tree
Showing 12 changed files with 560 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ updates:
- "🤖 Dependencies"
schedule:
interval: "daily"
- package-ecosystem: "gomod"
directory: "/etcd/" # Location of package manifests
labels:
- "🤖 Dependencies"
schedule:
interval: "daily"
- package-ecosystem: "gomod"
directory: "/pebble/" # Location of package manifests
labels:
Expand Down
43 changes: 43 additions & 0 deletions .github/release-drafter-etcd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name-template: 'Etcd - v$RESOLVED_VERSION'
tag-template: 'etcd/v$RESOLVED_VERSION'
tag-prefix: etcd/v
include-paths:
- etcd
categories:
- title: '🚀 New'
labels:
- '✏️ Feature'
- title: '🧹 Updates'
labels:
- '🧹 Updates'
- '🤖 Dependencies'
- title: '🐛 Fixes'
labels:
- '☢️ Bug'
- title: '📚 Documentation'
labels:
- '📒 Documentation'
change-template: '- $TITLE (#$NUMBER)'
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
version-resolver:
major:
labels:
- 'major'
minor:
labels:
- 'minor'
- '✏️ Feature'
patch:
labels:
- 'patch'
- '📒 Documentation'
- '☢️ Bug'
- '🤖 Dependencies'
- '🧹 Updates'
default: patch
template: |
$CHANGES
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...etcd/v$RESOLVED_VERSION
Thank you $CONTRIBUTORS for making this update possible.
6 changes: 5 additions & 1 deletion .github/workflows/gosec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
- name: Run Gosec (root)
working-directory: .
run: |
gosec -exclude-dir=arangodb -exclude-dir=badger -exclude-dir=couchbase -exclude-dir=dynamodb -exclude-dir=memcache -exclude-dir=memory -exclude-dir=mongodb -exclude-dir=mysql -exclude-dir=postgres -exclude-dir=redis -exclude-dir=ristretto -exclude-dir=sqlite3 -exclude-dir=s3 -exclude-dir=bbolt -exclude-dir=azureblob -exclude-dir=mssql -exclude-dir=pebble ./....
gosec -exclude-dir=arangodb -exclude-dir=badger -exclude-dir=couchbase -exclude-dir=dynamodb -exclude-dir=etcd -exclude-dir=memcache -exclude-dir=memory -exclude-dir=mongodb -exclude-dir=mysql -exclude-dir=postgres -exclude-dir=redis -exclude-dir=ristretto -exclude-dir=sqlite3 -exclude-dir=s3 -exclude-dir=bbolt -exclude-dir=azureblob -exclude-dir=mssql -exclude-dir=pebble ./....
# -----
- name: Run Gosec (arangodb)
working-directory: ./arangodb
Expand All @@ -56,6 +56,10 @@ jobs:
working-directory: ./dynamodb
run: gosec ./...
# -----
- name: Run Gosec (etcd)
working-directory: ./etcd
run: gosec ./...
# -----
- name: Run Gosec (memcache)
working-directory: ./memcache
run: gosec ./...
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/release-drafter-etcd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Release Drafter Etcd
on:
push:
# branches to consider in the event; optional, defaults to all
branches:
- master
- main
paths:
- 'etcd/**'
jobs:
draft_release_etcd:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter-etcd.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 changes: 37 additions & 0 deletions .github/workflows/test-etcd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
on:
push:
branches:
- master
- main
paths:
- 'etcd/**'
pull_request:
paths:
- 'etcd/**'
name: "Tests Etcd"
jobs:
Tests:
runs-on: ubuntu-latest
strategy:
matrix:
go-version:
- 1.19.x
- 1.20.x
steps:
- name: Fetch Repository
uses: actions/checkout@v3
- name: Install etcd
run: |
docker run -d --name Etcd-server \
--publish 2379:2379 \
--publish 2380:2380 \
--env ALLOW_NONE_AUTHENTICATION=yes \
--env ETCD_ADVERTISE_CLIENT_URLS=http://etcd-server:2379 \
bitnami/etcd:latest
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: '${{ matrix.go-version }}'
- name: Run Test
run: cd ./etcd && go test ./... -v -race
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type Storage interface {
- [DynamoDB](/dynamodb) <a href="https://github.com/gofiber/storage/actions?query=workflow%3A%22Tests+DynamoDB%22">
<img src="https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-dynamodb.yml?branch=main&label=%F0%9F%A7%AA%20&style=flat&color=75C46B">
</a>
- [Etcd](/etcd) <a href="https://github.com/gofiber/storage/actions?query=workflow%3A%22Tests+Etcd%22">
<img src="https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-Etcd.yml?branch=main&label=%F0%9F%A7%AA%20&style=flat&color=75C46B">
</a>
- [Memcache](/memcache) <a href="https://github.com/gofiber/storage/actions?query=workflow%3A%22Tests+Memcache%22">
<img src="https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-memcache.yml?branch=main&label=%F0%9F%A7%AA%20&style=flat&color=75C46B">
</a>
Expand Down
76 changes: 76 additions & 0 deletions etcd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Etcd

A Etcd storage driver using [`etcd-io/etcd`](https://github.com/etcd-io/etcd).

### Table of Contents
- [Signatures](#signatures)
- [Installation](#installation)
- [Examples](#examples)
- [Config](#config)
- [Default Config](#default-config)

### Signatures
```go
func New(config ...Config) *Storage
func (s *Storage) Get(key string) ([]byte, error)
func (s *Storage) Set(key string, val []byte, exp time.Duration) error
func (s *Storage) Delete(key string) error
func (s *Storage) Reset() error
func (s *Storage) Close() error
func (s *Storage) Conn() *clientv3.Client
```

### Installation
Etcd is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet:
```bash
go mod init github.com/<user>/<repo>
```
And then install the etcd implementation:
```bash
go get github.com/gofiber/storage/etcd
```

### Examples
Import the storage package.
```go
import "github.com/gofiber/storage/etcd"
```

You can use the following possibilities to create a storage:
```go
// Initialize default config
store := etcd.New()

// Initialize custom config
store := etcd.New(Config{
Endpoints: []string{"localhost:2379"},
})

```

### Config
```go
type Config struct {
// Endpoints is a list of URLs.
Endpoints []string
// DialTimeout is the timeout for failing to establish a connection.
DialTimeout time.Duration
// Username is a username for authentication.
Username string
// Password is a password for authentication.
Password string
// TLS holds the client secure credentials, if any.
TLS *tls.Config
}
```

### Default Config
```go
var ConfigDefault = Config{
Endpoints: []string{"localhost:2379"},
DialTimeout: 2 * time.Second,
Username: "",
Password: "",
TLS: nil,
}
```
52 changes: 52 additions & 0 deletions etcd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package etcd

import (
"crypto/tls"
"time"
)

// Config defines the config for storage.
type Config struct {
// Endpoints is a list of URLs.
Endpoints []string
// DialTimeout is the timeout for failing to establish a connection.
DialTimeout time.Duration
// Username is a username for authentication.
Username string
// Password is a password for authentication.
Password string
// TLS holds the client secure credentials, if any.
TLS *tls.Config
}

// ConfigDefault is the default config
var ConfigDefault = Config{
Endpoints: []string{"localhost:2379"},
DialTimeout: 2 * time.Second,
Username: "",
Password: "",
TLS: nil,
}

// Helper function to set default values
func configDefault(config ...Config) Config {
// Return default config if nothing provided
if len(config) < 1 {
return ConfigDefault
}

// Override default config
cfg := config[0]
// Set default values
if cfg.Username == "" {
cfg.Username = ConfigDefault.Username
}
if cfg.Password == "" {
cfg.Password = ConfigDefault.Password
}
if cfg.DialTimeout == 0 {
cfg.DialTimeout = ConfigDefault.DialTimeout
}

return cfg
}
100 changes: 100 additions & 0 deletions etcd/etcd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package etcd

import (
"context"
"go.etcd.io/etcd/client/v3"
"time"
)

type Storage struct {
db *clientv3.Client
}

func New(config ...Config) *Storage {
cfg := configDefault(config...)

cli, err := clientv3.New(clientv3.Config{
Endpoints: cfg.Endpoints,
DialTimeout: cfg.DialTimeout,
Username: cfg.Username,
Password: cfg.Password,
TLS: cfg.TLS,
})
if err != nil {
panic(err)
}

store := &Storage{
db: cli,
}

return store
}

func (s *Storage) Get(key string) ([]byte, error) {
if len(key) <= 0 {
return nil, nil
}
item, err := s.db.Get(context.Background(), key)

if err != nil {
return nil, err
}

if len(item.Kvs) <= 0 {
return nil, nil
}

return item.Kvs[0].Value, nil
}

func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
// Ain't Nobody Got Time For That
if len(key) <= 0 || len(val) <= 0 {
return nil
}

lease, err := s.db.Grant(context.Background(), int64(exp.Seconds()))

if err != nil {
return err
}

_, err = s.db.Put(context.Background(), key, string(val), clientv3.WithLease(lease.ID))
if err != nil {
return err
}

return nil
}

func (s *Storage) Delete(key string) error {
if len(key) <= 0 {
return nil
}

_, err := s.db.Delete(context.Background(), key)
if err != nil {
return err
}

return nil
}

func (s *Storage) Reset() error {
_, err := s.db.Delete(context.Background(), "", clientv3.WithPrefix())

if err != nil {
return err
}

return nil
}

func (s *Storage) Close() error {
return s.db.Close()
}

func (s *Storage) Conn() *clientv3.Client {
return s.db
}
Loading

0 comments on commit f0e4fda

Please sign in to comment.