vendor
This commit is contained in:
27
vendor/novit.nc/direktil/pkg/cas/cas.go
vendored
Normal file
27
vendor/novit.nc/direktil/pkg/cas/cas.go
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Package cas provides a content-accessible storage implementation
|
||||
package cas
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Content is an item's content.
|
||||
type Content interface {
|
||||
io.Reader
|
||||
io.Seeker
|
||||
io.Closer
|
||||
}
|
||||
|
||||
// Meta is an item's metadata.
|
||||
type Meta interface {
|
||||
Size() int64
|
||||
ModTime() time.Time
|
||||
}
|
||||
|
||||
// Store is a CAS store.
|
||||
type Store interface {
|
||||
GetOrCreate(tag, item string, create func(io.Writer) error) (content Content, meta Meta, err error)
|
||||
Tags() (tags []string, err error)
|
||||
Remove(tag string) error
|
||||
}
|
112
vendor/novit.nc/direktil/pkg/cas/dir-store.go
vendored
Normal file
112
vendor/novit.nc/direktil/pkg/cas/dir-store.go
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package cas
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// NewDirStore create a new store backed by the given directory.
|
||||
func NewDir(path string) *DirStore {
|
||||
return &DirStore{
|
||||
path: path,
|
||||
}
|
||||
}
|
||||
|
||||
// DirStore is a Store backed by a directory.
|
||||
type DirStore struct {
|
||||
path string
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
var _ Store = &DirStore{}
|
||||
|
||||
// GetOrCreate is part of the Store interface.
|
||||
func (s *DirStore) GetOrCreate(tag, item string, create func(io.Writer) error) (content Content, meta Meta, err error) {
|
||||
fullPath := filepath.Join(s.path, tag, item)
|
||||
|
||||
f, err := os.Open(fullPath)
|
||||
if err != nil {
|
||||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
f, err = os.Open(fullPath)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(fullPath), 0700)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var out *os.File
|
||||
out, err = os.OpenFile(fullPath+".part", os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = create(out)
|
||||
|
||||
out.Close()
|
||||
|
||||
if err != nil {
|
||||
os.Remove(fullPath + ".part")
|
||||
return
|
||||
}
|
||||
|
||||
if err = os.Rename(fullPath+".part", fullPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
f, err = os.Open(fullPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
stat, err := os.Stat(fullPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return f, stat, nil
|
||||
}
|
||||
|
||||
// Tags is part of the Store interface.
|
||||
func (s *DirStore) Tags() (tags []string, err error) {
|
||||
entries, err := ioutil.ReadDir(s.path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return []string{}, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
tags = make([]string, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
name := entry.Name()
|
||||
|
||||
if name[0] == '.' {
|
||||
continue
|
||||
}
|
||||
|
||||
tags = append(tags, name)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Remove is part of the Store interface.
|
||||
func (s *DirStore) Remove(tag string) error {
|
||||
return os.RemoveAll(filepath.Join(s.path, tag))
|
||||
}
|
10
vendor/novit.nc/direktil/pkg/clustersconfig/cert-request.go
vendored
Normal file
10
vendor/novit.nc/direktil/pkg/clustersconfig/cert-request.go
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
package clustersconfig
|
||||
|
||||
type CertRequest struct {
|
||||
Template `yaml:",inline"`
|
||||
|
||||
CA string
|
||||
Profile string
|
||||
Label string
|
||||
PerHost bool `yaml:"per_host"`
|
||||
}
|
220
vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go
vendored
Normal file
220
vendor/novit.nc/direktil/pkg/clustersconfig/clustersconfig.go
vendored
Normal file
@ -0,0 +1,220 @@
|
||||
package clustersconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Hosts []*Host
|
||||
Groups []*Group
|
||||
Clusters []*Cluster
|
||||
Configs []*Template
|
||||
StaticPods []*Template `yaml:"static_pods"`
|
||||
SSLConfig string `yaml:"ssl_config"`
|
||||
CertRequests []*CertRequest `yaml:"cert_requests"`
|
||||
}
|
||||
|
||||
func FromBytes(data []byte) (*Config, error) {
|
||||
config := &Config{}
|
||||
if err := yaml.Unmarshal(data, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func FromFile(path string) (*Config, error) {
|
||||
ba, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return FromBytes(ba)
|
||||
}
|
||||
|
||||
func (c *Config) Host(name string) *Host {
|
||||
for _, host := range c.Hosts {
|
||||
if host.Name == name {
|
||||
return host
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) HostByIP(ip string) *Host {
|
||||
for _, host := range c.Hosts {
|
||||
if host.IP == ip {
|
||||
return host
|
||||
}
|
||||
|
||||
for _, otherIP := range host.IPs {
|
||||
if otherIP == ip {
|
||||
return host
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) HostByMAC(mac string) *Host {
|
||||
// a bit of normalization
|
||||
mac = strings.Replace(strings.ToLower(mac), "-", ":", -1)
|
||||
|
||||
for _, host := range c.Hosts {
|
||||
if strings.ToLower(host.MAC) == mac {
|
||||
return host
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) Group(name string) *Group {
|
||||
for _, group := range c.Groups {
|
||||
if group.Name == name {
|
||||
return group
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) Cluster(name string) *Cluster {
|
||||
for _, cluster := range c.Clusters {
|
||||
if cluster.Name == name {
|
||||
return cluster
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) ConfigTemplate(name string) *Template {
|
||||
for _, cfg := range c.Configs {
|
||||
if cfg.Name == name {
|
||||
return cfg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) StaticPodsTemplate(name string) *Template {
|
||||
for _, s := range c.StaticPods {
|
||||
if s.Name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) CSR(name string) *CertRequest {
|
||||
for _, s := range c.CertRequests {
|
||||
if s.Name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) SaveTo(path string) error {
|
||||
ba, err := yaml.Marshal(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(path, ba, 0600)
|
||||
}
|
||||
|
||||
type Template struct {
|
||||
Name string
|
||||
Template string
|
||||
|
||||
parsedTemplate *template.Template
|
||||
}
|
||||
|
||||
func (t *Template) Execute(wr io.Writer, data interface{}, extraFuncs map[string]interface{}) error {
|
||||
if t.parsedTemplate == nil {
|
||||
var templateFuncs = map[string]interface{}{
|
||||
"indent": func(indent, s string) (indented string) {
|
||||
indented = indent + strings.Replace(s, "\n", "\n"+indent, -1)
|
||||
return
|
||||
},
|
||||
}
|
||||
|
||||
for name, f := range extraFuncs {
|
||||
templateFuncs[name] = f
|
||||
}
|
||||
|
||||
tmpl, err := template.New("tmpl").
|
||||
Funcs(templateFuncs).
|
||||
Parse(t.Template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.parsedTemplate = tmpl
|
||||
}
|
||||
|
||||
return t.parsedTemplate.Execute(wr, data)
|
||||
}
|
||||
|
||||
// Host represents a host served by this server.
|
||||
type Host struct {
|
||||
Name string
|
||||
MAC string
|
||||
IP string
|
||||
IPs []string
|
||||
Cluster string
|
||||
Group string
|
||||
Vars Vars
|
||||
}
|
||||
|
||||
// Group represents a group of hosts and provides their configuration.
|
||||
type Group struct {
|
||||
Name string
|
||||
Master bool
|
||||
IPXE string
|
||||
Kernel string
|
||||
Initrd string
|
||||
Config string
|
||||
StaticPods string `yaml:"static_pods"`
|
||||
Versions map[string]string
|
||||
Vars Vars
|
||||
}
|
||||
|
||||
// Vars store user-defined key-values
|
||||
type Vars map[string]interface{}
|
||||
|
||||
// Cluster represents a cluster of hosts, allowing for cluster-wide variables.
|
||||
type Cluster struct {
|
||||
Name string
|
||||
Domain string
|
||||
Subnets struct {
|
||||
Services string
|
||||
Pods string
|
||||
}
|
||||
Vars Vars
|
||||
}
|
||||
|
||||
func (c *Cluster) KubernetesSvcIP() net.IP {
|
||||
return c.NthSvcIP(1)
|
||||
}
|
||||
|
||||
func (c *Cluster) DNSSvcIP() net.IP {
|
||||
return c.NthSvcIP(2)
|
||||
}
|
||||
|
||||
func (c *Cluster) NthSvcIP(n byte) net.IP {
|
||||
_, cidr, err := net.ParseCIDR(c.Subnets.Services)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("Invalid services CIDR: %v", err))
|
||||
}
|
||||
|
||||
ip := cidr.IP
|
||||
ip[len(ip)-1] += n
|
||||
|
||||
return ip
|
||||
}
|
149
vendor/novit.nc/direktil/pkg/clustersconfig/dir.go
vendored
Normal file
149
vendor/novit.nc/direktil/pkg/clustersconfig/dir.go
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package clustersconfig
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func FromDir(dirPath string) (*Config, error) {
|
||||
config := &Config{}
|
||||
|
||||
store := dirStore{dirPath}
|
||||
load := func(dir, name string, out interface{}) error {
|
||||
ba, err := store.Get(path.Join(dir, name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return yaml.Unmarshal(ba, out)
|
||||
}
|
||||
|
||||
// load clusters
|
||||
names, err := store.List("clusters")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
cluster := &Cluster{Name: name}
|
||||
if err := load("clusters", name, cluster); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.Clusters = append(config.Clusters, cluster)
|
||||
}
|
||||
|
||||
// load groups
|
||||
names, err = store.List("groups")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
o := &Group{Name: name}
|
||||
if err := load("groups", name, o); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.Groups = append(config.Groups, o)
|
||||
}
|
||||
|
||||
// load hosts
|
||||
names, err = store.List("hosts")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
o := &Host{Name: name}
|
||||
if err := load("hosts", name, o); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.Hosts = append(config.Hosts, o)
|
||||
}
|
||||
|
||||
// load config templates
|
||||
loadTemplates := func(dir string, templates *[]*Template) error {
|
||||
names, err = store.List(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
ba, err := store.Get(path.Join(dir, name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o := &Template{Name: name, Template: string(ba)}
|
||||
|
||||
*templates = append(*templates, o)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := loadTemplates("configs", &config.Configs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := loadTemplates("static-pods", &config.StaticPods); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ba, err := ioutil.ReadFile(filepath.Join(dirPath, "ssl-config.json")); err == nil {
|
||||
config.SSLConfig = string(ba)
|
||||
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if ba, err := ioutil.ReadFile(filepath.Join(dirPath, "cert-requests.yaml")); err == nil {
|
||||
reqs := make([]*CertRequest, 0)
|
||||
if err = yaml.Unmarshal(ba, &reqs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.CertRequests = reqs
|
||||
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type dirStore struct {
|
||||
path string
|
||||
}
|
||||
|
||||
// Names is part of the kvStore interface
|
||||
func (b *dirStore) List(prefix string) ([]string, error) {
|
||||
files, err := filepath.Glob(filepath.Join(b.path, filepath.Join(path.Split(prefix)), "*.yaml"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
names := make([]string, 0, len(files))
|
||||
for _, f := range files {
|
||||
f2 := strings.TrimSuffix(f, ".yaml")
|
||||
f2 = filepath.Base(f2)
|
||||
|
||||
if f2[0] == '.' { // ignore hidden files
|
||||
continue
|
||||
}
|
||||
|
||||
names = append(names, f2)
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// Load is part of the DataBackend interface
|
||||
func (b *dirStore) Get(key string) ([]byte, error) {
|
||||
return ioutil.ReadFile(filepath.Join(b.path, filepath.Join(path.Split(key))+".yaml"))
|
||||
}
|
101
vendor/novit.nc/direktil/pkg/config/config.go
vendored
Normal file
101
vendor/novit.nc/direktil/pkg/config/config.go
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// Config represent this system's configuration
|
||||
type Config struct {
|
||||
Vars []VarDefault
|
||||
|
||||
Layers []string
|
||||
Modules []string
|
||||
|
||||
RootUser struct {
|
||||
PasswordHash string `yaml:"password_hash"`
|
||||
AuthorizedKeys []string `yaml:"authorized_keys"`
|
||||
} `yaml:"root_user"`
|
||||
|
||||
Storage StorageConfig
|
||||
|
||||
Groups []GroupDef
|
||||
Users []UserDef
|
||||
|
||||
Files []FileDef
|
||||
|
||||
Networks []NetworkDef
|
||||
}
|
||||
|
||||
type VarDefault struct {
|
||||
Name string
|
||||
Default string
|
||||
}
|
||||
|
||||
type StorageConfig struct {
|
||||
UdevMatch string `yaml:"udev_match"`
|
||||
RemoveVolumes []string `yaml:"remove_volumes"`
|
||||
Volumes []VolumeDef
|
||||
}
|
||||
|
||||
type VolumeDef struct {
|
||||
Name string
|
||||
Size string
|
||||
Extents string
|
||||
FS string
|
||||
Mount struct {
|
||||
Path string
|
||||
Options string
|
||||
}
|
||||
}
|
||||
|
||||
type GroupDef struct {
|
||||
Name string
|
||||
Gid int
|
||||
}
|
||||
|
||||
type UserDef struct {
|
||||
Name string
|
||||
Gid int
|
||||
Uid int
|
||||
}
|
||||
|
||||
type FileDef struct {
|
||||
Path string
|
||||
Mode os.FileMode
|
||||
Content string
|
||||
}
|
||||
|
||||
type NetworkDef struct {
|
||||
Match struct {
|
||||
All bool
|
||||
Name string
|
||||
Ping *struct {
|
||||
Source string
|
||||
Target string
|
||||
Count int
|
||||
Timeout int
|
||||
}
|
||||
}
|
||||
Optional bool
|
||||
Script string
|
||||
}
|
||||
|
||||
func Load(file string) (config *Config, err error) {
|
||||
config = &Config{}
|
||||
|
||||
configData, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read %s: %v", file, err)
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(configData, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse %s: %v", file, err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user