package server import ( "encoding/json" "fmt" "os" "strings" "time" "github.com/docker/distribution" "github.com/docker/distribution/context" "github.com/docker/distribution/manifest/schema2" imageapi "github.com/openshift/origin/pkg/image/api" ) // Context keys const ( // repositoryKey serves to store/retrieve repository object to/from context. repositoryKey = "openshift.repository" ) func WithRepository(parent context.Context, repo *repository) context.Context { return context.WithValue(parent, repositoryKey, repo) } func RepositoryFrom(ctx context.Context) (repo *repository, found bool) { repo, found = ctx.Value(repositoryKey).(*repository) return } func getOptionValue( envVar string, optionName string, defval interface{}, options map[string]interface{}, conversionFunc func(v interface{}) (interface{}, error), ) (value interface{}, err error) { value = defval if optValue, ok := options[optionName]; ok { converted, convErr := conversionFunc(optValue) if convErr != nil { err = fmt.Errorf("config option %q: invalid value: %v", optionName, convErr) } else { value = converted } } if len(envVar) == 0 { return } envValue := os.Getenv(envVar) if len(envValue) == 0 { return } converted, convErr := conversionFunc(envValue) if convErr != nil { err = fmt.Errorf("invalid value of environment variable %s: %v", envVar, convErr) } else { value = converted } return } func getBoolOption(envVar string, optionName string, defval bool, options map[string]interface{}) (bool, error) { value, err := getOptionValue(envVar, optionName, defval, options, func(value interface{}) (b interface{}, err error) { switch t := value.(type) { case bool: return t, nil case string: switch strings.ToLower(t) { case "true": return true, nil case "false": return false, nil } } return defval, fmt.Errorf("%#+v is not a boolean", value) }) return value.(bool), err } func getDurationOption(envVar string, optionName string, defval time.Duration, options map[string]interface{}) (time.Duration, error) { value, err := getOptionValue(envVar, optionName, defval, options, func(value interface{}) (d interface{}, err error) { s, ok := value.(string) if !ok { return defval, fmt.Errorf("expected string, not %T", value) } parsed, err := time.ParseDuration(s) if err != nil { return defval, fmt.Errorf("parse duration error: %v", err) } return parsed, nil }) return value.(time.Duration), err } // deserializedManifestFromImage converts an Image to a DeserializedManifest. func deserializedManifestFromImage(image *imageapi.Image) (*schema2.DeserializedManifest, error) { var manifest schema2.DeserializedManifest if err := json.Unmarshal([]byte(image.DockerImageManifest), &manifest); err != nil { return nil, err } return &manifest, nil } func getNamespaceName(resourceName string) (string, string, error) { repoParts := strings.SplitN(resourceName, "/", 2) if len(repoParts) != 2 { return "", "", ErrNamespaceRequired } ns := repoParts[0] if len(ns) == 0 { return "", "", ErrNamespaceRequired } name := repoParts[1] if len(name) == 0 { return "", "", ErrNamespaceRequired } return ns, name, nil } // effectiveCreateOptions find out what the blob creation options are going to do by dry-running them. func effectiveCreateOptions(options []distribution.BlobCreateOption) (*distribution.CreateOptions, error) { opts := &distribution.CreateOptions{} for _, createOptions := range options { err := createOptions.Apply(opts) if err != nil { return nil, err } } return opts, nil }