-
Couldn't load subscription status.
- Fork 881
config: add config subcommand #2405
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # rkt config | ||
|
|
||
| The `config` subcommand prints the configuration of each rkt stage in JSON on the standard output. | ||
|
|
||
| ## Structure | ||
|
|
||
| The general structure is a simple hierarchy consisting of the following top-level element: | ||
|
|
||
| ``` | ||
| { | ||
| "stage0": [...] | ||
| } | ||
| ``` | ||
|
|
||
| The entry "stage0" refers to stage-specific configuration; "stage1" is currently left out intentionally because its configuration subsystem is subject to change. The generated output are valid configuration entries as specified in the configuration documentation. | ||
|
|
||
| The "stage0" entry contains subentries of rktKind "auth", "dockerAuth", "paths", and "stage1". Note that the `config` subcommand will output separate entries per "auth" domain and separate entries per "dockerAuth" registry. While it is possible to specify an array of strings in the input configuration rkt internally merges configuration state from different directories potentially creating multiple entries. | ||
|
|
||
| Consider the following system configuration: | ||
| ``` | ||
| $ cat /etc/rkt/auth.d/basic.json | ||
| { | ||
| "rktKind": "auth", | ||
| "rktVersion": "v1", | ||
| "domains": [ | ||
| "foo.com", | ||
| "bar.com", | ||
| "baz.com" | ||
| ], | ||
| "type": "basic", | ||
| "credentials": { "user": "sysUser", "password": "sysPassword" } | ||
| } | ||
| ``` | ||
|
|
||
| And the following user configuration: | ||
| ``` | ||
| $ ~/.config/rkt/auth.d/basic.json | ||
| { | ||
| "rktKind": "auth", | ||
| "rktVersion": "v1", | ||
| "domains": [ | ||
| "foo.com" | ||
| ], | ||
| "type": "basic", | ||
| "credentials": { "user": "user", "password": "password" } | ||
| } | ||
| ``` | ||
|
|
||
| The `config` subcommand would generate the following separate merged entries: | ||
| ``` | ||
| { | ||
| "stage0": [ | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "auth", | ||
| "domains": [ "bar.com" ], | ||
| "type": "basic", | ||
| "credentials": { "user": "sysUser", "password": "sysPassword" } | ||
| }, | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "auth", | ||
| "domains": [ "baz.com" ], | ||
| "type": "basic", | ||
| "credentials": { "user": "sysUser", "password": "sysPassword" } | ||
| }, | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "auth", | ||
| "domains": [ "foo.com" ], | ||
| "type": "basic", | ||
| "credentials": { "user": "user", "password": "password" } | ||
| } | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| In the example given above the user configuration entry for the domain "foo.com" overrides the system configuration entry leaving the entries "bar.com" and "baz.com" unchanged. The `config` subcommand output creates three separate entries for "foo.com", "bar.com", and "baz.com". | ||
|
|
||
| Note: While the "bar.com", and "baz.com" entries in the example given above could be merged into one entry they are still being printed separate. This behavior is subject to change, future implementations may provide a merged output. | ||
|
|
||
| ## Example | ||
|
|
||
| ``` | ||
| $ rkt config | ||
| { | ||
| "stage0": [ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OOB notes:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, please capture everything from the design doc in here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed OOB notes. I could not reproduce the oauth/basic mutual incompatibility, I mixed up the already documented override semantics of system/user directories. |
||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "auth", | ||
| "domains": [ | ||
| "bar.com" | ||
| ], | ||
| "type": "oauth", | ||
| "credentials": { | ||
| "token": "someToken" | ||
| } | ||
| }, | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "auth", | ||
| "domains": [ | ||
| "foo.com" | ||
| ], | ||
| "type": "basic", | ||
| "credentials": { | ||
| "user": "user", | ||
| "password": "userPassword" | ||
| } | ||
| }, | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "paths", | ||
| "data": "/var/lib/rkt", | ||
| "stage1-images": "/usr/lib/rkt" | ||
| }, | ||
| { | ||
| "rktVersion": "v1", | ||
| "rktKind": "stage1", | ||
| "name": "coreos.com/rkt/stage1-coreos", | ||
| "version": "0.15.0+git", | ||
| "location": "/usr/libexec/rkt/stage1-coreos.aci" | ||
| } | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| // Copyright 2016 The rkt Authors | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package main | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
|
|
||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| var ( | ||
| cmdConfig = &cobra.Command{ | ||
| Use: "config", | ||
| Short: "Print configuration for each stage in JSON format", | ||
| Long: `The output will be parsable JSON with "stage0" and stage1" as keys and rkt configuration entries as values. | ||
| The generated configuration entries resemble the original rkt configuration format.`, | ||
| Run: runWrapper(runConfig), | ||
| } | ||
| ) | ||
|
|
||
| func init() { | ||
| cmdRkt.AddCommand(cmdConfig) | ||
| } | ||
|
|
||
| func runConfig(cmd *cobra.Command, args []string) int { | ||
| config, err := getConfig() | ||
| if err != nil { | ||
| stderr.PrintE("cannot get configuration", err) | ||
| return 1 | ||
| } | ||
|
|
||
| b, err := json.Marshal(config) | ||
| if err != nil { | ||
| stderr.PanicE("error marshaling configuration", err) | ||
| } | ||
|
|
||
| stdout.Print(string(b)) | ||
| return 0 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ package config | |
|
|
||
| import ( | ||
| "encoding/json" | ||
| "errors" | ||
| "fmt" | ||
| "io/ioutil" | ||
| "net/http" | ||
|
|
@@ -37,8 +38,8 @@ type Headerer interface { | |
| // BasicCredentials holds typical credentials used for authentication | ||
| // (user and password). Used for fetching docker images. | ||
| type BasicCredentials struct { | ||
| User string | ||
| Password string | ||
| User string `json:"user"` | ||
| Password string `json:"password"` | ||
| } | ||
|
|
||
| // ConfigurablePaths holds various paths defined in the configuration. | ||
|
|
@@ -64,6 +65,90 @@ type Config struct { | |
| Stage1 Stage1Data | ||
| } | ||
|
|
||
| // MarshalJSON marshals the config for user output. | ||
| func (c *Config) MarshalJSON() ([]byte, error) { | ||
| stage0 := []interface{}{} | ||
|
|
||
| for host, auth := range c.AuthPerHost { | ||
| var typ string | ||
| var credentials interface{} | ||
|
|
||
| switch h := auth.(type) { | ||
| case *basicAuthHeaderer: | ||
| typ = "basic" | ||
| credentials = h.auth | ||
| case *oAuthBearerTokenHeaderer: | ||
| typ = "oauth" | ||
| credentials = h.auth | ||
| default: | ||
| return nil, errors.New("unknown headerer type") | ||
| } | ||
|
|
||
| auth := struct { | ||
| RktVersion string `json:"rktVersion"` | ||
| RktKind string `json:"rktKind"` | ||
| Domains []string `json:"domains"` | ||
| Type string `json:"type"` | ||
| Credentials interface{} `json:"credentials"` | ||
| }{ | ||
| RktVersion: "v1", | ||
| RktKind: "auth", | ||
| Domains: []string{host}, | ||
| Type: typ, | ||
| Credentials: credentials, | ||
| } | ||
|
|
||
| stage0 = append(stage0, auth) | ||
| } | ||
|
|
||
| for registry, credentials := range c.DockerCredentialsPerRegistry { | ||
| dockerAuth := struct { | ||
| RktVersion string `json:"rktVersion"` | ||
| RktKind string `json:"rktKind"` | ||
| Registries []string `json:"registries"` | ||
| Credentials BasicCredentials `json:"credentials"` | ||
| }{ | ||
| RktVersion: "v1", | ||
| RktKind: "dockerAuth", | ||
| Registries: []string{registry}, | ||
| Credentials: credentials, | ||
| } | ||
|
|
||
| stage0 = append(stage0, dockerAuth) | ||
| } | ||
|
|
||
| paths := struct { | ||
| RktVersion string `json:"rktVersion"` | ||
| RktKind string `json:"rktKind"` | ||
| Data string `json:"data"` | ||
| Stage1Images string `json:"stage1-images"` | ||
| }{ | ||
| RktVersion: "v1", | ||
| RktKind: "paths", | ||
| Data: c.Paths.DataDir, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @krnowak @alban this will print a different path if the user specified There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I'd keep it like that. |
||
| Stage1Images: c.Paths.Stage1ImagesDir, | ||
| } | ||
|
|
||
| stage1 := struct { | ||
| RktVersion string `json:"rktVersion"` | ||
| RktKind string `json:"rktKind"` | ||
| Name string `json:"name"` | ||
| Version string `json:"version"` | ||
| Location string `json:"location"` | ||
| }{ | ||
| RktVersion: "v1", | ||
| RktKind: "stage1", | ||
| Name: c.Stage1.Name, | ||
| Version: c.Stage1.Version, | ||
| Location: c.Stage1.Location, | ||
| } | ||
|
|
||
| stage0 = append(stage0, paths, stage1) | ||
|
|
||
| data := map[string]interface{}{"stage0": stage0} | ||
| return json.Marshal(data) | ||
| } | ||
|
|
||
| type configParser interface { | ||
| parse(config *Config, raw []byte) error | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Paging @joshix for doc review.