mirror of
https://github.com/rancher/os.git
synced 2025-07-01 09:11:48 +00:00
Merge pull request #1147 from joshwget/write-files-enhancements
Extend write_files to run in all system services
This commit is contained in:
commit
64711f9e66
@ -12,8 +12,10 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/coreos/coreos-cloudinit/system"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/rancher/os/config"
|
||||
rancherConfig "github.com/rancher/os/config"
|
||||
"github.com/rancher/os/docker"
|
||||
"github.com/rancher/os/util"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -38,7 +40,7 @@ func Main() {
|
||||
|
||||
log.Infof("Running cloud-init-execute: pre-console=%v, console=%v", preConsole, console)
|
||||
|
||||
cfg := config.LoadConfig()
|
||||
cfg := rancherConfig.LoadConfig()
|
||||
|
||||
if !console && !preConsole {
|
||||
console = true
|
||||
@ -53,21 +55,13 @@ func Main() {
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyConsole(cfg *config.CloudConfig) {
|
||||
func ApplyConsole(cfg *rancherConfig.CloudConfig) {
|
||||
if len(cfg.SSHAuthorizedKeys) > 0 {
|
||||
authorizeSSHKeys("rancher", cfg.SSHAuthorizedKeys, sshKeyName)
|
||||
authorizeSSHKeys("docker", cfg.SSHAuthorizedKeys, sshKeyName)
|
||||
}
|
||||
|
||||
for _, file := range cfg.WriteFiles {
|
||||
f := system.File{File: file}
|
||||
fullPath, err := system.WriteFile(&f, "/")
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err, "path": fullPath}).Error("Error writing file")
|
||||
continue
|
||||
}
|
||||
log.Printf("Wrote file %s to filesystem", fullPath)
|
||||
}
|
||||
WriteFiles(cfg, "console")
|
||||
|
||||
for _, configMount := range cfg.Mounts {
|
||||
if len(configMount) != 4 {
|
||||
@ -88,7 +82,29 @@ func ApplyConsole(cfg *config.CloudConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
func applyPreConsole(cfg *config.CloudConfig) {
|
||||
func WriteFiles(cfg *rancherConfig.CloudConfig, container string) {
|
||||
for _, file := range cfg.WriteFiles {
|
||||
fileContainer := file.Container
|
||||
if fileContainer == "" {
|
||||
fileContainer = "console"
|
||||
}
|
||||
if fileContainer != container {
|
||||
continue
|
||||
}
|
||||
|
||||
f := system.File{
|
||||
File: file.File,
|
||||
}
|
||||
fullPath, err := system.WriteFile(&f, "/")
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"err": err, "path": fullPath}).Error("Error writing file")
|
||||
continue
|
||||
}
|
||||
log.Printf("Wrote file %s to filesystem", fullPath)
|
||||
}
|
||||
}
|
||||
|
||||
func applyPreConsole(cfg *rancherConfig.CloudConfig) {
|
||||
if _, err := os.Stat(resizeStamp); os.IsNotExist(err) && cfg.Rancher.ResizeDevice != "" {
|
||||
if err := resizeDevice(cfg); err == nil {
|
||||
os.Create(resizeStamp)
|
||||
@ -105,9 +121,20 @@ func applyPreConsole(cfg *config.CloudConfig) {
|
||||
log.Errorf("Failed to set sysctl key %s: %s", k, err)
|
||||
}
|
||||
}
|
||||
|
||||
client, err := docker.NewSystemClient()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
for _, restart := range cfg.Rancher.RestartServices {
|
||||
if err = client.ContainerRestart(context.Background(), restart, 10); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func resizeDevice(cfg *config.CloudConfig) error {
|
||||
func resizeDevice(cfg *rancherConfig.CloudConfig) error {
|
||||
cmd := exec.Command("growpart", cfg.Rancher.ResizeDevice, "1")
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
|
@ -70,9 +70,6 @@ func Main() {
|
||||
|
||||
func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadata) error {
|
||||
os.MkdirAll(rancherConfig.CloudConfigDir, os.ModeDir|0600)
|
||||
os.Remove(rancherConfig.CloudConfigScriptFile)
|
||||
os.Remove(rancherConfig.CloudConfigBootFile)
|
||||
os.Remove(rancherConfig.MetaDataFile)
|
||||
|
||||
if len(scriptBytes) > 0 {
|
||||
log.Infof("Writing to %s", rancherConfig.CloudConfigScriptFile)
|
||||
@ -82,10 +79,12 @@ func saveFiles(cloudConfigBytes, scriptBytes []byte, metadata datasource.Metadat
|
||||
}
|
||||
}
|
||||
|
||||
if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
|
||||
return err
|
||||
if len(cloudConfigBytes) > 0 {
|
||||
if err := util.WriteFileAtomic(rancherConfig.CloudConfigBootFile, cloudConfigBytes, 400); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
|
||||
}
|
||||
log.Infof("Written to %s:\n%s", rancherConfig.CloudConfigBootFile, string(cloudConfigBytes))
|
||||
|
||||
metaDataBytes, err := yaml.Marshal(metadata)
|
||||
if err != nil {
|
||||
|
@ -45,6 +45,12 @@ func Main() {
|
||||
SkipFlagParsing: true,
|
||||
Action: devAction,
|
||||
},
|
||||
{
|
||||
Name: "entrypoint",
|
||||
HideHelp: true,
|
||||
SkipFlagParsing: true,
|
||||
Action: entrypointAction,
|
||||
},
|
||||
{
|
||||
Name: "env",
|
||||
ShortName: "e",
|
||||
|
74
cmd/control/entrypoint.go
Normal file
74
cmd/control/entrypoint.go
Normal file
@ -0,0 +1,74 @@
|
||||
package control
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/codegangsta/cli"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/rancher/os/cmd/cloudinitexecute"
|
||||
"github.com/rancher/os/config"
|
||||
"github.com/rancher/os/docker"
|
||||
"github.com/rancher/os/util"
|
||||
)
|
||||
|
||||
const (
|
||||
ca = "/etc/ssl/certs/ca-certificates.crt"
|
||||
caBase = "/etc/ssl/certs/ca-certificates.crt.rancher"
|
||||
)
|
||||
|
||||
func entrypointAction(c *cli.Context) error {
|
||||
if err := mount.Mount("/host/dev", "/dev", "", "rbind"); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
if err := util.FileCopy(caBase, ca); err != nil && !os.IsNotExist(err) {
|
||||
log.Error(err)
|
||||
}
|
||||
|
||||
cfg := config.LoadConfig()
|
||||
|
||||
shouldWriteFiles := false
|
||||
for _, file := range cfg.WriteFiles {
|
||||
if file.Container != "" {
|
||||
shouldWriteFiles = true
|
||||
}
|
||||
}
|
||||
|
||||
if shouldWriteFiles {
|
||||
writeFiles(cfg)
|
||||
}
|
||||
|
||||
if len(os.Args) < 3 {
|
||||
return nil
|
||||
}
|
||||
|
||||
binary, err := exec.LookPath(os.Args[2])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return syscall.Exec(binary, os.Args[2:], os.Environ())
|
||||
}
|
||||
|
||||
func writeFiles(cfg *config.CloudConfig) error {
|
||||
id, err := util.GetCurrentContainerId()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := docker.NewSystemClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := client.ContainerInspect(context.Background(), id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cloudinitexecute.WriteFiles(cfg, info.Name[1:])
|
||||
return nil
|
||||
}
|
@ -85,12 +85,17 @@ type Repositories map[string]Repository
|
||||
|
||||
type CloudConfig struct {
|
||||
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"`
|
||||
WriteFiles []config.File `yaml:"write_files"`
|
||||
WriteFiles []File `yaml:"write_files"`
|
||||
Hostname string `yaml:"hostname"`
|
||||
Mounts [][]string `yaml:"mounts,omitempty"`
|
||||
Rancher RancherConfig `yaml:"rancher,omitempty"`
|
||||
}
|
||||
|
||||
type File struct {
|
||||
config.File
|
||||
Container string `yaml:"container,omitempty"`
|
||||
}
|
||||
|
||||
type RancherConfig struct {
|
||||
Console string `yaml:"console,omitempty"`
|
||||
Environment map[string]string `yaml:"environment,omitempty"`
|
||||
@ -119,6 +124,7 @@ type RancherConfig struct {
|
||||
Defaults Defaults `yaml:"defaults,omitempty"`
|
||||
ResizeDevice string `yaml:"resize_device,omitempty"`
|
||||
Sysctl map[string]string `yaml:"sysctl,omitempty"`
|
||||
RestartServices []string `yaml:"restart_services,omitempty"`
|
||||
}
|
||||
|
||||
type UpgradeConfig struct {
|
||||
|
@ -32,8 +32,7 @@ RUN rm /sbin/poweroff /sbin/reboot /sbin/halt && \
|
||||
adduser docker sudo && \
|
||||
echo '%sudo ALL=(ALL) ALL' >> /etc/sudoers
|
||||
COPY inputrc /etc/inputrc
|
||||
COPY entry.sh /usr/sbin/entry.sh
|
||||
COPY growpart /usr/bin/growpart
|
||||
RUN sed -i -e 's/duid/clientid/g' /etc/dhcpcd.conf
|
||||
|
||||
ENTRYPOINT ["/usr/sbin/entry.sh"]
|
||||
ENTRYPOINT ["/usr/bin/ros", "entrypoint"]
|
||||
|
@ -250,6 +250,9 @@ rancher:
|
||||
uts: host
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
preload-system-images:
|
||||
image: {{.OS_REPO}}/os-preload:{{.VERSION}}{{.SUFFIX}}
|
||||
labels:
|
||||
@ -289,6 +292,7 @@ rancher:
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
system-volumes:
|
||||
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
||||
@ -325,9 +329,8 @@ rancher:
|
||||
uts: host
|
||||
privileged: true
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
volumes:
|
||||
- /usr/bin/ros:/usr/bin/ros:ro
|
||||
udev:
|
||||
image: {{.OS_REPO}}/os-udev:{{.VERSION}}{{.SUFFIX}}
|
||||
environment:
|
||||
@ -340,6 +343,7 @@ rancher:
|
||||
privileged: true
|
||||
restart: always
|
||||
volumes_from:
|
||||
- command-volumes
|
||||
- system-volumes
|
||||
user-volumes:
|
||||
image: {{.OS_REPO}}/os-base:{{.VERSION}}{{.SUFFIX}}
|
||||
|
@ -15,19 +15,19 @@ INITRD=${ARTIFACTS}/initrd
|
||||
|
||||
mkdir -p ${ARTIFACTS} ${PREPOP_DIR}
|
||||
|
||||
if [ "$(docker info | grep 'Storage Driver: ' | sed 's/Storage Driver: //')" != "overlay" ]; then
|
||||
echo Overlay storage driver is require to prepackage exploded images
|
||||
echo packaging images.tar instead
|
||||
tar czf ${ARTIFACTS}/rootfs.tar.gz --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
||||
exit 0
|
||||
fi
|
||||
#if [ "$(docker info | grep 'Storage Driver: ' | sed 's/Storage Driver: //')" != "overlay" ]; then
|
||||
echo Overlay storage driver is require to prepackage exploded images
|
||||
echo packaging images.tar instead
|
||||
tar czf ${ARTIFACTS}/rootfs.tar.gz --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
||||
exit 0
|
||||
#fi
|
||||
|
||||
DFS=$(docker run -d --privileged -v /lib/modules/$(uname -r):/lib/modules/$(uname -r) ${DFS_IMAGE}${SUFFIX} ${DFS_ARGS})
|
||||
trap "docker rm -fv ${DFS_ARCH} ${DFS}" EXIT
|
||||
docker exec -i ${DFS} docker load < ${INITRD_DIR}/usr/share/ros/images.tar
|
||||
docker stop ${DFS}
|
||||
docker run --rm --volumes-from=${DFS} rancher/os-base tar -c -C /var/lib/docker ./image | tar -x -C ${PREPOP_DIR}
|
||||
docker run --rm --volumes-from=${DFS} rancher/os-base tar -c -C /var/lib/docker ./overlay | tar -x -C ${PREPOP_DIR}
|
||||
docker run --rm --volumes-from=${DFS} busybox tar -c -C /var/lib/docker ./image | tar -x -C ${PREPOP_DIR}
|
||||
docker run --rm --volumes-from=${DFS} busybox tar -c -C /var/lib/docker ./overlay | tar -x -C ${PREPOP_DIR}
|
||||
|
||||
tar -cf ${ARTIFACTS}/rootfs.tar --exclude usr/share/ros/images.tar --exclude lib/modules --exclude lib/firmware -C ${INITRD_DIR} .
|
||||
tar -rf ${ARTIFACTS}/rootfs.tar -C ${IMAGE_CACHE} .
|
||||
|
29
tests/assets/test_23/cloud-config.yml
Normal file
29
tests/assets/test_23/cloud-config.yml
Normal file
@ -0,0 +1,29 @@
|
||||
#cloud-config
|
||||
write_files:
|
||||
- path: "/test"
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
console content
|
||||
- path: "/test2"
|
||||
container: console
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
console content
|
||||
- path: "/test"
|
||||
container: ntp
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
ntp content
|
||||
- path: "/test"
|
||||
container: syslog
|
||||
permissions: "0644"
|
||||
owner: "root"
|
||||
content: |
|
||||
syslog content
|
||||
rancher:
|
||||
restart_services: [syslog]
|
||||
ssh_authorized_keys:
|
||||
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC85w9stZyiLQp/DkVO6fqwiShYcj1ClKdtCqgHtf+PLpJkFReSFu8y21y+ev09gsSMRRrjF7yt0pUHV6zncQhVeqsZtgc5WbELY2DOYUGmRn/CCvPbXovoBrQjSorqlBmpuPwsStYLr92Xn+VVsMNSUIegHY22DphGbDKG85vrKB8HxUxGIDxFBds/uE8FhSy+xsoyT/jUZDK6pgq2HnGl6D81ViIlKecpOpWlW3B+fea99ADNyZNVvDzbHE5pcI3VRw8u59WmpWOUgT6qacNVACl8GqpBvQk8sw7O/X9DSZHCKafeD9G5k+GYbAUz92fKWrx/lOXfUXPS3+c8dRIF
|
@ -7,6 +7,6 @@ func (s *QemuSuite) TestKernelHeaders(c *C) {
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.CheckCall(c, `
|
||||
sleep 10
|
||||
sleep 15
|
||||
docker inspect kernel-headers`)
|
||||
}
|
||||
|
13
tests/write_files_test.go
Normal file
13
tests/write_files_test.go
Normal file
@ -0,0 +1,13 @@
|
||||
package integration
|
||||
|
||||
import . "gopkg.in/check.v1"
|
||||
|
||||
func (s *QemuSuite) TestWriteFiles(c *C) {
|
||||
err := s.RunQemu("--cloud-config", "./tests/assets/test_23/cloud-config.yml")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
s.CheckCall(c, "sudo cat /test | grep 'console content'")
|
||||
s.CheckCall(c, "sudo cat /test2 | grep 'console content'")
|
||||
s.CheckCall(c, "sudo system-docker exec ntp cat /test | grep 'ntp content'")
|
||||
s.CheckCall(c, "sudo system-docker exec syslog cat /test | grep 'syslog content'")
|
||||
}
|
@ -4,7 +4,7 @@ github.com/Sirupsen/logrus v0.9.0
|
||||
github.com/boltdb/bolt v1.2.0
|
||||
github.com/cloudfoundry-incubator/candiedyaml 01cbc92901719f599b11f3a7e3b1768d7002b0bb https://github.com/rancher/candiedyaml
|
||||
github.com/cloudfoundry/gosigar 3ed7c74352dae6dc00bdc8c74045375352e3ec05
|
||||
github.com/codegangsta/cli 95199f812193f6f1e8bbe0a916d9f3ed50729909 https://github.com/ibuildthecloud/cli-1.git
|
||||
github.com/codegangsta/cli d2b9ba9c38eb353ba3c6df3f57072348e19cc5c7 https://github.com/rancher/cli-1
|
||||
github.com/containernetworking/cni a8e4fa0dffdac6a236f85be91502603ec06957f9 https://github.com/rancher/cni.git
|
||||
github.com/coreos/coreos-cloudinit v1.11.0-3-gb1c1753 https://github.com/rancher/coreos-cloudinit.git
|
||||
github.com/coreos/go-iptables fbb73372b87f6e89951c2b6b31470c2c9d5cfae3
|
||||
|
1
vendor/github.com/codegangsta/cli/.gitignore
generated
vendored
1
vendor/github.com/codegangsta/cli/.gitignore
generated
vendored
@ -1 +1,2 @@
|
||||
*.coverprofile
|
||||
node_modules/
|
||||
|
8
vendor/github.com/codegangsta/cli/.travis.yml
generated
vendored
8
vendor/github.com/codegangsta/cli/.travis.yml
generated
vendored
@ -2,6 +2,10 @@ language: go
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
|
||||
go:
|
||||
- 1.2.2
|
||||
- 1.3.3
|
||||
@ -25,8 +29,12 @@ matrix:
|
||||
|
||||
before_script:
|
||||
- go get github.com/urfave/gfmxr/...
|
||||
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
||||
npm install markdown-toc ;
|
||||
fi
|
||||
|
||||
script:
|
||||
- ./runtests vet
|
||||
- ./runtests test
|
||||
- ./runtests gfmxr
|
||||
- ./runtests toc
|
||||
|
14
vendor/github.com/codegangsta/cli/CHANGELOG.md
generated
vendored
14
vendor/github.com/codegangsta/cli/CHANGELOG.md
generated
vendored
@ -3,13 +3,24 @@
|
||||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.18.0] - 2016-06-27
|
||||
### Added
|
||||
- `./runtests` test runner with coverage tracking by default
|
||||
- testing on OS X
|
||||
- testing on Windows
|
||||
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
|
||||
|
||||
### Changed
|
||||
- Use spaces for alignment in help/usage output instead of tabs, making the
|
||||
output alignment consistent regardless of tab width
|
||||
|
||||
### Fixed
|
||||
- Printing of command aliases in help text
|
||||
- Printing of visible flags for both struct and struct pointer flags
|
||||
- Display the `help` subcommand when using `CommandCategories`
|
||||
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
||||
detecting the signature of the `Action` field
|
||||
|
||||
## [1.17.0] - 2016-05-09
|
||||
### Added
|
||||
@ -290,7 +301,8 @@ signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
||||
### Added
|
||||
- Initial implementation.
|
||||
|
||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.17.0...HEAD
|
||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
|
||||
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
|
||||
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
|
||||
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
||||
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
|
||||
|
28
vendor/github.com/codegangsta/cli/LICENSE
generated
vendored
28
vendor/github.com/codegangsta/cli/LICENSE
generated
vendored
@ -1,21 +1,21 @@
|
||||
Copyright (C) 2013 Jeremy Saenz
|
||||
All Rights Reserved.
|
||||
MIT License
|
||||
|
||||
MIT LICENSE
|
||||
Copyright (c) 2016 Jeremy Saenz & Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
1028
vendor/github.com/codegangsta/cli/README.md
generated
vendored
1028
vendor/github.com/codegangsta/cli/README.md
generated
vendored
File diff suppressed because it is too large
Load Diff
27
vendor/github.com/codegangsta/cli/app.go
generated
vendored
27
vendor/github.com/codegangsta/cli/app.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -139,13 +140,6 @@ func (a *App) Setup() {
|
||||
}
|
||||
a.Commands = newCmds
|
||||
|
||||
a.categories = CommandCategories{}
|
||||
for _, command := range a.Commands {
|
||||
a.categories = a.categories.AddCommand(command.Category, command)
|
||||
}
|
||||
sort.Sort(a.categories)
|
||||
|
||||
// append help to commands
|
||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
||||
a.Commands = append(a.Commands, helpCommand)
|
||||
if (HelpFlag != BoolFlag{}) {
|
||||
@ -153,7 +147,6 @@ func (a *App) Setup() {
|
||||
}
|
||||
}
|
||||
|
||||
//append version/help flags
|
||||
if a.EnableBashCompletion {
|
||||
a.appendFlag(BashCompletionFlag)
|
||||
}
|
||||
@ -161,6 +154,12 @@ func (a *App) Setup() {
|
||||
if !a.HideVersion {
|
||||
a.appendFlag(VersionFlag)
|
||||
}
|
||||
|
||||
a.categories = CommandCategories{}
|
||||
for _, command := range a.Commands {
|
||||
a.categories = a.categories.AddCommand(command.Category, command)
|
||||
}
|
||||
sort.Sort(a.categories)
|
||||
}
|
||||
|
||||
// Run is the entry point to the cli app. Parses the arguments slice and routes
|
||||
@ -461,11 +460,13 @@ func (a Author) String() string {
|
||||
func HandleAction(action interface{}, context *Context) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
switch r.(type) {
|
||||
case error:
|
||||
err = r.(error)
|
||||
default:
|
||||
err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
|
||||
// Try to detect a known reflection error from *this scope*, rather than
|
||||
// swallowing all panics that may happen when calling an Action func.
|
||||
s := fmt.Sprintf("%v", r)
|
||||
if strings.HasPrefix(s, "reflect: ") && strings.Contains(s, "too many input arguments") {
|
||||
err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2)
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
105
vendor/github.com/codegangsta/cli/context.go
generated
vendored
105
vendor/github.com/codegangsta/cli/context.go
generated
vendored
@ -31,6 +31,21 @@ func (c *Context) Int(name string) int {
|
||||
return lookupInt(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Int64 looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Int64(name string) int64 {
|
||||
return lookupInt64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Uint looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Uint(name string) uint {
|
||||
return lookupUint(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists
|
||||
func (c *Context) Uint64(name string) uint64 {
|
||||
return lookupUint64(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Duration looks up the value of a local time.Duration flag, returns 0 if no
|
||||
// time.Duration flag exists
|
||||
func (c *Context) Duration(name string) time.Duration {
|
||||
@ -70,6 +85,12 @@ func (c *Context) IntSlice(name string) []int {
|
||||
return lookupIntSlice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Int64Slice looks up the value of a local int slice flag, returns nil if no int
|
||||
// slice flag exists
|
||||
func (c *Context) Int64Slice(name string) []int64 {
|
||||
return lookupInt64Slice(name, c.flagSet)
|
||||
}
|
||||
|
||||
// Generic looks up the value of a local generic flag, returns nil if no generic
|
||||
// flag exists
|
||||
func (c *Context) Generic(name string) interface{} {
|
||||
@ -84,6 +105,30 @@ func (c *Context) GlobalInt(name string) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalInt64 looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalInt64(name string) int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalUint(name string) uint {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists
|
||||
func (c *Context) GlobalUint64(name string) uint64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupUint64(name, fs)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0)
|
||||
// if no float64 flag exists
|
||||
func (c *Context) GlobalFloat64(name string) float64 {
|
||||
@ -147,6 +192,15 @@ func (c *Context) GlobalIntSlice(name string) []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GlobalInt64Slice looks up the value of a global int slice flag, returns nil if
|
||||
// no int slice flag exists
|
||||
func (c *Context) GlobalInt64Slice(name string) []int64 {
|
||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
||||
return lookupInt64Slice(name, fs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GlobalGeneric looks up the value of a global generic flag, returns nil if no
|
||||
// generic flag exists
|
||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
||||
@ -306,7 +360,46 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
||||
func lookupInt(name string, set *flag.FlagSet) int {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.Atoi(f.Value.String())
|
||||
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(val)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupInt64(name string, set *flag.FlagSet) int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint(name string, set *flag.FlagSet) uint {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint(val)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func lookupUint64(name string, set *flag.FlagSet) uint64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
val, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
@ -370,6 +463,16 @@ func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
return (f.Value.(*Int64Slice)).Value()
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
||||
f := set.Lookup(name)
|
||||
if f != nil {
|
||||
|
233
vendor/github.com/codegangsta/cli/flag.go
generated
vendored
233
vendor/github.com/codegangsta/cli/flag.go
generated
vendored
@ -189,7 +189,7 @@ func (f *IntSlice) Set(value string) error {
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *IntSlice) String() string {
|
||||
return fmt.Sprintf("%d", *f)
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
@ -245,6 +245,77 @@ func (f IntSliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Int64Slice is an opaque type for []int to satisfy flag.Value
|
||||
type Int64Slice []int64
|
||||
|
||||
// Set parses the value into an integer and appends it to the list of values
|
||||
func (f *Int64Slice) Set(value string) error {
|
||||
tmp, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*f = append(*f, tmp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String returns a readable representation of this value (for usage defaults)
|
||||
func (f *Int64Slice) String() string {
|
||||
return fmt.Sprintf("%#v", *f)
|
||||
}
|
||||
|
||||
// Value returns the slice of ints set by this flag
|
||||
func (f *Int64Slice) Value() []int64 {
|
||||
return *f
|
||||
}
|
||||
|
||||
// Int64SliceFlag is an int flag that can be specified multiple times on the
|
||||
// command-line
|
||||
type Int64SliceFlag struct {
|
||||
Name string
|
||||
Value *Int64Slice
|
||||
Usage string
|
||||
EnvVar string
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Int64SliceFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
newVal := &Int64Slice{}
|
||||
for _, s := range strings.Split(envVal, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
err := newVal.Set(s)
|
||||
if err != nil {
|
||||
fmt.Fprintf(ErrWriter, err.Error())
|
||||
}
|
||||
}
|
||||
f.Value = newVal
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Value == nil {
|
||||
f.Value = &Int64Slice{}
|
||||
}
|
||||
set.Var(f.Value, name, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Int64SliceFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// BoolFlag is a switch that defaults to false
|
||||
type BoolFlag struct {
|
||||
Name string
|
||||
@ -376,7 +447,6 @@ func (f StringFlag) GetName() string {
|
||||
}
|
||||
|
||||
// IntFlag is a flag that takes an integer
|
||||
// Errors if the value provided cannot be parsed
|
||||
type IntFlag struct {
|
||||
Name string
|
||||
Value int
|
||||
@ -420,6 +490,138 @@ func (f IntFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Int64Flag is a flag that takes a 64-bit integer
|
||||
type Int64Flag struct {
|
||||
Name string
|
||||
Value int64
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *int64
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Int64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = envValInt
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Int64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Int64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Int64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// UintFlag is a flag that takes an unsigned integer
|
||||
type UintFlag struct {
|
||||
Name string
|
||||
Value uint
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *uint
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f UintFlag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f UintFlag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = uint(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.UintVar(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f UintFlag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// Uint64Flag is a flag that takes an unsigned 64-bit integer
|
||||
type Uint64Flag struct {
|
||||
Name string
|
||||
Value uint64
|
||||
Usage string
|
||||
EnvVar string
|
||||
Destination *uint64
|
||||
Hidden bool
|
||||
}
|
||||
|
||||
// String returns the usage
|
||||
func (f Uint64Flag) String() string {
|
||||
return FlagStringer(f)
|
||||
}
|
||||
|
||||
// Apply populates the flag given the flag set and environment
|
||||
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
||||
if f.EnvVar != "" {
|
||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
||||
envVar = strings.TrimSpace(envVar)
|
||||
if envVal := os.Getenv(envVar); envVal != "" {
|
||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
||||
if err == nil {
|
||||
f.Value = uint64(envValInt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eachName(f.Name, func(name string) {
|
||||
if f.Destination != nil {
|
||||
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
|
||||
return
|
||||
}
|
||||
set.Uint64(name, f.Value, f.Usage)
|
||||
})
|
||||
}
|
||||
|
||||
// GetName returns the name of the flag.
|
||||
func (f Uint64Flag) GetName() string {
|
||||
return f.Name
|
||||
}
|
||||
|
||||
// DurationFlag is a flag that takes a duration specified in Go's duration
|
||||
// format: https://golang.org/pkg/time/#ParseDuration
|
||||
type DurationFlag struct {
|
||||
@ -466,7 +668,6 @@ func (f DurationFlag) GetName() string {
|
||||
}
|
||||
|
||||
// Float64Flag is a flag that takes an float value
|
||||
// Errors if the value provided cannot be parsed
|
||||
type Float64Flag struct {
|
||||
Name string
|
||||
Value float64
|
||||
@ -512,7 +713,7 @@ func (f Float64Flag) GetName() string {
|
||||
func visibleFlags(fl []Flag) []Flag {
|
||||
visible := []Flag{}
|
||||
for _, flag := range fl {
|
||||
if !reflect.ValueOf(flag).FieldByName("Hidden").Bool() {
|
||||
if !flagValue(flag).FieldByName("Hidden").Bool() {
|
||||
visible = append(visible, flag)
|
||||
}
|
||||
}
|
||||
@ -578,13 +779,24 @@ func withEnvHint(envVar, str string) string {
|
||||
return str + envText
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
func flagValue(f Flag) reflect.Value {
|
||||
fv := reflect.ValueOf(f)
|
||||
for fv.Kind() == reflect.Ptr {
|
||||
fv = reflect.Indirect(fv)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
func stringifyFlag(f Flag) string {
|
||||
fv := flagValue(f)
|
||||
|
||||
switch f.(type) {
|
||||
case IntSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
||||
case Int64SliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
||||
case StringSliceFlag:
|
||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
||||
@ -630,6 +842,17 @@ func stringifyIntSliceFlag(f IntSliceFlag) string {
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
for _, i := range f.Value.Value() {
|
||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
|
||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
||||
}
|
||||
|
||||
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
||||
defaultVals := []string{}
|
||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
||||
|
5
vendor/github.com/codegangsta/cli/help.go
generated
vendored
5
vendor/github.com/codegangsta/cli/help.go
generated
vendored
@ -117,8 +117,9 @@ var HelpPrinter helpPrinter = printHelp
|
||||
var VersionPrinter = printVersion
|
||||
|
||||
// ShowAppHelp is an action that displays the help.
|
||||
func ShowAppHelp(c *Context) {
|
||||
func ShowAppHelp(c *Context) error {
|
||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
||||
@ -191,7 +192,7 @@ func printHelp(out io.Writer, templ string, data interface{}) {
|
||||
"join": strings.Join,
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
|
||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
||||
err := t.Execute(w, data)
|
||||
if err != nil {
|
||||
|
8
vendor/github.com/codegangsta/cli/runtests
generated
vendored
8
vendor/github.com/codegangsta/cli/runtests
generated
vendored
@ -18,7 +18,8 @@ def main(sysargs=sys.argv[:]):
|
||||
targets = {
|
||||
'vet': _vet,
|
||||
'test': _test,
|
||||
'gfmxr': _gfmxr
|
||||
'gfmxr': _gfmxr,
|
||||
'toc': _toc,
|
||||
}
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
@ -62,6 +63,11 @@ def _vet():
|
||||
_run('go vet ./...'.split())
|
||||
|
||||
|
||||
def _toc():
|
||||
_run(['node_modules/.bin/markdown-toc', '-i', 'README.md'])
|
||||
_run(['git', 'diff', '--quiet'])
|
||||
|
||||
|
||||
def _run(command):
|
||||
print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
|
||||
check_call(command)
|
||||
|
Loading…
Reference in New Issue
Block a user