1
0
mirror of https://github.com/rancher/os.git synced 2025-06-01 11:25:51 +00:00
os/util/util.go

290 lines
5.3 KiB
Go
Raw Normal View History

2015-02-09 04:38:37 +00:00
package util
import (
"archive/tar"
2015-03-25 22:27:33 +00:00
"bufio"
2015-04-16 06:16:23 +00:00
"errors"
2015-02-09 04:38:37 +00:00
"fmt"
"io"
"io/ioutil"
"math/rand"
"net/http"
2015-02-09 04:38:37 +00:00
"os"
"path"
"strings"
2015-02-09 04:38:37 +00:00
2015-03-25 22:27:33 +00:00
"gopkg.in/yaml.v2"
2015-04-16 05:57:59 +00:00
log "github.com/Sirupsen/logrus"
2015-02-09 04:38:37 +00:00
"github.com/docker/docker/pkg/mount"
)
var (
2015-04-16 06:16:23 +00:00
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
ErrNoNetwork = errors.New("Networking not available to load resource")
2015-04-16 05:57:59 +00:00
ErrNotFound = errors.New("Failed to find resource")
)
2015-03-25 22:27:33 +00:00
func GetOSType() string {
f, err := os.Open("/etc/os-release")
defer f.Close()
if err != nil {
return "busybox"
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if len(line) > 8 && line[:8] == "ID_LIKE=" {
return line[8:]
}
}
return "busybox"
}
2015-02-09 04:38:37 +00:00
func Remount(directory, options string) error {
return mount.Mount("", directory, "", fmt.Sprintf("remount,%s", options))
}
func ExtractTar(archive string, dest string) error {
f, err := os.Open(archive)
if err != nil {
return err
}
defer f.Close()
input := tar.NewReader(f)
for {
header, err := input.Next()
if err == io.EOF {
break
} else if err != nil {
return err
}
if header == nil {
break
}
fileInfo := header.FileInfo()
fileName := path.Join(dest, header.Name)
if fileInfo.IsDir() {
//log.Debugf("DIR : %s", fileName)
err = os.MkdirAll(fileName, fileInfo.Mode())
if err != nil {
return err
}
} else {
//log.Debugf("FILE: %s", fileName)
destFile, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileInfo.Mode())
if err != nil {
return err
}
_, err = io.Copy(destFile, input)
// Not deferring, concerned about holding open too many files
destFile.Close()
if err != nil {
return err
}
}
}
return nil
}
func Contains(values []string, value string) bool {
if len(value) == 0 {
return false
}
for _, i := range values {
if i == value {
return true
}
}
return false
}
type ReturnsErr func() error
func ShortCircuit(funcs ...ReturnsErr) error {
for _, f := range funcs {
err := f()
if err != nil {
return err
}
}
return nil
}
type ErrWriter struct {
w io.Writer
Err error
}
func NewErrorWriter(w io.Writer) *ErrWriter {
return &ErrWriter{
w: w,
}
}
func (e *ErrWriter) Write(buf []byte) *ErrWriter {
if e.Err != nil {
return e
}
_, e.Err = e.w.Write(buf)
return e
}
func RandSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
2015-03-15 04:27:04 +00:00
func Convert(from, to interface{}) error {
bytes, err := yaml.Marshal(from)
if err != nil {
return err
}
return yaml.Unmarshal(bytes, to)
}
2015-03-18 13:22:19 +00:00
2015-04-16 06:16:23 +00:00
func MergeBytes(left, right []byte) ([]byte, error) {
leftMap := make(map[interface{}]interface{})
rightMap := make(map[interface{}]interface{})
err := yaml.Unmarshal(left, &leftMap)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(right, &rightMap)
if err != nil {
return nil, err
}
MergeMaps(leftMap, rightMap)
return yaml.Marshal(leftMap)
}
2015-03-18 13:22:19 +00:00
func MergeMaps(left, right map[interface{}]interface{}) {
for k, v := range right {
merged := false
if existing, ok := left[k]; ok {
if rightMap, ok := v.(map[interface{}]interface{}); ok {
if leftMap, ok := existing.(map[interface{}]interface{}); ok {
merged = true
MergeMaps(leftMap, rightMap)
}
}
}
if !merged {
left[k] = v
}
}
}
2015-04-16 05:57:59 +00:00
func GetServices(urls []string) ([]string, error) {
result := []string{}
for _, url := range urls {
indexUrl := fmt.Sprintf("%s/index.yml", url)
content, err := LoadResource(indexUrl, true, []string{})
if err != nil {
log.Errorf("Failed to load %s: %v", indexUrl, err)
continue
}
services := make(map[string][]string)
err = yaml.Unmarshal(content, &services)
if err != nil {
log.Errorf("Failed to unmarshal %s: %v", indexUrl, err)
continue
}
if list, ok := services["services"]; ok {
result = append(result, list...)
}
}
2015-05-26 21:00:18 +00:00
return result, nil
2015-04-16 05:57:59 +00:00
}
func LoadResource(location string, network bool, urls []string) ([]byte, error) {
var bytes []byte
err := ErrNotFound
if strings.HasPrefix(location, "http:/") || strings.HasPrefix(location, "https:/") {
2015-04-16 06:16:23 +00:00
if !network {
return nil, ErrNoNetwork
}
resp, err := http.Get(location)
if err != nil {
return nil, err
}
2015-04-16 05:57:59 +00:00
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("non-200 http response: %d", resp.StatusCode)
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
2015-04-16 05:57:59 +00:00
} else if strings.HasPrefix(location, "/") {
return ioutil.ReadFile(location)
2015-04-16 05:57:59 +00:00
} else if len(location) > 0 {
for _, url := range urls {
ymlUrl := fmt.Sprintf("%s/%s/%s.yml", url, location[0:1], location)
bytes, err = LoadResource(ymlUrl, network, []string{})
if err == nil {
2015-04-17 13:31:38 +00:00
log.Debugf("Loaded %s from %s", location, ymlUrl)
2015-04-16 05:57:59 +00:00
return bytes, nil
}
}
}
return nil, err
}
func GetValue(kvPairs []string, key string) string {
if kvPairs == nil {
return ""
}
prefix := key + "="
for _, i := range kvPairs {
if strings.HasPrefix(i, prefix) {
return strings.TrimPrefix(i, prefix)
}
}
2015-04-16 05:57:59 +00:00
return ""
}
func Map2KVPairs(m map[string]string) []string {
r := make([]string, 0, len(m))
for k, v := range m {
r = append(r, k+"="+v)
}
return r
}
func KVPairs2Map(kvs []string) map[string]string {
r := make(map[string]string, len(kvs))
for _, kv := range kvs {
2015-04-30 08:43:45 +00:00
s := strings.SplitN(kv, "=", 2)
r[s[0]] = s[1]
}
return r
}