forked from LaconicNetwork/kompose
Add new examples to kompose (#1803)
#### What type of PR is this? <!-- Add one of the following kinds: /kind bug /kind documentation /kind feature --> /kind cleanup #### What this PR does / why we need it: Fixes the current broken examples by: * Removing all the old incompatible ones (we do not really support v3 anymore or v2... since switching libraries) * Uses quay.io/kompose/web as our front end example which is a fork of the guestbook-go kubernetes examples #### Which issue(s) this PR fixes: <!-- *Automatically closes linked issue when PR is merged. Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`. --> Closes https://github.com/kubernetes/kompose/issues/1757 #### Special notes for your reviewer: Test using docker-compose (you'll see it come up!), then try with kompose :) Signed-off-by: Charlie Drage <charlie@charliedrage.com>
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.8"
|
||||
- "1.9"
|
||||
- "1.10"
|
||||
- "1.11"
|
||||
- "1.12"
|
||||
- "1.13"
|
||||
- "1.14"
|
||||
- tip
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Copyright 2021 Alexander F. Rødseth
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
# pinterface
|
||||
|
||||
[](https://goreportcard.com/report/github.com/xyproto/pinterface) [](https://raw.githubusercontent.com/xyproto/pinterface/main/LICENSE)
|
||||
|
||||
Interface types for `simple*` and `permission*` packages.
|
||||
|
||||
Interfaces for:
|
||||
---------------
|
||||
|
||||
* Redis: [permissions2](https://github.com/xyproto/permissions2) and [simpleredis](https://github.com/xyproto/simpleredis)
|
||||
* Bolt: [permissionbolt](https://github.com/xyproto/permissionbolt) and [simplebolt](https://github.com/xyproto/simplebolt)
|
||||
* MariaDB/MySQL: [permissionsql](https://github.com/xyproto/permissionsql) and [simplemaria](https://github.com/xyproto/simplemaria)
|
||||
* PostgreSQL: [pstore](https://github.com/xyproto/pstore) and [simplehstore](https://github.com/xyproto/simplehstore)
|
||||
|
||||
[](https://repology.org/project/go:github-xyproto-pinterface/versions)
|
||||
|
||||
General information
|
||||
-------------------
|
||||
|
||||
* Version: 1.5.3 (The tag is `v1.5.3` to work better with `go mod`. The API has version `5.3`.)
|
||||
* License: BSD-3
|
||||
* Author: Alexander F. Rødseth <xyproto@archlinux.org>
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
// Package pinterface provides interface types for the xyproto/simple* and xyproto/permission* packages
|
||||
package pinterface
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Version is the API version. The API is stable within the same major version number
|
||||
const Version = 5.3
|
||||
|
||||
// Database interfaces
|
||||
|
||||
type IList interface {
|
||||
Add(value string) error
|
||||
All() ([]string, error)
|
||||
Clear() error
|
||||
LastN(n int) ([]string, error)
|
||||
Last() (string, error)
|
||||
Remove() error
|
||||
}
|
||||
|
||||
type ISet interface {
|
||||
Add(value string) error
|
||||
All() ([]string, error)
|
||||
Clear() error
|
||||
Del(value string) error
|
||||
Has(value string) (bool, error)
|
||||
Remove() error
|
||||
}
|
||||
|
||||
type IHashMap interface {
|
||||
All() ([]string, error)
|
||||
Clear() error
|
||||
DelKey(owner, key string) error
|
||||
Del(key string) error
|
||||
Exists(owner string) (bool, error)
|
||||
Get(owner, key string) (string, error)
|
||||
Has(owner, key string) (bool, error)
|
||||
Keys(owner string) ([]string, error)
|
||||
Remove() error
|
||||
Set(owner, key, value string) error
|
||||
}
|
||||
|
||||
type IHashMap2 interface {
|
||||
All() ([]string, error)
|
||||
AllWhere(key, value string) ([]string, error)
|
||||
Clear() error
|
||||
Count() (int64, error)
|
||||
DelKey(owner, key string) error
|
||||
Del(key string) error
|
||||
Empty() (bool, error)
|
||||
Exists(owner string) (bool, error)
|
||||
GetMap(owner string, keys []string) (map[string]string, error)
|
||||
Get(owner, key string) (string, error)
|
||||
Has(owner, key string) (bool, error)
|
||||
Keys(owner string) ([]string, error)
|
||||
Remove() error
|
||||
SetLargeMap(all map[string]map[string]string) error
|
||||
SetMap(owner string, m map[string]string) error
|
||||
Set(owner, key, value string) error
|
||||
}
|
||||
|
||||
type IKeyValue interface {
|
||||
Clear() error
|
||||
Del(key string) error
|
||||
Get(key string) (string, error)
|
||||
Inc(key string) (string, error)
|
||||
Remove() error
|
||||
Set(key, value string) error
|
||||
}
|
||||
|
||||
// Interface for making it possible to depend on different versions of the permission package,
|
||||
// or other packages that implement userstates.
|
||||
type IUserState interface {
|
||||
AddUnconfirmed(username, confirmationCode string)
|
||||
AddUser(username, password, email string)
|
||||
AdminRights(req *http.Request) bool
|
||||
AllUnconfirmedUsernames() ([]string, error)
|
||||
AllUsernames() ([]string, error)
|
||||
AlreadyHasConfirmationCode(confirmationCode string) bool
|
||||
BooleanField(username, fieldname string) bool
|
||||
ClearCookie(w http.ResponseWriter)
|
||||
ConfirmationCode(username string) (string, error)
|
||||
ConfirmUserByConfirmationCode(confirmationcode string) error
|
||||
Confirm(username string)
|
||||
CookieSecret() string
|
||||
CookieTimeout(username string) int64
|
||||
CorrectPassword(username, password string) bool
|
||||
Email(username string) (string, error)
|
||||
FindUserByConfirmationCode(confirmationcode string) (string, error)
|
||||
GenerateUniqueConfirmationCode() (string, error)
|
||||
HashPassword(username, password string) string
|
||||
HasUser(username string) bool
|
||||
IsAdmin(username string) bool
|
||||
IsConfirmed(username string) bool
|
||||
IsLoggedIn(username string) bool
|
||||
Login(w http.ResponseWriter, username string) error
|
||||
Logout(username string)
|
||||
MarkConfirmed(username string)
|
||||
PasswordAlgo() string
|
||||
PasswordHash(username string) (string, error)
|
||||
RemoveAdminStatus(username string)
|
||||
RemoveUnconfirmed(username string)
|
||||
RemoveUser(username string)
|
||||
SetAdminStatus(username string)
|
||||
SetBooleanField(username, fieldname string, val bool)
|
||||
SetCookieSecret(cookieSecret string)
|
||||
SetCookieTimeout(cookieTime int64)
|
||||
SetLoggedIn(username string)
|
||||
SetLoggedOut(username string)
|
||||
SetMinimumConfirmationCodeLength(length int)
|
||||
SetPasswordAlgo(algorithm string) error
|
||||
SetPassword(username, password string)
|
||||
SetUsernameCookie(w http.ResponseWriter, username string) error
|
||||
UsernameCookie(req *http.Request) (string, error)
|
||||
Username(req *http.Request) string
|
||||
UserRights(req *http.Request) bool
|
||||
|
||||
Creator() ICreator
|
||||
Host() IHost
|
||||
Users() IHashMap
|
||||
}
|
||||
|
||||
// Data structure creator
|
||||
type ICreator interface {
|
||||
NewHashMap(id string) (IHashMap, error)
|
||||
NewKeyValue(id string) (IKeyValue, error)
|
||||
NewList(id string) (IList, error)
|
||||
NewSet(id string) (ISet, error)
|
||||
}
|
||||
|
||||
// Database host (or file)
|
||||
type IHost interface {
|
||||
Close()
|
||||
Ping() error
|
||||
}
|
||||
|
||||
// Redis host (implemented structures can also be an IHost, of course)
|
||||
type IRedisHost interface {
|
||||
DatabaseIndex()
|
||||
Pool()
|
||||
}
|
||||
|
||||
// Redis data structure creator
|
||||
type IRedisCreator interface {
|
||||
SelectDatabase(dbindex int)
|
||||
}
|
||||
|
||||
// Middleware for permissions
|
||||
type IPermissions interface {
|
||||
AddAdminPath(prefix string)
|
||||
AddPublicPath(prefix string)
|
||||
AddUserPath(prefix string)
|
||||
Clear()
|
||||
DenyFunction() http.HandlerFunc
|
||||
Rejected(w http.ResponseWriter, req *http.Request) bool
|
||||
ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc)
|
||||
SetAdminPath(pathPrefixes []string)
|
||||
SetDenyFunction(f http.HandlerFunc)
|
||||
SetPublicPath(pathPrefixes []string)
|
||||
SetUserPath(pathPrefixes []string)
|
||||
UserState() IUserState
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Copyright 2023 Alexander F. Rødseth
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package simpleredis
|
||||
|
||||
import (
|
||||
"github.com/xyproto/pinterface"
|
||||
)
|
||||
|
||||
// For implementing pinterface.ICreator
|
||||
|
||||
type RedisCreator struct {
|
||||
pool *ConnectionPool
|
||||
dbindex int
|
||||
}
|
||||
|
||||
func NewCreator(pool *ConnectionPool, dbindex int) *RedisCreator {
|
||||
return &RedisCreator{pool, dbindex}
|
||||
}
|
||||
|
||||
func (c *RedisCreator) SelectDatabase(dbindex int) {
|
||||
c.dbindex = dbindex
|
||||
}
|
||||
|
||||
func (c *RedisCreator) NewList(id string) (pinterface.IList, error) {
|
||||
return &List{c.pool, id, c.dbindex}, nil
|
||||
}
|
||||
|
||||
func (c *RedisCreator) NewSet(id string) (pinterface.ISet, error) {
|
||||
return &Set{c.pool, id, c.dbindex}, nil
|
||||
}
|
||||
|
||||
func (c *RedisCreator) NewHashMap(id string) (pinterface.IHashMap, error) {
|
||||
return &HashMap{c.pool, id, c.dbindex}, nil
|
||||
}
|
||||
|
||||
func (c *RedisCreator) NewKeyValue(id string) (pinterface.IKeyValue, error) {
|
||||
return &KeyValue{c.pool, id, c.dbindex}, nil
|
||||
}
|
||||
+737
@@ -0,0 +1,737 @@
|
||||
// Package simpleredis provides an easy way to use Redis.
|
||||
package simpleredis
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gomodule/redigo/redis"
|
||||
)
|
||||
|
||||
const (
|
||||
// Version number. Stable API within major version numbers.
|
||||
Version = 2.6
|
||||
|
||||
// The default [url]:port that Redis is running at
|
||||
defaultRedisServer = ":6379"
|
||||
)
|
||||
|
||||
// Common for each of the Redis data structures used here
|
||||
type redisDatastructure struct {
|
||||
pool *ConnectionPool
|
||||
id string
|
||||
dbindex int
|
||||
}
|
||||
|
||||
type (
|
||||
// A pool of readily available Redis connections
|
||||
ConnectionPool redis.Pool
|
||||
|
||||
List redisDatastructure
|
||||
Set redisDatastructure
|
||||
HashMap redisDatastructure
|
||||
KeyValue redisDatastructure
|
||||
)
|
||||
|
||||
var (
|
||||
// Timeout settings for new connections
|
||||
connectTimeout = 7 * time.Second
|
||||
readTimeout = 7 * time.Second
|
||||
writeTimeout = 7 * time.Second
|
||||
idleTimeout = 240 * time.Second
|
||||
|
||||
// How many connections should stay ready for requests, at a maximum?
|
||||
// When an idle connection is used, new idle connections are created.
|
||||
maxIdleConnections = 3
|
||||
)
|
||||
|
||||
/* --- Helper functions --- */
|
||||
|
||||
// Connect to the local instance of Redis at port 6379
|
||||
func newRedisConnection() (redis.Conn, error) {
|
||||
return newRedisConnectionTo(defaultRedisServer)
|
||||
}
|
||||
|
||||
// Connect to host:port, host may be omitted, so ":6379" is valid.
|
||||
// Will not try to AUTH with any given password (password@host:port).
|
||||
func newRedisConnectionTo(hostColonPort string) (redis.Conn, error) {
|
||||
// Discard the password, if provided
|
||||
if _, theRest, ok := twoFields(hostColonPort, "@"); ok {
|
||||
hostColonPort = theRest
|
||||
}
|
||||
hostColonPort = strings.TrimSpace(hostColonPort)
|
||||
c, err := redis.Dial("tcp", hostColonPort, redis.DialConnectTimeout(connectTimeout), redis.DialReadTimeout(readTimeout), redis.DialWriteTimeout(writeTimeout))
|
||||
if err != nil {
|
||||
if c != nil {
|
||||
c.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Get a string from a list of results at a given position
|
||||
func getString(bi []interface{}, i int) string {
|
||||
return string(bi[i].([]uint8))
|
||||
}
|
||||
|
||||
// Test if the local Redis server is up and running
|
||||
func TestConnection() (err error) {
|
||||
return TestConnectionHost(defaultRedisServer)
|
||||
}
|
||||
|
||||
// Test if a given Redis server at host:port is up and running.
|
||||
// Does not try to PING or AUTH.
|
||||
func TestConnectionHost(hostColonPort string) (err error) {
|
||||
// Connect to the given host:port
|
||||
conn, err := newRedisConnectionTo(hostColonPort)
|
||||
defer func() {
|
||||
if conn != nil {
|
||||
conn.Close()
|
||||
}
|
||||
if r := recover(); r != nil {
|
||||
err = errors.New("Could not connect to redis server: " + hostColonPort)
|
||||
}
|
||||
}()
|
||||
return err
|
||||
}
|
||||
|
||||
/* --- ConnectionPool functions --- */
|
||||
|
||||
func copyPoolValues(src *redis.Pool) ConnectionPool {
|
||||
return ConnectionPool{
|
||||
Dial: src.Dial,
|
||||
DialContext: src.DialContext,
|
||||
TestOnBorrow: src.TestOnBorrow,
|
||||
MaxIdle: src.MaxIdle,
|
||||
MaxActive: src.MaxActive,
|
||||
IdleTimeout: src.IdleTimeout,
|
||||
Wait: src.Wait,
|
||||
MaxConnLifetime: src.MaxConnLifetime,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new connection pool
|
||||
func NewConnectionPool() *ConnectionPool {
|
||||
// The second argument is the maximum number of idle connections
|
||||
redisPool := &redis.Pool{
|
||||
MaxIdle: maxIdleConnections,
|
||||
IdleTimeout: idleTimeout,
|
||||
Dial: newRedisConnection,
|
||||
}
|
||||
|
||||
pool := copyPoolValues(redisPool)
|
||||
return &pool
|
||||
}
|
||||
|
||||
// Split a string into two parts, given a delimiter.
|
||||
// Returns the two parts and true if it works out.
|
||||
func twoFields(s, delim string) (string, string, bool) {
|
||||
if strings.Count(s, delim) != 1 {
|
||||
return s, "", false
|
||||
}
|
||||
fields := strings.Split(s, delim)
|
||||
return fields[0], fields[1], true
|
||||
}
|
||||
|
||||
// Create a new connection pool given a host:port string.
|
||||
// A password may be supplied as well, on the form "password@host:port".
|
||||
func NewConnectionPoolHost(hostColonPort string) *ConnectionPool {
|
||||
// Create a redis Pool
|
||||
redisPool := &redis.Pool{
|
||||
// Maximum number of idle connections to the redis database
|
||||
MaxIdle: maxIdleConnections,
|
||||
IdleTimeout: idleTimeout,
|
||||
// Anonymous function for calling new RedisConnectionTo with the host:port
|
||||
Dial: func() (redis.Conn, error) {
|
||||
conn, err := newRedisConnectionTo(hostColonPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If a password is given, use it to authenticate
|
||||
if password, _, ok := twoFields(hostColonPort, "@"); ok {
|
||||
if password != "" {
|
||||
if _, err := conn.Do("AUTH", password); err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return conn, err
|
||||
},
|
||||
}
|
||||
pool := copyPoolValues(redisPool)
|
||||
return &pool
|
||||
}
|
||||
|
||||
// Set the number of maximum *idle* connections standing ready when
|
||||
// creating new connection pools. When an idle connection is used,
|
||||
// a new idle connection is created. The default is 3 and should be fine
|
||||
// for most cases.
|
||||
func SetMaxIdleConnections(maximum int) {
|
||||
maxIdleConnections = maximum
|
||||
}
|
||||
|
||||
// Get one of the available connections from the connection pool, given a database index
|
||||
func (pool *ConnectionPool) Get(dbindex int) redis.Conn {
|
||||
redisPool := (*redis.Pool)(pool)
|
||||
conn := redisPool.Get()
|
||||
// The default database index is 0
|
||||
if dbindex != 0 {
|
||||
// SELECT is not critical, ignore the return values
|
||||
conn.Do("SELECT", strconv.Itoa(dbindex))
|
||||
}
|
||||
return conn
|
||||
}
|
||||
|
||||
// Ping the server by sending a PING command
|
||||
func (pool *ConnectionPool) Ping() error {
|
||||
redisPool := (*redis.Pool)(pool)
|
||||
conn := redisPool.Get()
|
||||
_, err := conn.Do("PING")
|
||||
return err
|
||||
}
|
||||
|
||||
// Close down the connection pool
|
||||
func (pool *ConnectionPool) Close() {
|
||||
redisPool := (*redis.Pool)(pool)
|
||||
redisPool.Close()
|
||||
}
|
||||
|
||||
/* --- List functions --- */
|
||||
|
||||
// Create a new list
|
||||
func NewList(pool *ConnectionPool, id string) *List {
|
||||
return &List{pool, id, 0}
|
||||
}
|
||||
|
||||
// Select a different database
|
||||
func (rl *List) SelectDatabase(dbindex int) {
|
||||
rl.dbindex = dbindex
|
||||
}
|
||||
|
||||
// Returns the element at index index in the list
|
||||
func (rl *List) Get(index int64) (string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := conn.Do("LINDEX", rl.id, index)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.String(result, err)
|
||||
}
|
||||
|
||||
// Get the size of the list
|
||||
func (rl *List) Size() (int64, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
size, err := conn.Do("LLEN", rl.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.Int64(size, err)
|
||||
}
|
||||
|
||||
// Removes and returns the first element of the list
|
||||
func (rl *List) PopFirst() (string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := conn.Do("LPOP", rl.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.String(result, err)
|
||||
}
|
||||
|
||||
// Removes and returns the last element of the list
|
||||
func (rl *List) PopLast() (string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := conn.Do("LPOP", rl.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.String(result, err)
|
||||
}
|
||||
|
||||
// Add an element to the start of the list
|
||||
func (rl *List) AddStart(value string) error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("RPUSH", rl.id, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Add an element to the end of the list list
|
||||
func (rl *List) AddEnd(value string) error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("LPUSH", rl.id, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Default Add, aliased to List.AddStart
|
||||
func (rl *List) Add(value string) error {
|
||||
return rl.AddStart(value)
|
||||
}
|
||||
|
||||
// Get all elements of a list
|
||||
func (rl *List) All() ([]string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := redis.Values(conn.Do("LRANGE", rl.id, "0", "-1"))
|
||||
strs := make([]string, len(result))
|
||||
for i := 0; i < len(result); i++ {
|
||||
strs[i] = getString(result, i)
|
||||
}
|
||||
return strs, err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (rl *List) GetAll() ([]string, error) {
|
||||
return rl.All()
|
||||
}
|
||||
|
||||
// Get the last element of a list
|
||||
func (rl *List) Last() (string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := redis.Values(conn.Do("LRANGE", rl.id, "-1", "-1"))
|
||||
if len(result) == 1 {
|
||||
return getString(result, 0), err
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (rl *List) GetLast() (string, error) {
|
||||
return rl.Last()
|
||||
}
|
||||
|
||||
// Get the last N elements of a list
|
||||
func (rl *List) LastN(n int) ([]string, error) {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
result, err := redis.Values(conn.Do("LRANGE", rl.id, "-"+strconv.Itoa(n), "-1"))
|
||||
strs := make([]string, len(result))
|
||||
for i := 0; i < len(result); i++ {
|
||||
strs[i] = getString(result, i)
|
||||
}
|
||||
return strs, err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (rl *List) GetLastN(n int) ([]string, error) {
|
||||
return rl.LastN(n)
|
||||
}
|
||||
|
||||
// Remove the first occurrence of an element from the list
|
||||
func (rl *List) RemoveElement(value string) error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("LREM", rl.id, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set element of list at index n to value
|
||||
func (rl *List) Set(index int64, value string) error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("LSET", rl.id, index, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Trim an existing list so that it will contain only the specified range of
|
||||
// elements specified.
|
||||
func (rl *List) Trim(start, stop int64) error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("LTRIM", rl.id, start, stop)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove this list
|
||||
func (rl *List) Remove() error {
|
||||
conn := rl.pool.Get(rl.dbindex)
|
||||
_, err := conn.Do("DEL", rl.id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear the contents
|
||||
func (rl *List) Clear() error {
|
||||
return rl.Remove()
|
||||
}
|
||||
|
||||
/* --- Set functions --- */
|
||||
|
||||
// Create a new set
|
||||
func NewSet(pool *ConnectionPool, id string) *Set {
|
||||
return &Set{pool, id, 0}
|
||||
}
|
||||
|
||||
// Select a different database
|
||||
func (rs *Set) SelectDatabase(dbindex int) {
|
||||
rs.dbindex = dbindex
|
||||
}
|
||||
|
||||
// Add an element to the set
|
||||
func (rs *Set) Add(value string) error {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
_, err := conn.Do("SADD", rs.id, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Returns the set cardinality (number of elements) of the set
|
||||
func (rs *Set) Size() (int64, error) {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
size, err := conn.Do("SCARD", rs.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.Int64(size, err)
|
||||
}
|
||||
|
||||
// Check if a given value is in the set
|
||||
func (rs *Set) Has(value string) (bool, error) {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
retval, err := conn.Do("SISMEMBER", rs.id, value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.Bool(retval, err)
|
||||
}
|
||||
|
||||
// Get all elements of the set
|
||||
func (rs *Set) All() ([]string, error) {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
result, err := redis.Values(conn.Do("SMEMBERS", rs.id))
|
||||
strs := make([]string, len(result))
|
||||
for i := 0; i < len(result); i++ {
|
||||
strs[i] = getString(result, i)
|
||||
}
|
||||
return strs, err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (rs *Set) GetAll() ([]string, error) {
|
||||
return rs.All()
|
||||
}
|
||||
|
||||
// Remove a random member from the set
|
||||
func (rs *Set) Pop() (string, error) {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
result, err := conn.Do("SPOP", rs.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.String(result, err)
|
||||
}
|
||||
|
||||
// Get a random member of the set
|
||||
func (rs *Set) Random() (string, error) {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
result, err := conn.Do("SRANDMEMBER", rs.id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.String(result, err)
|
||||
}
|
||||
|
||||
// Remove an element from the set
|
||||
func (rs *Set) Del(value string) error {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
_, err := conn.Do("SREM", rs.id, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove this set
|
||||
func (rs *Set) Remove() error {
|
||||
conn := rs.pool.Get(rs.dbindex)
|
||||
_, err := conn.Do("DEL", rs.id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear the contents
|
||||
func (rs *Set) Clear() error {
|
||||
return rs.Remove()
|
||||
}
|
||||
|
||||
/* --- HashMap functions --- */
|
||||
|
||||
// Create a new hashmap
|
||||
func NewHashMap(pool *ConnectionPool, id string) *HashMap {
|
||||
return &HashMap{pool, id, 0}
|
||||
}
|
||||
|
||||
// Select a different database
|
||||
func (rh *HashMap) SelectDatabase(dbindex int) {
|
||||
rh.dbindex = dbindex
|
||||
}
|
||||
|
||||
// Set a value in a hashmap given the element id (for instance a user id) and the key (for instance "password")
|
||||
func (rh *HashMap) Set(elementid, key, value string) error {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
_, err := conn.Do("HSET", rh.id+":"+elementid, key, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Given an element id, set a key and a value together with an expiration time
|
||||
func (rh *HashMap) SetExpire(elementid, key, value string, expire time.Duration) error {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
if _, err := conn.Do("HSET", rh.id+":"+elementid, key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
// No EXPIRE in Redis for hash keys, as far as I can tell from the documentation.
|
||||
// This is the manual way.
|
||||
go func() {
|
||||
time.Sleep(expire)
|
||||
rh.DelKey(elementid, key)
|
||||
}()
|
||||
// Set the elementid to expire in the given duration (as milliseconds)
|
||||
//expireMilliseconds := expire.Nanoseconds() / 1000000
|
||||
//if _, err := conn.Do("PEXPIRE", rh.id+":"+elementid, expireMilliseconds); err != nil {
|
||||
// return err
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commented out because this would only return TTL for the elementid, not for the key
|
||||
// TimeToLive returns how long a key has to live until it expires
|
||||
// Returns a duration of 0 when the time has passed
|
||||
//func (rh *HashMap) TimeToLive(elementid string) (time.Duration, error) {
|
||||
// conn := rh.pool.Get(rh.dbindex)
|
||||
// ttlSecondsInterface, err := conn.Do("TTL", rh.id+":"+elementid)
|
||||
// if err != nil || ttlSecondsInterface.(int64) <= 0 {
|
||||
// return time.Duration(0), err
|
||||
// }
|
||||
// ns := time.Duration(ttlSecondsInterface.(int64)) * time.Second
|
||||
// return ns, nil
|
||||
//}
|
||||
|
||||
// Get a value from a hashmap given the element id (for instance a user id) and the key (for instance "password")
|
||||
func (rh *HashMap) Get(elementid, key string) (string, error) {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
result, err := redis.String(conn.Do("HGET", rh.id+":"+elementid, key))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Check if a given elementid + key is in the hash map
|
||||
func (rh *HashMap) Has(elementid, key string) (bool, error) {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
retval, err := conn.Do("HEXISTS", rh.id+":"+elementid, key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return redis.Bool(retval, err)
|
||||
}
|
||||
|
||||
// Keys returns the keys of the given elementid.
|
||||
func (rh *HashMap) Keys(elementid string) ([]string, error) {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
result, err := redis.Values(conn.Do("HKEYS", rh.id+":"+elementid))
|
||||
strs := make([]string, len(result))
|
||||
for i := 0; i < len(result); i++ {
|
||||
strs[i] = getString(result, i)
|
||||
}
|
||||
return strs, err
|
||||
}
|
||||
|
||||
// Check if a given elementid exists as a hash map at all
|
||||
func (rh *HashMap) Exists(elementid string) (bool, error) {
|
||||
// TODO: key is not meant to be a wildcard, check for "*"
|
||||
return hasKey(rh.pool, rh.id+":"+elementid, rh.dbindex)
|
||||
}
|
||||
|
||||
// Get all elementid's for all hash elements
|
||||
func (rh *HashMap) All() ([]string, error) {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
result, err := redis.Values(conn.Do("KEYS", rh.id+":*"))
|
||||
strs := make([]string, len(result))
|
||||
idlen := len(rh.id)
|
||||
for i := 0; i < len(result); i++ {
|
||||
strs[i] = getString(result, i)[idlen+1:]
|
||||
}
|
||||
return strs, err
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
func (rh *HashMap) GetAll() ([]string, error) {
|
||||
return rh.All()
|
||||
}
|
||||
|
||||
// Remove a key for an entry in a hashmap (for instance the email field for a user)
|
||||
func (rh *HashMap) DelKey(elementid, key string) error {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
_, err := conn.Do("HDEL", rh.id+":"+elementid, key)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove an element (for instance a user)
|
||||
func (rh *HashMap) Del(elementid string) error {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
_, err := conn.Do("DEL", rh.id+":"+elementid)
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove this hashmap (all keys that starts with this hashmap id and a colon)
|
||||
func (rh *HashMap) Remove() error {
|
||||
conn := rh.pool.Get(rh.dbindex)
|
||||
// Find all hashmap keys that starts with rh.id+":"
|
||||
results, err := redis.Values(conn.Do("KEYS", rh.id+":*"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// For each key id
|
||||
for i := 0; i < len(results); i++ {
|
||||
// Delete this key
|
||||
if _, err = conn.Do("DEL", getString(results, i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clear the contents
|
||||
func (rh *HashMap) Clear() error {
|
||||
return rh.Remove()
|
||||
}
|
||||
|
||||
/* --- KeyValue functions --- */
|
||||
|
||||
// Create a new key/value
|
||||
func NewKeyValue(pool *ConnectionPool, id string) *KeyValue {
|
||||
return &KeyValue{pool, id, 0}
|
||||
}
|
||||
|
||||
// Select a different database
|
||||
func (rkv *KeyValue) SelectDatabase(dbindex int) {
|
||||
rkv.dbindex = dbindex
|
||||
}
|
||||
|
||||
// Set a key and value
|
||||
func (rkv *KeyValue) Set(key, value string) error {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
_, err := conn.Do("SET", rkv.id+":"+key, value)
|
||||
return err
|
||||
}
|
||||
|
||||
// Set a key and value, with expiry
|
||||
func (rkv *KeyValue) SetExpire(key, value string, expire time.Duration) error {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
// Convert from nanoseconds to milliseconds
|
||||
expireMilliseconds := expire.Nanoseconds() / 1000000
|
||||
// Set the value, together with an expiry time, given in milliseconds
|
||||
_, err := conn.Do("SET", rkv.id+":"+key, value, "PX", expireMilliseconds)
|
||||
return err
|
||||
}
|
||||
|
||||
// TimeToLive returns how long a key has to live until it expires
|
||||
// Returns a duration of 0 when the time has passed
|
||||
func (rkv *KeyValue) TimeToLive(key string) (time.Duration, error) {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
ttlSecondsInterface, err := conn.Do("TTL", rkv.id+":"+key)
|
||||
if err != nil || ttlSecondsInterface.(int64) <= 0 {
|
||||
return time.Duration(0), err
|
||||
}
|
||||
ns := time.Duration(ttlSecondsInterface.(int64)) * time.Second
|
||||
return ns, nil
|
||||
}
|
||||
|
||||
// Get a value given a key
|
||||
func (rkv *KeyValue) Get(key string) (string, error) {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
result, err := redis.String(conn.Do("GET", rkv.id+":"+key))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Remove a key
|
||||
func (rkv *KeyValue) Del(key string) error {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
_, err := conn.Do("DEL", rkv.id+":"+key)
|
||||
return err
|
||||
}
|
||||
|
||||
// Increase the value of a key, returns the new value
|
||||
// Returns an empty string if there were errors,
|
||||
// or "0" if the key does not already exist.
|
||||
func (rkv *KeyValue) Inc(key string) (string, error) {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
result, err := redis.Int64(conn.Do("INCR", rkv.id+":"+key))
|
||||
if err != nil {
|
||||
return "0", err
|
||||
}
|
||||
return strconv.FormatInt(result, 10), nil
|
||||
}
|
||||
|
||||
// Remove this key/value
|
||||
func (rkv *KeyValue) Remove() error {
|
||||
conn := rkv.pool.Get(rkv.dbindex)
|
||||
// Find all keys that starts with rkv.id+":"
|
||||
results, err := redis.Values(conn.Do("KEYS", rkv.id+":*"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// For each key id
|
||||
for i := 0; i < len(results); i++ {
|
||||
// Delete this key
|
||||
if _, err = conn.Do("DEL", getString(results, i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clear the contents
|
||||
func (rkv *KeyValue) Clear() error {
|
||||
return rkv.Remove()
|
||||
}
|
||||
|
||||
// --- Generic redis functions ---
|
||||
|
||||
// Check if a key exists. The key can be a wildcard (ie. "user*").
|
||||
func hasKey(pool *ConnectionPool, wildcard string, dbindex int) (bool, error) {
|
||||
conn := pool.Get(dbindex)
|
||||
result, err := redis.Values(conn.Do("KEYS", wildcard))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(result) > 0, nil
|
||||
}
|
||||
|
||||
// --- Related to setting and retrieving timeout values
|
||||
|
||||
// SetConnectTimeout sets the connect timeout for new connections
|
||||
func SetConnectTimeout(t time.Duration) {
|
||||
connectTimeout = t
|
||||
}
|
||||
|
||||
// SetReadTimeout sets the read timeout for new connections
|
||||
func SetReadTimeout(t time.Duration) {
|
||||
readTimeout = t
|
||||
}
|
||||
|
||||
// SetWriteTimeout sets the write timeout for new connections
|
||||
func SetWriteTimeout(t time.Duration) {
|
||||
writeTimeout = t
|
||||
}
|
||||
|
||||
// SetIdleTimeout sets the idle timeout for new connections
|
||||
func SetIdleTimeout(t time.Duration) {
|
||||
idleTimeout = t
|
||||
}
|
||||
|
||||
// ConnectTimeout returns the current connect timeout for new connections
|
||||
func ConnectTimeout() time.Duration {
|
||||
return connectTimeout
|
||||
}
|
||||
|
||||
// ReadTimeout returns the current read timeout for new connections
|
||||
func ReadTimeout() time.Duration {
|
||||
return readTimeout
|
||||
}
|
||||
|
||||
// WriteTimeout returns the current write timeout for new connections
|
||||
func WriteTimeout() time.Duration {
|
||||
return writeTimeout
|
||||
}
|
||||
|
||||
// IdleTimeout returns the current idle timeout for new connections
|
||||
func IdleTimeout() time.Duration {
|
||||
return idleTimeout
|
||||
}
|
||||
Reference in New Issue
Block a user