Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
inclavare-containers
提交
33a410ee
I
inclavare-containers
项目概览
openanolis
/
inclavare-containers
通知
5
Star
7
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
5
列表
看板
标记
里程碑
合并请求
0
分析
仓库
DevOps
项目成员
Pages
I
inclavare-containers
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
5
Issue
5
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
33a410ee
编写于
6月 09, 2020
作者:
J
jiazhiguang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
execute sgx_sign in the occlum container
上级
ea9daf44
变更
36
展开全部
显示空白变更内容
内联
并排
Showing
36 changed file
with
6407 addition
and
192 deletion
+6407
-192
shim/README.md
shim/README.md
+1
-1
shim/go.sum
shim/go.sum
+1
-0
shim/runtime/carrier/constants/constants.go
shim/runtime/carrier/constants/constants.go
+166
-41
shim/runtime/carrier/occlum/occlum.go
shim/runtime/carrier/occlum/occlum.go
+201
-126
shim/runtime/utils/utils.go
shim/runtime/utils/utils.go
+58
-0
shim/runtime/v2/rune/v2/rune.go
shim/runtime/v2/rune/v2/rune.go
+7
-10
shim/runtime/v2/rune/v2/service.go
shim/runtime/v2/rune/v2/service.go
+0
-14
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/client.go
...thub.com/containerd/containerd/cmd/ctr/commands/client.go
+58
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
...ub.com/containerd/containerd/cmd/ctr/commands/commands.go
+197
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
...m/containerd/containerd/cmd/ctr/commands/commands_unix.go
+33
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go
...ontainerd/containerd/cmd/ctr/commands/commands_windows.go
+30
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
...ub.com/containerd/containerd/cmd/ctr/commands/resolver.go
+110
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/signals.go
...hub.com/containerd/containerd/cmd/ctr/commands/signals.go
+52
-0
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/utils.go
...ithub.com/containerd/containerd/cmd/ctr/commands/utils.go
+27
-0
shim/vendor/github.com/containerd/go-runc/monitor.go
shim/vendor/github.com/containerd/go-runc/monitor.go
+3
-0
shim/vendor/github.com/urfave/cli/.flake8
shim/vendor/github.com/urfave/cli/.flake8
+2
-0
shim/vendor/github.com/urfave/cli/.gitignore
shim/vendor/github.com/urfave/cli/.gitignore
+2
-0
shim/vendor/github.com/urfave/cli/.travis.yml
shim/vendor/github.com/urfave/cli/.travis.yml
+27
-0
shim/vendor/github.com/urfave/cli/CHANGELOG.md
shim/vendor/github.com/urfave/cli/CHANGELOG.md
+435
-0
shim/vendor/github.com/urfave/cli/LICENSE
shim/vendor/github.com/urfave/cli/LICENSE
+21
-0
shim/vendor/github.com/urfave/cli/README.md
shim/vendor/github.com/urfave/cli/README.md
+1391
-0
shim/vendor/github.com/urfave/cli/app.go
shim/vendor/github.com/urfave/cli/app.go
+509
-0
shim/vendor/github.com/urfave/cli/appveyor.yml
shim/vendor/github.com/urfave/cli/appveyor.yml
+26
-0
shim/vendor/github.com/urfave/cli/category.go
shim/vendor/github.com/urfave/cli/category.go
+44
-0
shim/vendor/github.com/urfave/cli/cli.go
shim/vendor/github.com/urfave/cli/cli.go
+22
-0
shim/vendor/github.com/urfave/cli/command.go
shim/vendor/github.com/urfave/cli/command.go
+304
-0
shim/vendor/github.com/urfave/cli/context.go
shim/vendor/github.com/urfave/cli/context.go
+278
-0
shim/vendor/github.com/urfave/cli/errors.go
shim/vendor/github.com/urfave/cli/errors.go
+115
-0
shim/vendor/github.com/urfave/cli/flag-types.json
shim/vendor/github.com/urfave/cli/flag-types.json
+93
-0
shim/vendor/github.com/urfave/cli/flag.go
shim/vendor/github.com/urfave/cli/flag.go
+807
-0
shim/vendor/github.com/urfave/cli/flag_generated.go
shim/vendor/github.com/urfave/cli/flag_generated.go
+627
-0
shim/vendor/github.com/urfave/cli/funcs.go
shim/vendor/github.com/urfave/cli/funcs.go
+41
-0
shim/vendor/github.com/urfave/cli/generate-flag-types
shim/vendor/github.com/urfave/cli/generate-flag-types
+255
-0
shim/vendor/github.com/urfave/cli/help.go
shim/vendor/github.com/urfave/cli/help.go
+339
-0
shim/vendor/github.com/urfave/cli/runtests
shim/vendor/github.com/urfave/cli/runtests
+122
-0
shim/vendor/modules.txt
shim/vendor/modules.txt
+3
-0
未找到文件。
shim/README.md
浏览文件 @
33a410ee
...
...
@@ -16,7 +16,7 @@ Carrier is a abstract framework to build an enclave for the specified enclave ru
## Build requirements
Go 1.1
4
.x or above.
Go 1.1
3
.x or above.
## How to build and install
...
...
shim/go.sum
浏览文件 @
33a410ee
...
...
@@ -238,6 +238,7 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5 h1:MCfT24H3f//U5+UCrZp1/riVO3B50BovxtDiNn0XKkk=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
...
...
shim/runtime/carrier/constants/constants.go
浏览文件 @
33a410ee
...
...
@@ -89,45 +89,170 @@ function start() {
start $@`
//FIXME
BuildOcclumEnclaveScript
=
`#!/bin/bash
set -xe
data_dir=/data
rootfs=/rootfs
work_dir=%s
entry_point=%s
occlum_config_path=${rootfs}/%s
occlum_workspace=${data_dir}/../occlum_workspace
CarrierScript
=
`#!/bin/bash
set -xe
base_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
occlum_workspace=/occlum_workspace
temp=$(getopt -a -o a:r:w:p:c:e:u:m:s:k:n: -l action:,rootfs:,work_dir:,entry_point:,occlum_config_path:,enclave_config_path:,\
unsigned_encalve_path:,unsigned_material_path:,signed_enclave_path:,public_key_path:,signature_path: -- "$@")
eval set -- "$temp"
while true
do
case "$1" in
-a|--action)
action=$2; shift;;
-r|--rootfs)
rootfs=$2; shift;;
-w|--work_dir)
work_dir=$2; shift;;
-p|--entry_point)
entry_point=$2; shift;;
-c|--occlum_config_path)
occlum_config_path=$2; shift;;
-e|--enclave_config_path)
enclave_config_path=$2; shift;;
-u|--unsigned_encalve_path)
unsigned_encalve_path=$2; shift;;
-m|--unsigned_material_path)
unsigned_material_path=$2; shift;;
-s|--signed_enclave_path)
signed_enclave_path=$2; shift;;
-k|--public_key_path)
public_key_path=$2; shift;;
-n|--signature_path)
signature_path=$2; shift;;
--)
shift
break
;;
*)
echo "Unknown argument: $1"; shift;;
esac
shift
done
function copyOcclumLiberaries() {
pushd ${rootfs}/${work_dir}
local lib_dir=${rootfs}/lib
/bin/cp -f /usr/lib/x86_64-linux-gnu/libprotobuf.so ${lib_dir}
/bin/cp -f /lib/x86_64-linux-gnu/libseccomp.so.2 ${lib_dir}
/bin/cp -f /usr/lib/libsgx_u*.so* ${lib_dir}
/bin/cp -f /usr/lib/libsgx_enclave_common.so.1 ${lib_dir}
/bin/cp -f /usr/lib/libsgx_launch.so.1 ${lib_dir}
ln -sfn .occlum/build/lib/libocclum-pal.so liberpal-occlum.so
# ==== fixme: the file /sbin/ldconfig maybe not exist in customer's image
chroot ${rootfs} /sbin/ldconfig
popd
}
function buildUnsignedEnclave(){
if [[ "${entry_point}" == "" || "${rootfs}" == "" || "${work_dir}" == "" ]]; then
echo "BuildUnsignedEnclave:: the argumentes should not be empty: entry_point, rootfs, work_dir"
exit 1
fi
rm -fr ${occlum_workspace}
mkdir -p ${occlum_workspace}
pushd ${occlum_workspace}
# occlum init
occlum init
# replace Occlum.json with user-supplied Occlum.json
if [[ "${occlum_config_path}" != "" && -f ${occlum_config_path} ]];then
/bin/cp -f ${occlum_config_path} Occlum.json
fi
# set occlum entrypoint
sed -i "s#/bin#${entry_point}#g" Occlum.json
/bin/bash ${data_dir}/replace_occlum_image.sh ${rootfs} image
# build occlum image
/bin/bash ${base_dir}/replace_occlum_image.sh ${rootfs} image
# occlum build
occlum build
rm -f ${rootfs}/${work_dir}/.occlum/build/lib/libocclum-libos.signed.so
mkdir -p ${rootfs}/${work_dir} || true
/bin/cp -fr .occlum ${rootfs}/${work_dir}
/bin/cp -f Enclave.xml ${rootfs}/${work_dir}
# ===fixme debug====
/bin/cp -fr image ${rootfs}/${work_dir}
/bin/cp -f Occlum.json ${rootfs}/${work_dir}
# ==================
/bin/cp -f Enclave.xml ${data_dir}
# copy occlum liberaries to rootfs
copyOcclumLiberaries
popd
pushd ${rootfs}/${work_dir}
# ==== copy sgxsdk libs =======
lib_dir=${rootfs}/lib
/bin/cp -f /usr/lib/x86_64-linux-gnu/libprotobuf.so ${lib_dir}
/bin/cp -f /lib/x86_64-linux-gnu/libseccomp.so.2 ${lib_dir}
/bin/cp -f /usr/lib/libsgx_u*.so* ${lib_dir}
/bin/cp -f /usr/lib/libsgx_enclave_common.so.1 ${lib_dir}
/bin/cp -f /usr/lib/libsgx_launch.so.1 ${lib_dir}
# ==================
ln -sfn .occlum/build/lib/libocclum-pal.so liberpal-occlum.so
chroot ${rootfs} /sbin/ldconfig
popd
`
}
function generateSigningMaterial() {
if [[ "${enclave_config_path}" == "" || "${unsigned_encalve_path}" == "" || "${unsigned_material_path}" == "" ]]; then
echo "GenerateSigningMaterial:: the argumentes should not be empty: enclave_config_path, unsigned_encalve_path, unsigned_material_path"
exit 1
fi
/opt/intel/sgxsdk/bin/x64/sgx_sign gendata -enclave ${unsigned_encalve_path} -config ${enclave_config_path} -out ${unsigned_material_path}
}
function cascadeEnclaveSignature() {
if [[ "${enclave_config_path}" == "" || "${unsigned_encalve_path}" == "" || "${unsigned_material_path}" == "" \
|| "${signed_enclave_path}" == "" || "${public_key_path}" == "" || "${signature_path}" == "" ]]; then
echo "CascadeEnclaveSignature:: the argumentes should not be empty: enclave_config_path, unsigned_encalve_path, unsigned_material_path, signed_enclave_path, public_key_path, signature_path"
exit 1
fi
/opt/intel/sgxsdk/bin/x64/sgx_sign catsig -enclave ${unsigned_encalve_path} -config ${enclave_config_path} -out ${signed_enclave_path} -key ${public_key_path} \
-sig ${signature_path} -unsigned ${unsigned_material_path}
}
function mockSignature() {
if [[ "${public_key_path}" == "" || "${signature_path}" == "" || "${unsigned_material_path}" == "" ]]; then
echo "MockSignature:: the argumentes should not be empty: public_key_path, signature_path, unsigned_material_path"
exit 1
fi
dir=$(mktemp -d)
openssl genrsa -out ${dir}/privatekey.pem -3 3072
openssl rsa -in ${dir}/privatekey.pem -pubout -out ${public_key_path}
openssl dgst -sha256 -out ${signature_path} -sign ${dir}/privatekey.pem -keyform PEM ${unsigned_material_path}
rm -fr ${dir}
}
function doAction(){
if [ "${action}" == "" ]; then
echo "the argument should not be empty: action"
exit 1
fi
case ${action} in
buildUnsignedEnclave)
buildUnsignedEnclave
;;
generateSigningMaterial)
generateSigningMaterial
;;
cascadeEnclaveSignature)
cascadeEnclaveSignature
;;
mockSignature)
mockSignature
;;
*)
echo "unknown action: ${action}"
exit 1
;;
esac
}
doAction`
StartScript
=
`#!/bin/bash
function handle_TERM() {
echo "recevied signal SIGTERM, exit now"
exit 0
}
function handle_INT() {
echo "recevied signal SIGINT, exit now"
exit 0
}
trap 'handle_INT' SIGINT
trap 'handle_TERM' SIGTERM
while true
do
sleep 1
done`
)
shim/runtime/carrier/occlum/occlum.go
浏览文件 @
33a410ee
...
...
@@ -2,51 +2,56 @@ package occlum
import
(
"context"
"encoding/hex"
"fmt"
"io/ioutil"
"math/rand"
"os"
"os/exec"
"path/filepath"
"strconv"
"syscall"
"time"
"github.com/BurntSushi/toml"
shim_config
"github.com/alibaba/inclavare-containers/shim/config"
"github.com/alibaba/inclavare-containers/shim/runtime/carrier"
carr_const
"github.com/alibaba/inclavare-containers/shim/runtime/carrier/constants"
"github.com/alibaba/inclavare-containers/shim/runtime/config"
"github.com/alibaba/inclavare-containers/shim/runtime/utils"
"github.com/alibaba/inclavare-containers/shim/runtime/v2/rune/constants"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/cmd/ctr/commands"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/runtime/v2/task"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"github.com/BurntSushi/toml"
"github.com/alibaba/inclavare-containers/shim/runtime/config"
shim_config
"github.com/alibaba/inclavare-containers/shim/config"
"github.com/alibaba/inclavare-containers/shim/runtime/carrier"
"github.com/alibaba/inclavare-containers/shim/runtime/v2/rune/constants"
carr_const
"github.com/alibaba/inclavare-containers/shim/runtime/carrier/constants"
)
const
(
defaultNamespace
=
"default"
//occlumEnclaveBuilderImage = "docker.io/occlum/occlum:0.12.0-ubuntu18.04"
buildOcclumEnclaveFileName
=
"build_occulum_enclave.sh"
defaultNamespace
=
"k8s.io"
replaceOcclumImageScript
=
"replace_occlum_image.sh"
//containerdAddress = "/run/containerd/containerd.sock"
carrierScriptFileName
=
"carrier.sh"
startScriptFileName
=
"start.sh"
rootfsDirName
=
"rootfs"
encalveDataDir
=
"data"
//sgxToolSign = "/opt/intel/sgxsdk/bin/x64/sgx_sign"
enclaveDataDir
=
"data"
)
var
_
carrier
.
Carrier
=
&
occlum
{}
type
occlumBuildTask
struct
{
client
*
containerd
.
Client
container
*
containerd
.
Container
task
*
containerd
.
Task
}
type
occlum
struct
{
context
context
.
Context
bundle
string
workDirectory
string
entryPoints
[]
string
configPath
string
task
*
occlumBuildTask
spec
*
specs
.
Spec
shimConfig
*
shim_config
.
Config
}
...
...
@@ -64,6 +69,7 @@ func NewOcclumCarrier(ctx context.Context, bundle string) (carrier.Carrier, erro
context
:
ctx
,
bundle
:
bundle
,
shimConfig
:
&
cfg
,
task
:
&
occlumBuildTask
{},
},
nil
}
...
...
@@ -82,59 +88,55 @@ func (c *occlum) BuildUnsignedEnclave(req *task.CreateTaskRequest, args *carrier
}
namespace
,
ok
:=
namespaces
.
Namespace
(
c
.
context
)
logrus
.
Debugf
(
"BuildUnsignedEnclave: get namespace %s, containerdAddress: %s"
,
namespace
,
c
.
shimConfig
.
Containerd
.
Socket
)
if
!
ok
{
namespace
=
defaultNamespace
}
// Create a new client connected to the default socket path for containerd.
client
,
err
:=
containerd
.
New
(
c
.
shimConfig
.
Containerd
.
Socket
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"failed to create containerd client. error: %++v"
,
err
)
}
else
{
c
.
task
.
client
=
client
}
defer
client
.
Close
()
logrus
.
Debugf
(
"BuildUnsignedEnclave: get containerd client successfully"
)
// Create a new context with "k8s.io" namespace
ctx
,
cancle
:=
context
.
WithTimeout
(
context
.
Background
(),
time
.
Minute
*
10
)
defer
cancle
()
ctx
=
namespaces
.
WithNamespace
(
c
.
context
,
namespace
)
if
err
=
createNamespaceIfNotExist
(
client
,
namespace
);
err
!=
nil
{
logrus
.
Errorf
(
"BuildUnsignedEnclave: create namespace %s failed. error: %++v"
,
namespace
,
err
)
return
""
,
err
}
// pull the image t
o be
used to build enclave.
// pull the image t
hat
used to build enclave.
occlumEnclaveBuilderImage
:=
c
.
shimConfig
.
EnclaveRuntime
.
Occlum
.
BuildImage
image
,
err
:=
client
.
Pull
(
c
tx
,
occlumEnclaveBuilderImage
,
containerd
.
WithPullUnpack
)
image
,
err
:=
client
.
Pull
(
c
.
context
,
occlumEnclaveBuilderImage
,
containerd
.
WithPullUnpack
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"failed to pull image %s. error: %++v"
,
occlumEnclaveBuilderImage
,
err
)
}
logrus
.
Debugf
(
"BuildUnsignedEnclave: pull image %s successfully"
,
occlumEnclaveBuilderImage
)
// Generate the containerID.
// Generate the containerId and snapshotId.
// FIXME debug
rand
.
Seed
(
time
.
Now
()
.
UnixNano
())
containerId
:=
fmt
.
Sprintf
(
"occlum-enclave-builder-%s"
,
strconv
.
FormatInt
(
rand
.
Int63
(),
16
))
snapshotId
:=
fmt
.
Sprintf
(
"occlum-enclave-builder-snapshot-%s"
,
strconv
.
FormatInt
(
rand
.
Int63
(),
16
))
logrus
.
Debugf
(
"BuildUnsignedEnclave: containerId: %s, snapshotId: %s"
,
containerId
,
snapshotId
)
if
err
:=
os
.
Mkdir
(
filepath
.
Join
(
req
.
Bundle
,
enc
al
veDataDir
),
0755
);
err
!=
nil
{
if
err
:=
os
.
Mkdir
(
filepath
.
Join
(
req
.
Bundle
,
enc
la
veDataDir
),
0755
);
err
!=
nil
{
return
""
,
err
}
// Create a shell script which is used to build occlum enclave.
buildEnclaveScript
:=
filepath
.
Join
(
req
.
Bundle
,
encalveDataDir
,
buildOcclumEnclaveFileName
)
if
err
:=
ioutil
.
WriteFile
(
buildEnclaveScript
,
[]
byte
(
fmt
.
Sprintf
(
carr_const
.
BuildOcclumEnclaveScript
,
c
.
workDirectory
,
c
.
entryPoints
[
0
],
c
.
configPath
)),
os
.
ModePerm
);
err
!=
nil
{
replaceImagesScript
:=
filepath
.
Join
(
req
.
Bundle
,
enclaveDataDir
,
replaceOcclumImageScript
)
if
err
:=
ioutil
.
WriteFile
(
replaceImagesScript
,
[]
byte
(
carr_const
.
ReplaceOcclumImageScript
),
os
.
ModePerm
);
err
!=
nil
{
return
""
,
err
}
replaceImagesScript
:=
filepath
.
Join
(
req
.
Bundle
,
encalveDataDir
,
replaceOcclumImageScript
)
if
err
:=
ioutil
.
WriteFile
(
replaceImagesScript
,
[]
byte
(
carr_const
.
ReplaceOcclumImageScript
),
os
.
ModePerm
);
err
!=
nil
{
carrierScript
:=
filepath
.
Join
(
req
.
Bundle
,
enclaveDataDir
,
carrierScriptFileName
)
if
err
:=
ioutil
.
WriteFile
(
carrierScript
,
[]
byte
(
carr_const
.
CarrierScript
),
os
.
ModePerm
);
err
!=
nil
{
return
""
,
err
}
startScript
:=
filepath
.
Join
(
req
.
Bundle
,
enclaveDataDir
,
startScriptFileName
)
if
err
:=
ioutil
.
WriteFile
(
startScript
,
[]
byte
(
carr_const
.
StartScript
),
os
.
ModePerm
);
err
!=
nil
{
return
""
,
err
}
...
...
@@ -147,9 +149,9 @@ func (c *occlum) BuildUnsignedEnclave(req *task.CreateTaskRequest, args *carrier
Options
:
[]
string
{
"rbind"
,
"rw"
},
}
dataMount
:=
specs
.
Mount
{
Destination
:
filepath
.
Join
(
"/"
,
enc
al
veDataDir
),
Destination
:
filepath
.
Join
(
"/"
,
enc
la
veDataDir
),
Type
:
"bind"
,
Source
:
filepath
.
Join
(
req
.
Bundle
,
enc
al
veDataDir
),
Source
:
filepath
.
Join
(
req
.
Bundle
,
enc
la
veDataDir
),
Options
:
[]
string
{
"rbind"
,
"rw"
},
}
...
...
@@ -159,14 +161,12 @@ func (c *occlum) BuildUnsignedEnclave(req *task.CreateTaskRequest, args *carrier
mounts
=
append
(
mounts
,
rootfsMount
,
dataMount
)
// create a container
container
,
err
:=
client
.
NewContainer
(
c
tx
,
c
.
context
,
containerId
,
containerd
.
WithImage
(
image
),
containerd
.
WithNewSnapshot
(
snapshotId
,
image
),
containerd
.
WithNewSpec
(
oci
.
WithImageConfig
(
image
),
oci
.
WithProcessArgs
(
"/bin/bash"
,
filepath
.
Join
(
"/"
,
encalveDataDir
,
buildOcclumEnclaveFileName
)),
//FIXME debug
//oci.WithProcessArgs("sleep", "infinity"),
oci
.
WithProcessArgs
(
"/bin/bash"
,
filepath
.
Join
(
"/"
,
enclaveDataDir
,
startScriptFileName
)),
oci
.
WithPrivileged
,
oci
.
WithMounts
(
mounts
),
),
...
...
@@ -174,40 +174,40 @@ func (c *occlum) BuildUnsignedEnclave(req *task.CreateTaskRequest, args *carrier
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"failed to create container by image %s. error: %++v"
,
occlumEnclaveBuilderImage
,
err
)
}
else
{
c
.
task
.
container
=
&
container
}
defer
container
.
Delete
(
ctx
,
containerd
.
WithSnapshotCleanup
)
// Create a task from the container.
t
ask
,
err
:=
container
.
NewTask
(
ctx
,
cio
.
NewCreator
(
cio
.
WithStdio
))
t
,
err
:=
container
.
NewTask
(
c
.
context
,
cio
.
NewCreator
(
cio
.
WithStdio
))
if
err
!=
nil
{
return
""
,
err
}
else
{
c
.
task
.
task
=
&
t
}
defer
task
.
Delete
(
ctx
)
logrus
.
Debugf
(
"BuildUnsignedEnclave: create task successfully"
)
// Wait before calling start
exitStatusC
,
err
:=
task
.
Wait
(
ctx
)
if
err
!=
nil
{
if
err
:=
t
.
Start
(
c
.
context
);
err
!=
nil
{
logrus
.
Errorf
(
"BuildUnsignedEnclave: start task failed. error: %++v"
,
err
)
return
""
,
err
}
// Call start() on the task to execute the building scripts.
if
err
:=
task
.
Start
(
ctx
);
err
!=
nil
{
return
""
,
err
cmd
:=
[]
string
{
"/bin/bash"
,
filepath
.
Join
(
"/"
,
enclaveDataDir
,
carrierScriptFileName
),
"--action"
,
"buildUnsignedEnclave"
,
"--entry_point"
,
c
.
entryPoints
[
0
],
"--work_dir"
,
c
.
workDirectory
,
"--rootfs"
,
filepath
.
Join
(
"/"
,
rootfsDirName
),
}
// Wait for the process to fully exit and print out the exit status
status
:=
<-
exitStatusC
code
,
_
,
err
:=
status
.
Result
()
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"container exited abnormaly with exit code %d. error: %++v"
,
code
,
err
)
}
else
if
code
!=
0
{
return
""
,
fmt
.
Errorf
(
"container exited abnormaly with exit code %d"
,
code
)
if
c
.
configPath
!=
""
{
cmd
=
append
(
cmd
,
"--occlum_config_path"
,
filepath
.
Join
(
"/"
,
rootfsDirName
,
c
.
configPath
))
}
enclavePath
:=
filepath
.
Join
(
req
.
Bundle
,
rootfsDirName
,
c
.
workDirectory
,
".occlum/build/lib/libocclum-libos.so"
)
logrus
.
Debugf
(
"BuildUnsignedEnclave: exit code: %d. enclavePath: %s"
,
code
,
enclavePath
)
logrus
.
Debugf
(
"BuildUnsignedEnclave: command: %v"
,
cmd
)
if
err
:=
c
.
execTask
(
cmd
...
);
err
!=
nil
{
logrus
.
Errorf
(
"BuildUnsignedEnclave: exec failed. error: %++v"
,
err
)
return
""
,
err
}
enclavePath
:=
filepath
.
Join
(
"/"
,
rootfsDirName
,
c
.
workDirectory
,
".occlum/build/lib/libocclum-libos.so"
)
return
enclavePath
,
nil
}
...
...
@@ -215,69 +215,107 @@ func (c *occlum) BuildUnsignedEnclave(req *task.CreateTaskRequest, args *carrier
// GenerateSigningMaterial impl Carrier.
func
(
c
*
occlum
)
GenerateSigningMaterial
(
req
*
task
.
CreateTaskRequest
,
args
*
carrier
.
CommonArgs
)
(
signingMaterial
string
,
err
error
)
{
signingMaterial
=
filepath
.
Join
(
req
.
Bundle
,
encalveDataDir
,
"enclave_sig.dat"
)
args
.
Config
=
filepath
.
Join
(
req
.
Bundle
,
encalveDataDir
,
"Enclave.xml"
)
sgxToolSign
:=
c
.
shimConfig
.
SgxToolSign
logrus
.
Debugf
(
"GenerateSigningMaterial cmmmand: %s gendata -enclave %s -config %s -out %s"
,
sgxToolSign
,
args
.
Enclave
,
args
.
Config
,
signingMaterial
)
gendataArgs
:=
[]
string
{
"gendata"
,
"-enclave"
,
args
.
Enclave
,
"-config"
,
args
.
Config
,
"-out"
,
signingMaterial
,
signingMaterial
=
filepath
.
Join
(
"/"
,
rootfsDirName
,
c
.
workDirectory
,
"enclave_sig.dat"
)
args
.
Config
=
filepath
.
Join
(
"/"
,
rootfsDirName
,
c
.
workDirectory
,
"Enclave.xml"
)
cmd
:=
[]
string
{
"/bin/bash"
,
filepath
.
Join
(
"/"
,
enclaveDataDir
,
carrierScriptFileName
),
"--action"
,
"generateSigningMaterial"
,
"--enclave_config_path"
,
args
.
Config
,
"--unsigned_encalve_path"
,
args
.
Enclave
,
"--unsigned_material_path"
,
signingMaterial
,
}
cmd
:=
exec
.
Command
(
sgxToolSign
,
gendataArgs
...
)
if
result
,
err
:=
cmd
.
Output
();
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"GenerateSigningMaterial: sgx_sign gendata failed. error: %v %s"
,
err
,
string
(
result
))
logrus
.
Debugf
(
"GenerateSigningMaterial: sgx_sign gendata command: %v"
,
cmd
)
if
err
:=
c
.
execTask
(
cmd
...
);
err
!=
nil
{
logrus
.
Errorf
(
"GenerateSigningMaterial: sgx_sign gendata failed. error: %++v"
,
err
)
return
""
,
err
}
logrus
.
Debugf
(
"GenerateSigningMaterial: sgx_sign gendata successfully"
)
return
signingMaterial
,
nil
}
// CascadeEnclaveSignature impl Carrier.
func
(
c
*
occlum
)
CascadeEnclaveSignature
(
req
*
task
.
CreateTaskRequest
,
args
*
carrier
.
CascadeEnclaveSignatureArgs
)
(
signedEnclave
string
,
err
error
)
{
signedEnclave
=
filepath
.
Join
(
req
.
Bundle
,
rootfsDirName
,
c
.
workDirectory
,
".occlum/build/lib/libocclum-libos.signed.so"
)
sgxToolSign
:=
c
.
shimConfig
.
SgxToolSign
logrus
.
Debugf
(
"CascadeEnclaveSignature cmmmand: %s catsig -enclave %s -config %s -out %s -key %s -sig %s -unsigned %s"
,
sgxToolSign
,
args
.
Enclave
,
args
.
Config
,
signedEnclave
,
args
.
Key
,
args
.
Signature
,
args
.
SigningMaterial
)
catsigArgs
:=
[]
string
{
"catsig"
,
"-enclave"
,
args
.
Enclave
,
"-config"
,
args
.
Config
,
"-out"
,
signedEnclave
,
"-key"
,
args
.
Key
,
"-sig"
,
args
.
Signature
,
"-unsigned"
,
args
.
SigningMaterial
,
}
cmd
:=
exec
.
Command
(
sgxToolSign
,
catsigArgs
...
)
if
result
,
err
:=
cmd
.
Output
();
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"CascadeEnclaveSignature: sgx_sign catsig failed. error: %v %s"
,
err
,
string
(
result
))
var
bufferSize
int64
=
1024
*
4
signedEnclave
=
filepath
.
Join
(
"/"
,
rootfsDirName
,
c
.
workDirectory
,
".occlum/build/lib/libocclum-libos.signed.so"
)
publicKey
:=
filepath
.
Join
(
"/"
,
enclaveDataDir
,
"public_key.pem"
)
signature
:=
filepath
.
Join
(
"/"
,
enclaveDataDir
,
"signature.dat"
)
if
err
:=
utils
.
CopyFile
(
args
.
Key
,
filepath
.
Join
(
req
.
Bundle
,
publicKey
),
bufferSize
);
err
!=
nil
{
logrus
.
Errorf
(
"CascadeEnclaveSignature copy file %s to %s failed. err: %++v"
,
args
.
Key
,
publicKey
,
err
)
return
""
,
err
}
if
err
:=
utils
.
CopyFile
(
args
.
Signature
,
filepath
.
Join
(
req
.
Bundle
,
signature
),
bufferSize
);
err
!=
nil
{
logrus
.
Errorf
(
"CascadeEnclaveSignature copy file %s to %s failed. err: %++v"
,
args
.
Signature
,
signature
,
err
)
return
""
,
err
}
cmd
:=
[]
string
{
"/bin/bash"
,
filepath
.
Join
(
"/"
,
enclaveDataDir
,
carrierScriptFileName
),
"--action"
,
"cascadeEnclaveSignature"
,
"--enclave_config_path"
,
args
.
Config
,
"--unsigned_encalve_path"
,
args
.
Enclave
,
"--unsigned_material_path"
,
args
.
SigningMaterial
,
"--signed_enclave_path"
,
signedEnclave
,
"--public_key_path"
,
publicKey
,
"--signature_path"
,
signature
,
}
logrus
.
Debugf
(
"CascadeEnclaveSignature: sgx_sign catsig command: %v"
,
cmd
)
if
err
:=
c
.
execTask
(
cmd
...
);
err
!=
nil
{
logrus
.
Errorf
(
"CascadeEnclaveSignature: sgx_sign catsig failed. error: %++v"
,
err
)
return
""
,
err
}
logrus
.
Debugf
(
"CascadeEnclaveSignature: sgx_sign catsig successfully"
)
return
signedEnclave
,
nil
}
// Cleanup impl Carrier.
func
(
c
*
occlum
)
Cleanup
()
error
{
//TODO
defer
func
()
{
if
c
.
task
.
client
!=
nil
{
c
.
task
.
client
.
Close
()
}
}()
defer
func
()
{
if
c
.
task
.
container
!=
nil
{
container
:=
*
c
.
task
.
container
if
err
:=
container
.
Delete
(
c
.
context
,
containerd
.
WithSnapshotCleanup
);
err
!=
nil
{
logrus
.
Errorf
(
"Cleanup: delete container %s failed. err: %++v"
,
container
.
ID
(),
err
)
}
logrus
.
Debugf
(
"Cleanup: delete container %s successfully."
,
container
.
ID
())
}
}()
if
c
.
task
.
task
==
nil
{
return
nil
}
t
:=
*
c
.
task
.
task
if
err
:=
t
.
Kill
(
c
.
context
,
syscall
.
SIGTERM
);
err
!=
nil
{
logrus
.
Errorf
(
"Cleanup: kill task %s failed. err: %++v"
,
t
.
ID
(),
err
)
return
err
}
for
{
status
,
err
:=
t
.
Status
(
c
.
context
)
if
err
!=
nil
{
logrus
.
Errorf
(
"Cleanup: get task %s status failed. error: %++v"
,
t
.
ID
(),
err
)
return
err
}
if
status
.
ExitStatus
!=
0
{
logrus
.
Errorf
(
"Cleanup: task %s exit abnormally. exit code: %d, task status: %s"
,
t
.
ID
(),
status
.
ExitStatus
,
status
.
Status
)
return
fmt
.
Errorf
(
"task %s exit abnormally. exit code: %d, task status: %s"
,
t
.
ID
(),
status
.
ExitStatus
,
status
.
Status
)
}
if
status
.
Status
!=
containerd
.
Stopped
{
logrus
.
Debugf
(
"Cleanup: task %s status: %s"
,
t
.
ID
(),
status
.
Status
)
time
.
Sleep
(
time
.
Second
)
continue
}
break
}
if
_
,
err
:=
t
.
Delete
(
c
.
context
);
err
!=
nil
{
logrus
.
Errorf
(
"Cleanup: delete task %s failed. error: %++v"
,
t
.
ID
(),
err
)
return
err
}
logrus
.
Debugf
(
"Cleanup: clean occlum container and task successfully"
)
return
nil
}
...
...
@@ -295,17 +333,14 @@ func (c *occlum) initBundleConfig() error {
carr_const
.
EnclaveTypeKeyName
:
string
(
carr_const
.
IntelSGX
),
carr_const
.
EnclaveRuntimeArgsKeyName
:
carr_const
.
DefaultEnclaveRuntimeArgs
,
}
if
o
cclumConfigPath
,
ok
:=
config
.
GetEnv
(
spec
,
carr_const
.
OcclumConfigPathKeyName
);
o
k
{
occlumConfigPath
,
ok
:=
config
.
GetEnv
(
spec
,
carr_const
.
OcclumConfigPathKeyName
)
if
ok
{
c
.
configPath
=
occlumConfigPath
}
c
.
spec
=
spec
if
err
:=
config
.
UpdateEnvs
(
spec
,
envs
,
false
);
err
!=
nil
{
return
err
}
return
config
.
SaveSpec
(
configPath
,
spec
)
}
...
...
@@ -328,13 +363,6 @@ func createNamespaceIfNotExist(client *containerd.Client, namespace string) erro
return
svc
.
Create
(
ctx
,
namespace
,
nil
)
}
// generateID generates a random unique id.
func
generateID
()
string
{
b
:=
make
([]
byte
,
32
)
rand
.
Read
(
b
)
return
hex
.
EncodeToString
(
b
)
}
func
setLogLevel
(
level
string
)
{
switch
level
{
case
"debug"
:
...
...
@@ -349,3 +377,50 @@ func setLogLevel(level string) {
logrus
.
SetLevel
(
logrus
.
InfoLevel
)
}
}
func
(
c
*
occlum
)
execTask
(
args
...
string
)
error
{
container
:=
*
c
.
task
.
container
t
:=
*
c
.
task
.
task
if
container
==
nil
||
t
==
nil
{
return
fmt
.
Errorf
(
"task is not exist"
)
}
spec
,
err
:=
container
.
Spec
(
c
.
context
)
if
err
!=
nil
{
logrus
.
Errorf
(
"execTask: get container spec failed. error: %++v"
,
err
)
return
err
}
pspec
:=
spec
.
Process
pspec
.
Terminal
=
false
pspec
.
Args
=
args
cioOpts
:=
[]
cio
.
Opt
{
cio
.
WithStdio
,
cio
.
WithFIFODir
(
"/run/containerd/fifo"
)}
ioCreator
:=
cio
.
NewCreator
(
cioOpts
...
)
process
,
err
:=
t
.
Exec
(
c
.
context
,
utils
.
GenerateID
(),
pspec
,
ioCreator
)
if
err
!=
nil
{
logrus
.
Errorf
(
"execTask: exec process in task failed. error: %++v"
,
err
)
return
err
}
defer
process
.
Delete
(
c
.
context
)
statusC
,
err
:=
process
.
Wait
(
c
.
context
)
if
err
!=
nil
{
return
err
}
sigc
:=
commands
.
ForwardAllSignals
(
c
.
context
,
process
)
defer
commands
.
StopCatch
(
sigc
)
if
err
:=
process
.
Start
(
c
.
context
);
err
!=
nil
{
logrus
.
Errorf
(
"execTask: start process failed. error: %++v"
,
err
)
return
err
}
status
:=
<-
statusC
code
,
_
,
err
:=
status
.
Result
()
if
err
!=
nil
{
logrus
.
Errorf
(
"execTask: exec process failed. error: %++v"
,
err
)
return
err
}
if
code
!=
0
{
return
fmt
.
Errorf
(
"process exit abnormaly. exitCode: %d, error: %++v"
,
code
,
status
.
Error
())
}
logrus
.
Debugf
(
"execTask: exec successfully."
)
return
nil
}
shim/runtime/utils/utils.go
0 → 100644
浏览文件 @
33a410ee
package
utils
import
(
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"os"
)
func
CopyFile
(
src
,
dst
string
,
bufferSize
int64
)
error
{
sourceFileStat
,
err
:=
os
.
Stat
(
src
)
if
err
!=
nil
{
return
err
}
if
!
sourceFileStat
.
Mode
()
.
IsRegular
()
{
return
fmt
.
Errorf
(
"%s is not a regular file."
,
src
)
}
source
,
err
:=
os
.
Open
(
src
)
if
err
!=
nil
{
return
err
}
defer
source
.
Close
()
_
,
err
=
os
.
Stat
(
dst
)
if
err
==
nil
{
return
fmt
.
Errorf
(
"File %s already exists."
,
dst
)
}
destination
,
err
:=
os
.
Create
(
dst
)
if
err
!=
nil
{
return
err
}
defer
destination
.
Close
()
if
err
!=
nil
{
panic
(
err
)
}
buf
:=
make
([]
byte
,
bufferSize
)
for
{
n
,
err
:=
source
.
Read
(
buf
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
return
err
}
if
n
==
0
{
break
}
if
_
,
err
:=
destination
.
Write
(
buf
[
:
n
]);
err
!=
nil
{
return
err
}
}
return
err
}
// GenerateID generates a random unique id.
func
GenerateID
()
string
{
b
:=
make
([]
byte
,
32
)
rand
.
Read
(
b
)
return
hex
.
EncodeToString
(
b
)
}
shim/runtime/v2/rune/v2/rune.go
浏览文件 @
33a410ee
...
...
@@ -31,9 +31,7 @@ func (s *service) carrierMain(req *taskAPI.CreateTaskRequest) (carrier.Carrier,
var
carr
carrier
.
Carrier
defer
func
()
{
if
err
!=
nil
&&
carr
!=
nil
{
carr
.
Cleanup
()
}
}()
found
,
carrierKind
,
err
:=
getCarrierKind
(
req
.
Bundle
)
...
...
@@ -98,8 +96,13 @@ func (s *service) carrierMain(req *taskAPI.CreateTaskRequest) (carrier.Carrier,
/*publicKey, signature, err := remoteSign("https://10.0.8.126:8443/api/v1/signature", commonArgs.Enclave)
defer os.RemoveAll(path.Dir(publicKey))*/
//FIXME mock signature
publicKey
,
signature
,
err
:=
mockSign
(
signingMaterial
)
materialRealPath
:=
signingMaterial
if
carrierKind
==
rune
.
Occlum
{
materialRealPath
=
filepath
.
Join
(
req
.
Bundle
,
signingMaterial
)
}
publicKey
,
signature
,
err
:=
mockSign
(
materialRealPath
)
if
err
!=
nil
{
logrus
.
Errorf
(
"carrierMain: mock sign failed. error: %++v"
,
err
)
return
carr
,
err
}
defer
os
.
RemoveAll
(
path
.
Dir
(
publicKey
))
...
...
@@ -115,12 +118,6 @@ func (s *service) carrierMain(req *taskAPI.CreateTaskRequest) (carrier.Carrier,
return
carr
,
err
}
logrus
.
Debugf
(
"Finished carrier: %v, signedEnclave: %s"
,
carr
,
signedEnclave
)
//FIXME debug
//if carrierKind == rune.Occlum {
// time.Sleep(time.Minute * 3)
//}
return
carr
,
nil
}
...
...
shim/runtime/v2/rune/v2/service.go
浏览文件 @
33a410ee
...
...
@@ -305,12 +305,9 @@ func setOCIRuntime(ctx context.Context, r *taskAPI.CreateTaskRequest) (err error
// Create a new initial process and container with the underlying OCI runtime
func
(
s
*
service
)
Create
(
ctx
context
.
Context
,
r
*
taskAPI
.
CreateTaskRequest
)
(
_
*
taskAPI
.
CreateTaskResponse
,
err
error
)
{
logrus
.
Infof
(
"xxxx debug 0 =============="
)
s
.
mu
.
Lock
()
defer
s
.
mu
.
Unlock
()
logrus
.
Infof
(
"xxxx debug 1 =============="
)
err
=
setOCIRuntime
(
ctx
,
r
)
if
err
!=
nil
{
return
nil
,
err
...
...
@@ -318,7 +315,6 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
carr
,
err
:=
s
.
carrierMain
(
r
)
if
err
!=
nil
{
logrus
.
Infof
(
"xxxx debug 2 =============="
)
return
nil
,
err
}
...
...
@@ -328,7 +324,6 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
container
,
err
:=
runc
.
NewContainer
(
ctx
,
s
.
platform
,
r
)
if
err
!=
nil
{
logrus
.
Errorf
(
"rune Create NewContainer error: %++v"
,
err
)
logrus
.
Infof
(
"xxxx debug 3 =============="
)
return
nil
,
err
}
...
...
@@ -381,7 +376,6 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
// log.G(ctx).Infof("Attestation Failed!")
//}
}
logrus
.
Infof
(
"xxxx debug 4 =============="
)
return
&
taskAPI
.
CreateTaskResponse
{
Pid
:
uint32
(
container
.
Pid
()),
},
nil
...
...
@@ -389,35 +383,28 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
// Start a process
func
(
s
*
service
)
Start
(
ctx
context
.
Context
,
r
*
taskAPI
.
StartRequest
)
(
*
taskAPI
.
StartResponse
,
error
)
{
logrus
.
Infof
(
"xxxx debug 5 =============="
)
container
,
err
:=
s
.
getContainer
(
r
.
ID
)
if
err
!=
nil
{
logrus
.
Infof
(
"xxxx debug 6 =============="
)
return
nil
,
err
}
// hold the send lock so that the start events are sent before any exit events in the error case
s
.
eventSendMu
.
Lock
()
p
,
err
:=
container
.
Start
(
ctx
,
r
)
logrus
.
Infof
(
"xxxx debug 7 =============="
)
if
err
!=
nil
{
s
.
eventSendMu
.
Unlock
()
logrus
.
Infof
(
"xxxx debug 8 ==============. error: %++v"
,
err
)
return
nil
,
errdefs
.
ToGRPC
(
err
)
}
switch
r
.
ExecID
{
case
""
:
if
err
:=
s
.
ep
.
Add
(
container
.
ID
,
container
.
Cgroup
());
err
!=
nil
{
logrus
.
Infof
(
"xxxx debug 9 =============="
)
logrus
.
WithError
(
err
)
.
Error
(
"add cg to OOM monitor"
)
}
logrus
.
Infof
(
"xxxx debug 10 =============="
)
s
.
send
(
&
eventstypes
.
TaskStart
{
ContainerID
:
container
.
ID
,
Pid
:
uint32
(
p
.
Pid
()),
})
default
:
logrus
.
Infof
(
"xxxx debug 11 =============="
)
s
.
send
(
&
eventstypes
.
TaskExecStarted
{
ContainerID
:
container
.
ID
,
ExecID
:
r
.
ExecID
,
...
...
@@ -425,7 +412,6 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
})
}
s
.
eventSendMu
.
Unlock
()
logrus
.
Infof
(
"xxxx debug 12 =============="
)
return
&
taskAPI
.
StartResponse
{
Pid
:
uint32
(
p
.
Pid
()),
},
nil
...
...
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/client.go
0 → 100644
浏览文件 @
33a410ee
/*
Copyright The containerd 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
commands
import
(
gocontext
"context"
"github.com/containerd/containerd"
"github.com/containerd/containerd/namespaces"
"github.com/urfave/cli"
)
// AppContext returns the context for a command. Should only be called once per
// command, near the start.
//
// This will ensure the namespace is picked up and set the timeout, if one is
// defined.
func
AppContext
(
context
*
cli
.
Context
)
(
gocontext
.
Context
,
gocontext
.
CancelFunc
)
{
var
(
ctx
=
gocontext
.
Background
()
timeout
=
context
.
GlobalDuration
(
"timeout"
)
namespace
=
context
.
GlobalString
(
"namespace"
)
cancel
gocontext
.
CancelFunc
)
ctx
=
namespaces
.
WithNamespace
(
ctx
,
namespace
)
if
timeout
>
0
{
ctx
,
cancel
=
gocontext
.
WithTimeout
(
ctx
,
timeout
)
}
else
{
ctx
,
cancel
=
gocontext
.
WithCancel
(
ctx
)
}
return
ctx
,
cancel
}
// NewClient returns a new containerd client
func
NewClient
(
context
*
cli
.
Context
,
opts
...
containerd
.
ClientOpt
)
(
*
containerd
.
Client
,
gocontext
.
Context
,
gocontext
.
CancelFunc
,
error
)
{
timeoutOpt
:=
containerd
.
WithTimeout
(
context
.
GlobalDuration
(
"connect-timeout"
))
opts
=
append
(
opts
,
timeoutOpt
)
client
,
err
:=
containerd
.
New
(
context
.
GlobalString
(
"address"
),
opts
...
)
if
err
!=
nil
{
return
nil
,
nil
,
nil
,
err
}
ctx
,
cancel
:=
AppContext
(
context
)
return
client
,
ctx
,
cancel
,
nil
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
0 → 100644
浏览文件 @
33a410ee
/*
Copyright The containerd 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
commands
import
(
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/containerd/containerd/defaults"
"github.com/urfave/cli"
)
var
(
// SnapshotterFlags are cli flags specifying snapshotter names
SnapshotterFlags
=
[]
cli
.
Flag
{
cli
.
StringFlag
{
Name
:
"snapshotter"
,
Usage
:
"snapshotter name. Empty value stands for the default value."
,
EnvVar
:
"CONTAINERD_SNAPSHOTTER"
,
},
}
// LabelFlag is a cli flag specifying labels
LabelFlag
=
cli
.
StringSliceFlag
{
Name
:
"label"
,
Usage
:
"labels to attach to the image"
,
}
// RegistryFlags are cli flags specifying registry options
RegistryFlags
=
[]
cli
.
Flag
{
cli
.
BoolFlag
{
Name
:
"skip-verify,k"
,
Usage
:
"skip SSL certificate validation"
,
},
cli
.
BoolFlag
{
Name
:
"plain-http"
,
Usage
:
"allow connections using plain HTTP"
,
},
cli
.
StringFlag
{
Name
:
"user,u"
,
Usage
:
"user[:password] Registry user and password"
,
},
cli
.
StringFlag
{
Name
:
"refresh"
,
Usage
:
"refresh token for authorization server"
,
},
}
// ContainerFlags are cli flags specifying container options
ContainerFlags
=
[]
cli
.
Flag
{
cli
.
StringFlag
{
Name
:
"config,c"
,
Usage
:
"path to the runtime-specific spec config file"
,
},
cli
.
StringFlag
{
Name
:
"cwd"
,
Usage
:
"specify the working directory of the process"
,
},
cli
.
StringSliceFlag
{
Name
:
"env"
,
Usage
:
"specify additional container environment variables (i.e. FOO=bar)"
,
},
cli
.
StringFlag
{
Name
:
"env-file"
,
Usage
:
"specify additional container environment variables in a file(i.e. FOO=bar, one per line)"
,
},
cli
.
StringSliceFlag
{
Name
:
"label"
,
Usage
:
"specify additional labels (i.e. foo=bar)"
,
},
cli
.
StringSliceFlag
{
Name
:
"mount"
,
Usage
:
"specify additional container mount (ex: type=bind,src=/tmp,dst=/host,options=rbind:ro)"
,
},
cli
.
BoolFlag
{
Name
:
"net-host"
,
Usage
:
"enable host networking for the container"
,
},
cli
.
BoolFlag
{
Name
:
"privileged"
,
Usage
:
"run privileged container"
,
},
cli
.
BoolFlag
{
Name
:
"read-only"
,
Usage
:
"set the containers filesystem as readonly"
,
},
cli
.
StringFlag
{
Name
:
"runtime"
,
Usage
:
"runtime name"
,
Value
:
defaults
.
DefaultRuntime
,
},
cli
.
BoolFlag
{
Name
:
"tty,t"
,
Usage
:
"allocate a TTY for the container"
,
},
cli
.
StringSliceFlag
{
Name
:
"with-ns"
,
Usage
:
"specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')"
,
},
cli
.
StringFlag
{
Name
:
"pid-file"
,
Usage
:
"file path to write the task's pid"
,
},
cli
.
IntFlag
{
Name
:
"gpus"
,
Usage
:
"add gpus to the container"
,
},
cli
.
BoolFlag
{
Name
:
"allow-new-privs"
,
Usage
:
"turn off OCI spec's NoNewPrivileges feature flag"
,
},
cli
.
Uint64Flag
{
Name
:
"memory-limit"
,
Usage
:
"memory limit (in bytes) for the container"
,
},
cli
.
StringSliceFlag
{
Name
:
"device"
,
Usage
:
"add a device to a container"
,
},
cli
.
BoolFlag
{
Name
:
"seccomp"
,
Usage
:
"enable the default seccomp profile"
,
},
}
)
// ObjectWithLabelArgs returns the first arg and a LabelArgs object
func
ObjectWithLabelArgs
(
clicontext
*
cli
.
Context
)
(
string
,
map
[
string
]
string
)
{
var
(
first
=
clicontext
.
Args
()
.
First
()
labelStrings
=
clicontext
.
Args
()
.
Tail
()
)
return
first
,
LabelArgs
(
labelStrings
)
}
// LabelArgs returns a map of label key,value pairs
func
LabelArgs
(
labelStrings
[]
string
)
map
[
string
]
string
{
labels
:=
make
(
map
[
string
]
string
,
len
(
labelStrings
))
for
_
,
label
:=
range
labelStrings
{
parts
:=
strings
.
SplitN
(
label
,
"="
,
2
)
key
:=
parts
[
0
]
value
:=
"true"
if
len
(
parts
)
>
1
{
value
=
parts
[
1
]
}
labels
[
key
]
=
value
}
return
labels
}
// PrintAsJSON prints input in JSON format
func
PrintAsJSON
(
x
interface
{})
{
b
,
err
:=
json
.
MarshalIndent
(
x
,
""
,
" "
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"can't marshal %+v as a JSON string: %v
\n
"
,
x
,
err
)
}
fmt
.
Println
(
string
(
b
))
}
// WritePidFile writes the pid atomically to a file
func
WritePidFile
(
path
string
,
pid
int
)
error
{
path
,
err
:=
filepath
.
Abs
(
path
)
if
err
!=
nil
{
return
err
}
tempPath
:=
filepath
.
Join
(
filepath
.
Dir
(
path
),
fmt
.
Sprintf
(
".%s"
,
filepath
.
Base
(
path
)))
f
,
err
:=
os
.
OpenFile
(
tempPath
,
os
.
O_RDWR
|
os
.
O_CREATE
|
os
.
O_EXCL
|
os
.
O_SYNC
,
0666
)
if
err
!=
nil
{
return
err
}
_
,
err
=
fmt
.
Fprintf
(
f
,
"%d"
,
pid
)
f
.
Close
()
if
err
!=
nil
{
return
err
}
return
os
.
Rename
(
tempPath
,
path
)
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
0 → 100644
浏览文件 @
33a410ee
// +build !windows
/*
Copyright The containerd 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
commands
import
(
"github.com/urfave/cli"
)
func
init
()
{
ContainerFlags
=
append
(
ContainerFlags
,
cli
.
BoolFlag
{
Name
:
"rootfs"
,
Usage
:
"use custom rootfs that is not managed by containerd snapshotter"
,
},
cli
.
BoolFlag
{
Name
:
"no-pivot"
,
Usage
:
"disable use of pivot-root (linux only)"
,
})
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go
0 → 100644
浏览文件 @
33a410ee
// +build windows
/*
Copyright The containerd 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
commands
import
(
"github.com/urfave/cli"
)
func
init
()
{
ContainerFlags
=
append
(
ContainerFlags
,
cli
.
Uint64Flag
{
Name
:
"cpu-count"
,
Usage
:
"number of CPUs available to the container"
,
})
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
0 → 100644
浏览文件 @
33a410ee
/*
Copyright The containerd 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
commands
import
(
"bufio"
gocontext
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"strings"
"time"
"github.com/containerd/console"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
// PushTracker returns a new InMemoryTracker which tracks the ref status
var
PushTracker
=
docker
.
NewInMemoryTracker
()
func
passwordPrompt
()
(
string
,
error
)
{
c
:=
console
.
Current
()
defer
c
.
Reset
()
if
err
:=
c
.
DisableEcho
();
err
!=
nil
{
return
""
,
errors
.
Wrap
(
err
,
"failed to disable echo"
)
}
line
,
_
,
err
:=
bufio
.
NewReader
(
c
)
.
ReadLine
()
if
err
!=
nil
{
return
""
,
errors
.
Wrap
(
err
,
"failed to read line"
)
}
return
string
(
line
),
nil
}
// GetResolver prepares the resolver from the environment and options
func
GetResolver
(
ctx
gocontext
.
Context
,
clicontext
*
cli
.
Context
)
(
remotes
.
Resolver
,
error
)
{
username
:=
clicontext
.
String
(
"user"
)
var
secret
string
if
i
:=
strings
.
IndexByte
(
username
,
':'
);
i
>
0
{
secret
=
username
[
i
+
1
:
]
username
=
username
[
0
:
i
]
}
options
:=
docker
.
ResolverOptions
{
PlainHTTP
:
clicontext
.
Bool
(
"plain-http"
),
Tracker
:
PushTracker
,
}
if
username
!=
""
{
if
secret
==
""
{
fmt
.
Printf
(
"Password: "
)
var
err
error
secret
,
err
=
passwordPrompt
()
if
err
!=
nil
{
return
nil
,
err
}
fmt
.
Print
(
"
\n
"
)
}
}
else
if
rt
:=
clicontext
.
String
(
"refresh"
);
rt
!=
""
{
secret
=
rt
}
tr
:=
&
http
.
Transport
{
Proxy
:
http
.
ProxyFromEnvironment
,
DialContext
:
(
&
net
.
Dialer
{
Timeout
:
30
*
time
.
Second
,
KeepAlive
:
30
*
time
.
Second
,
DualStack
:
true
,
})
.
DialContext
,
MaxIdleConns
:
10
,
IdleConnTimeout
:
30
*
time
.
Second
,
TLSHandshakeTimeout
:
10
*
time
.
Second
,
TLSClientConfig
:
&
tls
.
Config
{
InsecureSkipVerify
:
clicontext
.
Bool
(
"skip-verify"
),
},
ExpectContinueTimeout
:
5
*
time
.
Second
,
}
options
.
Client
=
&
http
.
Client
{
Transport
:
tr
,
}
credentials
:=
func
(
host
string
)
(
string
,
string
,
error
)
{
// Only one host
return
username
,
secret
,
nil
}
authOpts
:=
[]
docker
.
AuthorizerOpt
{
docker
.
WithAuthClient
(
options
.
Client
),
docker
.
WithAuthCreds
(
credentials
)}
options
.
Authorizer
=
docker
.
NewDockerAuthorizer
(
authOpts
...
)
return
docker
.
NewResolver
(
options
),
nil
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/signals.go
0 → 100644
浏览文件 @
33a410ee
/*
Copyright The containerd 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
commands
import
(
gocontext
"context"
"os"
"os/signal"
"syscall"
"github.com/containerd/containerd"
"github.com/sirupsen/logrus"
)
type
killer
interface
{
Kill
(
gocontext
.
Context
,
syscall
.
Signal
,
...
containerd
.
KillOpts
)
error
}
// ForwardAllSignals forwards signals
func
ForwardAllSignals
(
ctx
gocontext
.
Context
,
task
killer
)
chan
os
.
Signal
{
sigc
:=
make
(
chan
os
.
Signal
,
128
)
signal
.
Notify
(
sigc
)
go
func
()
{
for
s
:=
range
sigc
{
logrus
.
Debug
(
"forwarding signal "
,
s
)
if
err
:=
task
.
Kill
(
ctx
,
s
.
(
syscall
.
Signal
));
err
!=
nil
{
logrus
.
WithError
(
err
)
.
Errorf
(
"forward signal %s"
,
s
)
}
}
}()
return
sigc
}
// StopCatch stops and closes a channel
func
StopCatch
(
sigc
chan
os
.
Signal
)
{
signal
.
Stop
(
sigc
)
close
(
sigc
)
}
shim/vendor/github.com/containerd/containerd/cmd/ctr/commands/utils.go
0 → 100644
浏览文件 @
33a410ee
/*
Copyright The containerd 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
commands
// IntToInt32Array converts an array of int's to int32's
func
IntToInt32Array
(
in
[]
int
)
[]
int32
{
var
ret
[]
int32
for
_
,
v
:=
range
in
{
ret
=
append
(
ret
,
int32
(
v
))
}
return
ret
}
shim/vendor/github.com/containerd/go-runc/monitor.go
浏览文件 @
33a410ee
...
...
@@ -74,3 +74,6 @@ func (m *defaultMonitor) Wait(c *exec.Cmd, ec chan Exit) (int, error) {
e
:=
<-
ec
return
e
.
Status
,
nil
}
shim/vendor/github.com/urfave/cli/.flake8
0 → 100644
浏览文件 @
33a410ee
[flake8]
max-line-length = 120
shim/vendor/github.com/urfave/cli/.gitignore
0 → 100644
浏览文件 @
33a410ee
*.coverprofile
node_modules/
shim/vendor/github.com/urfave/cli/.travis.yml
0 → 100644
浏览文件 @
33a410ee
language
:
go
sudo
:
false
dist
:
trusty
osx_image
:
xcode8.3
go
:
1.8.x
os
:
-
linux
-
osx
cache
:
directories
:
-
node_modules
before_script
:
-
go get github.com/urfave/gfmrun/... ||
true
-
go get golang.org/x/tools/cmd/goimports
-
if [ ! -f node_modules/.bin/markdown-toc ] ; then
npm install markdown-toc ;
fi
script
:
-
./runtests gen
-
./runtests vet
-
./runtests test
-
./runtests gfmrun
-
./runtests toc
shim/vendor/github.com/urfave/cli/CHANGELOG.md
0 → 100644
浏览文件 @
33a410ee
# Change Log
**ATTN**
: This project uses
[
semantic versioning
](
http://semver.org/
)
.
## [Unreleased]
## 1.20.0 - 2017-08-10
### Fixed
*
`HandleExitCoder`
is now correctly iterates over all errors in
a
`MultiError`
. The exit code is the exit code of the last error or
`1`
if
there are no
`ExitCoder`
s in the
`MultiError`
.
*
Fixed YAML file loading on Windows (previously would fail validate the file path)
*
Subcommand
`Usage`
,
`Description`
,
`ArgsUsage`
,
`OnUsageError`
correctly
propogated
*
`ErrWriter`
is now passed downwards through command structure to avoid the
need to redefine it
*
Pass
`Command`
context into
`OnUsageError`
rather than parent context so that
all fields are avaiable
*
Errors occuring in
`Before`
funcs are no longer double printed
*
Use
`UsageText`
in the help templates for commands and subcommands if
defined; otherwise build the usage as before (was previously ignoring this
field)
*
`IsSet`
and
`GlobalIsSet`
now correctly return whether a flag is set if
a program calls
`Set`
or
`GlobalSet`
directly after flag parsing (would
previously only return
`true`
if the flag was set during parsing)
### Changed
*
No longer exit the program on command/subcommand error if the error raised is
not an
`OsExiter`
. This exiting behavior was introduced in 1.19.0, but was
determined to be a regression in functionality. See
[
the
PR
](
https://github.com/urfave/cli/pull/595
)
for discussion.
### Added
*
`CommandsByName`
type was added to make it easy to sort
`Command`
s by name,
alphabetically
*
`altsrc`
now handles loading of string and int arrays from TOML
*
Support for definition of custom help templates for
`App`
via
`CustomAppHelpTemplate`
*
Support for arbitrary key/value fields on
`App`
to be used with
`CustomAppHelpTemplate`
via
`ExtraInfo`
*
`HelpFlag`
,
`VersionFlag`
, and
`BashCompletionFlag`
changed to explictly be
`cli.Flag`
s allowing for the use of custom flags satisfying the
`cli.Flag`
interface to be used.
## [1.19.1] - 2016-11-21
### Fixed
-
Fixes regression introduced in 1.19.0 where using an
`ActionFunc`
as
the
`Action`
for a command would cause it to error rather than calling the
function. Should not have a affected declarative cases using
`func(c
*cli.Context) err)`
.
-
Shell completion now handles the case where the user specifies
`--generate-bash-completion`
immediately after a flag that takes an argument.
Previously it call the application with
`--generate-bash-completion`
as the
flag value.
## [1.19.0] - 2016-11-19
### Added
-
`FlagsByName`
was added to make it easy to sort flags (e.g.
`sort.Sort(cli.FlagsByName(app.Flags))`
)
-
A
`Description`
field was added to
`App`
for a more detailed description of
the application (similar to the existing
`Description`
field on
`Command`
)
-
Flag type code generation via
`go generate`
-
Write to stderr and exit 1 if action returns non-nil error
-
Added support for TOML to the
`altsrc`
loader
-
`SkipArgReorder`
was added to allow users to skip the argument reordering.
This is useful if you want to consider all "flags" after an argument as
arguments rather than flags (the default behavior of the stdlib
`flag`
library). This is backported functionality from the
[
removal of the flag
reordering
](
https://github.com/urfave/cli/pull/398
)
in the unreleased version
2
-
For formatted errors (those implementing
`ErrorFormatter`
), the errors will
be formatted during output. Compatible with
`pkg/errors`
.
### Changed
-
Raise minimum tested/supported Go version to 1.2+
### Fixed
-
Consider empty environment variables as set (previously environment variables
with the equivalent of
`""`
would be skipped rather than their value used).
-
Return an error if the value in a given environment variable cannot be parsed
as the flag type. Previously these errors were silently swallowed.
-
Print full error when an invalid flag is specified (which includes the invalid flag)
-
`App.Writer`
defaults to
`stdout`
when
`nil`
-
If no action is specified on a command or app, the help is now printed instead of
`panic`
ing
-
`App.Metadata`
is initialized automatically now (previously was
`nil`
unless initialized)
-
Correctly show help message if
`-h`
is provided to a subcommand
-
`context.(Global)IsSet`
now respects environment variables. Previously it
would return
`false`
if a flag was specified in the environment rather than
as an argument
-
Removed deprecation warnings to STDERR to avoid them leaking to the end-user
-
`altsrc`
s import paths were updated to use
`gopkg.in/urfave/cli.v1`
. This
fixes issues that occurred when
`gopkg.in/urfave/cli.v1`
was imported as well
as
`altsrc`
where Go would complain that the types didn't match
## [1.18.1] - 2016-08-28
### Fixed
-
Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)
## [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.1] - 2016-08-28
### Fixed
-
Removed deprecation warnings to STDERR to avoid them leaking to the end-user
## [1.17.0] - 2016-05-09
### Added
-
Pluggable flag-level help text rendering via
`cli.DefaultFlagStringFunc`
-
`context.GlobalBoolT`
was added as an analogue to
`context.GlobalBool`
-
Support for hiding commands by setting
`Hidden: true`
-- this will hide the
commands in help output
### Changed
-
`Float64Flag`
,
`IntFlag`
, and
`DurationFlag`
default values are no longer
quoted in help text output.
-
All flag types now include
`(default: {value})`
strings following usage when a
default value can be (reasonably) detected.
-
`IntSliceFlag`
and
`StringSliceFlag`
usage strings are now more consistent
with non-slice flag types
-
Apps now exit with a code of 3 if an unknown subcommand is specified
(previously they printed "No help topic for...", but still exited 0. This
makes it easier to script around apps built using
`cli`
since they can trust
that a 0 exit code indicated a successful execution.
-
cleanups based on
[
Go Report Card
feedback
](
https://goreportcard.com/report/github.com/urfave/cli
)
## [1.16.1] - 2016-08-28
### Fixed
-
Removed deprecation warnings to STDERR to avoid them leaking to the end-user
## [1.16.0] - 2016-05-02
### Added
-
`Hidden`
field on all flag struct types to omit from generated help text
### Changed
-
`BashCompletionFlag`
(
`--enable-bash-completion`
) is now omitted from
generated help text via the
`Hidden`
field
### Fixed
-
handling of error values in
`HandleAction`
and
`HandleExitCoder`
## [1.15.0] - 2016-04-30
### Added
-
This file!
-
Support for placeholders in flag usage strings
-
`App.Metadata`
map for arbitrary data/state management
-
`Set`
and
`GlobalSet`
methods on
`*cli.Context`
for altering values after
parsing.
-
Support for nested lookup of dot-delimited keys in structures loaded from
YAML.
### Changed
-
The
`App.Action`
and
`Command.Action`
now prefer a return signature of
`func(*cli.Context) error`
, as defined by
`cli.ActionFunc`
. If a non-nil
`error`
is returned, there may be two outcomes:
-
If the error fulfills
`cli.ExitCoder`
, then
`os.Exit`
will be called
automatically
-
Else the error is bubbled up and returned from
`App.Run`
-
Specifying an
`Action`
with the legacy return signature of
`func(*cli.Context)`
will produce a deprecation message to stderr
-
Specifying an
`Action`
that is not a
`func`
type will produce a non-zero exit
from
`App.Run`
-
Specifying an
`Action`
func that has an invalid (input) signature will
produce a non-zero exit from
`App.Run`
### Deprecated
-
<a
name=
"deprecated-cli-app-runandexitonerror"
></a>
`cli.App.RunAndExitOnError`
, which should now be done by returning an error
that fulfills
`cli.ExitCoder`
to
`cli.App.Run`
.
-
<a
name=
"deprecated-cli-app-action-signature"
></a>
the legacy signature for
`cli.App.Action`
of
`func(*cli.Context)`
, which should now have a return
signature of
`func(*cli.Context) error`
, as defined by
`cli.ActionFunc`
.
### Fixed
-
Added missing
`*cli.Context.GlobalFloat64`
method
## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
### Added
-
Codebeat badge
-
Support for categorization via
`CategorizedHelp`
and
`Categories`
on app.
### Changed
-
Use
`filepath.Base`
instead of
`path.Base`
in
`Name`
and
`HelpName`
.
### Fixed
-
Ensure version is not shown in help text when
`HideVersion`
set.
## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
### Added
-
YAML file input support.
-
`NArg`
method on context.
## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
### Added
-
Custom usage error handling.
-
Custom text support in
`USAGE`
section of help output.
-
Improved help messages for empty strings.
-
AppVeyor CI configuration.
### Changed
-
Removed
`panic`
from default help printer func.
-
De-duping and optimizations.
### Fixed
-
Correctly handle
`Before`
/
`After`
at command level when no subcommands.
-
Case of literal
`-`
argument causing flag reordering.
-
Environment variable hints on Windows.
-
Docs updates.
## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
### Changed
-
Use
`path.Base`
in
`Name`
and
`HelpName`
-
Export
`GetName`
on flag types.
### Fixed
-
Flag parsing when skipping is enabled.
-
Test output cleanup.
-
Move completion check to account for empty input case.
## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
### Added
-
Destination scan support for flags.
-
Testing against
`tip`
in Travis CI config.
### Changed
-
Go version in Travis CI config.
### Fixed
-
Removed redundant tests.
-
Use correct example naming in tests.
## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
### Fixed
-
Remove unused var in bash completion.
## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
### Added
-
Coverage and reference logos in README.
### Fixed
-
Use specified values in help and version parsing.
-
Only display app version and help message once.
## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
### Added
-
More tests for existing functionality.
-
`ArgsUsage`
at app and command level for help text flexibility.
### Fixed
-
Honor
`HideHelp`
and
`HideVersion`
in
`App.Run`
.
-
Remove juvenile word from README.
## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
### Added
-
`FullName`
on command with accompanying help output update.
-
Set default
`$PROG`
in bash completion.
### Changed
-
Docs formatting.
### Fixed
-
Removed self-referential imports in tests.
## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
### Added
-
Support for
`Copyright`
at app level.
-
`Parent`
func at context level to walk up context lineage.
### Fixed
-
Global flag processing at top level.
## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
### Added
-
Aggregate errors from
`Before`
/
`After`
funcs.
-
Doc comments on flag structs.
-
Include non-global flags when checking version and help.
-
Travis CI config updates.
### Fixed
-
Ensure slice type flags have non-nil values.
-
Collect global flags from the full command hierarchy.
-
Docs prose.
## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
### Changed
-
`HelpPrinter`
signature includes output writer.
### Fixed
-
Specify go 1.1+ in docs.
-
Set
`Writer`
when running command as app.
## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
### Added
-
Multiple author support.
-
`NumFlags`
at context level.
-
`Aliases`
at command level.
### Deprecated
-
`ShortName`
at command level.
### Fixed
-
Subcommand help output.
-
Backward compatible support for deprecated
`Author`
and
`Email`
fields.
-
Docs regarding
`Names`
/
`Aliases`
.
## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
### Added
-
`After`
hook func support at app and command level.
### Fixed
-
Use parsed context when running command as subcommand.
-
Docs prose.
## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
### Added
-
Support for hiding
`-h / --help`
flags, but not
`help`
subcommand.
-
Stop flag parsing after
`--`
.
### Fixed
-
Help text for generic flags to specify single value.
-
Use double quotes in output for defaults.
-
Use
`ParseInt`
instead of
`ParseUint`
for int environment var values.
-
Use
`0`
as base when parsing int environment var values.
## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
### Added
-
Support for environment variable lookup "cascade".
-
Support for
`Stdout`
on app for output redirection.
### Fixed
-
Print command help instead of app help in
`ShowCommandHelp`
.
## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
### Added
-
Docs and example code updates.
### Changed
-
Default
`-v / --version`
flag made optional.
## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
### Added
-
`FlagNames`
at context level.
-
Exposed
`VersionPrinter`
var for more control over version output.
-
Zsh completion hook.
-
`AUTHOR`
section in default app help template.
-
Contribution guidelines.
-
`DurationFlag`
type.
## [1.2.0] - 2014-08-02
### Added
-
Support for environment variable defaults on flags plus tests.
## [1.1.0] - 2014-07-15
### Added
-
Bash completion.
-
Optional hiding of built-in help command.
-
Optional skipping of flag parsing at command level.
-
`Author`
,
`Email`
, and
`Compiled`
metadata on app.
-
`Before`
hook func support at app and command level.
-
`CommandNotFound`
func support at app level.
-
Command reference available on context.
-
`GenericFlag`
type.
-
`Float64Flag`
type.
-
`BoolTFlag`
type.
-
`IsSet`
flag helper on context.
-
More flag lookup funcs at context level.
-
More tests
&
docs.
### Changed
-
Help template updates to account for presence/absence of flags.
-
Separated subcommand help template.
-
Exposed
`HelpPrinter`
var for more control over help output.
## [1.0.0] - 2013-11-01
### Added
-
`help`
flag in default app flag set and each command flag set.
-
Custom handling of argument parsing errors.
-
Command lookup by name at app level.
-
`StringSliceFlag`
type and supporting
`StringSlice`
type.
-
`IntSliceFlag`
type and supporting
`IntSlice`
type.
-
Slice type flag lookups by name at context level.
-
Export of app and command help functions.
-
More tests
&
docs.
## 0.1.0 - 2013-07-22
### Added
-
Initial implementation.
[
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
[
1.14.0
]:
https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
[
1.13.0
]:
https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
[
1.12.0
]:
https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
[
1.11.1
]:
https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
[
1.11.0
]:
https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
[
1.10.2
]:
https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
[
1.10.1
]:
https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
[
1.10.0
]:
https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
[
1.9.0
]:
https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
[
1.8.0
]:
https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
[
1.7.1
]:
https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
[
1.7.0
]:
https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
[
1.6.0
]:
https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
[
1.5.0
]:
https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
[
1.4.1
]:
https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
[
1.4.0
]:
https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
[
1.3.1
]:
https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
[
1.3.0
]:
https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
[
1.2.0
]:
https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
[
1.1.0
]:
https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
[
1.0.0
]:
https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
shim/vendor/github.com/urfave/cli/LICENSE
0 → 100644
浏览文件 @
33a410ee
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:
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.
shim/vendor/github.com/urfave/cli/README.md
0 → 100644
浏览文件 @
33a410ee
此差异已折叠。
点击以展开。
shim/vendor/github.com/urfave/cli/app.go
0 → 100644
浏览文件 @
33a410ee
package
cli
import
(
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"sort"
"time"
)
var
(
changeLogURL
=
"https://github.com/urfave/cli/blob/master/CHANGELOG.md"
appActionDeprecationURL
=
fmt
.
Sprintf
(
"%s#deprecated-cli-app-action-signature"
,
changeLogURL
)
runAndExitOnErrorDeprecationURL
=
fmt
.
Sprintf
(
"%s#deprecated-cli-app-runandexitonerror"
,
changeLogURL
)
contactSysadmin
=
"This is an error in the application. Please contact the distributor of this application if this is not you."
errInvalidActionType
=
NewExitError
(
"ERROR invalid Action type. "
+
fmt
.
Sprintf
(
"Must be `func(*Context`)` or `func(*Context) error). %s"
,
contactSysadmin
)
+
fmt
.
Sprintf
(
"See %s"
,
appActionDeprecationURL
),
2
)
)
// App is the main structure of a cli application. It is recommended that
// an app be created with the cli.NewApp() function
type
App
struct
{
// The name of the program. Defaults to path.Base(os.Args[0])
Name
string
// Full name of command for help, defaults to Name
HelpName
string
// Description of the program.
Usage
string
// Text to override the USAGE section of help
UsageText
string
// Description of the program argument format.
ArgsUsage
string
// Version of the program
Version
string
// Description of the program
Description
string
// List of commands to execute
Commands
[]
Command
// List of flags to parse
Flags
[]
Flag
// Boolean to enable bash completion commands
EnableBashCompletion
bool
// Boolean to hide built-in help command
HideHelp
bool
// Boolean to hide built-in version flag and the VERSION section of help
HideVersion
bool
// Populate on app startup, only gettable through method Categories()
categories
CommandCategories
// An action to execute when the bash-completion flag is set
BashComplete
BashCompleteFunc
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
Before
BeforeFunc
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
After
AfterFunc
// The action to execute when no subcommands are specified
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
// *Note*: support for the deprecated `Action` signature will be removed in a future version
Action
interface
{}
// Execute this function if the proper command cannot be found
CommandNotFound
CommandNotFoundFunc
// Execute this function if an usage error occurs
OnUsageError
OnUsageErrorFunc
// Compilation date
Compiled
time
.
Time
// List of all authors who contributed
Authors
[]
Author
// Copyright of the binary if any
Copyright
string
// Name of Author (Note: Use App.Authors, this is deprecated)
Author
string
// Email of Author (Note: Use App.Authors, this is deprecated)
Email
string
// Writer writer to write output to
Writer
io
.
Writer
// ErrWriter writes error output
ErrWriter
io
.
Writer
// Execute this function to handle ExitErrors. If not provided, HandleExitCoder is provided to
// function as a default, so this is optional.
ExitErrHandler
ExitErrHandlerFunc
// Other custom info
Metadata
map
[
string
]
interface
{}
// Carries a function which returns app specific info.
ExtraInfo
func
()
map
[
string
]
string
// CustomAppHelpTemplate the text template for app help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomAppHelpTemplate
string
didSetup
bool
}
// Tries to find out when this binary was compiled.
// Returns the current time if it fails to find it.
func
compileTime
()
time
.
Time
{
info
,
err
:=
os
.
Stat
(
os
.
Args
[
0
])
if
err
!=
nil
{
return
time
.
Now
()
}
return
info
.
ModTime
()
}
// NewApp creates a new cli Application with some reasonable defaults for Name,
// Usage, Version and Action.
func
NewApp
()
*
App
{
return
&
App
{
Name
:
filepath
.
Base
(
os
.
Args
[
0
]),
HelpName
:
filepath
.
Base
(
os
.
Args
[
0
]),
Usage
:
"A new cli application"
,
UsageText
:
""
,
Version
:
"0.0.0"
,
BashComplete
:
DefaultAppComplete
,
Action
:
helpCommand
.
Action
,
Compiled
:
compileTime
(),
Writer
:
os
.
Stdout
,
}
}
// Setup runs initialization code to ensure all data structures are ready for
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
// will return early if setup has already happened.
func
(
a
*
App
)
Setup
()
{
if
a
.
didSetup
{
return
}
a
.
didSetup
=
true
if
a
.
Author
!=
""
||
a
.
Email
!=
""
{
a
.
Authors
=
append
(
a
.
Authors
,
Author
{
Name
:
a
.
Author
,
Email
:
a
.
Email
})
}
newCmds
:=
[]
Command
{}
for
_
,
c
:=
range
a
.
Commands
{
if
c
.
HelpName
==
""
{
c
.
HelpName
=
fmt
.
Sprintf
(
"%s %s"
,
a
.
HelpName
,
c
.
Name
)
}
newCmds
=
append
(
newCmds
,
c
)
}
a
.
Commands
=
newCmds
if
a
.
Command
(
helpCommand
.
Name
)
==
nil
&&
!
a
.
HideHelp
{
a
.
Commands
=
append
(
a
.
Commands
,
helpCommand
)
if
(
HelpFlag
!=
BoolFlag
{})
{
a
.
appendFlag
(
HelpFlag
)
}
}
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
)
if
a
.
Metadata
==
nil
{
a
.
Metadata
=
make
(
map
[
string
]
interface
{})
}
if
a
.
Writer
==
nil
{
a
.
Writer
=
os
.
Stdout
}
}
// Run is the entry point to the cli app. Parses the arguments slice and routes
// to the proper flag/args combination
func
(
a
*
App
)
Run
(
arguments
[]
string
)
(
err
error
)
{
a
.
Setup
()
// handle the completion flag separately from the flagset since
// completion could be attempted after a flag, but before its value was put
// on the command line. this causes the flagset to interpret the completion
// flag name as the value of the flag before it which is undesirable
// note that we can only do this because the shell autocomplete function
// always appends the completion flag at the end of the command
shellComplete
,
arguments
:=
checkShellCompleteFlag
(
a
,
arguments
)
// parse flags
set
,
err
:=
flagSet
(
a
.
Name
,
a
.
Flags
)
if
err
!=
nil
{
return
err
}
set
.
SetOutput
(
ioutil
.
Discard
)
err
=
set
.
Parse
(
arguments
[
1
:
])
nerr
:=
normalizeFlags
(
a
.
Flags
,
set
)
context
:=
NewContext
(
a
,
set
,
nil
)
if
nerr
!=
nil
{
fmt
.
Fprintln
(
a
.
Writer
,
nerr
)
ShowAppHelp
(
context
)
return
nerr
}
context
.
shellComplete
=
shellComplete
if
checkCompletions
(
context
)
{
return
nil
}
if
err
!=
nil
{
if
a
.
OnUsageError
!=
nil
{
err
:=
a
.
OnUsageError
(
context
,
err
,
false
)
a
.
handleExitCoder
(
context
,
err
)
return
err
}
fmt
.
Fprintf
(
a
.
Writer
,
"%s %s
\n\n
"
,
"Incorrect Usage."
,
err
.
Error
())
ShowAppHelp
(
context
)
return
err
}
if
!
a
.
HideHelp
&&
checkHelp
(
context
)
{
ShowAppHelp
(
context
)
return
nil
}
if
!
a
.
HideVersion
&&
checkVersion
(
context
)
{
ShowVersion
(
context
)
return
nil
}
if
a
.
After
!=
nil
{
defer
func
()
{
if
afterErr
:=
a
.
After
(
context
);
afterErr
!=
nil
{
if
err
!=
nil
{
err
=
NewMultiError
(
err
,
afterErr
)
}
else
{
err
=
afterErr
}
}
}()
}
if
a
.
Before
!=
nil
{
beforeErr
:=
a
.
Before
(
context
)
if
beforeErr
!=
nil
{
fmt
.
Fprintf
(
a
.
Writer
,
"%v
\n\n
"
,
beforeErr
)
ShowAppHelp
(
context
)
a
.
handleExitCoder
(
context
,
beforeErr
)
err
=
beforeErr
return
err
}
}
args
:=
context
.
Args
()
if
args
.
Present
()
{
name
:=
args
.
First
()
c
:=
a
.
Command
(
name
)
if
c
!=
nil
{
return
c
.
Run
(
context
)
}
}
if
a
.
Action
==
nil
{
a
.
Action
=
helpCommand
.
Action
}
// Run default Action
err
=
HandleAction
(
a
.
Action
,
context
)
a
.
handleExitCoder
(
context
,
err
)
return
err
}
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
// to cli.App.Run. This will cause the application to exit with the given eror
// code in the cli.ExitCoder
func
(
a
*
App
)
RunAndExitOnError
()
{
if
err
:=
a
.
Run
(
os
.
Args
);
err
!=
nil
{
fmt
.
Fprintln
(
a
.
errWriter
(),
err
)
OsExiter
(
1
)
}
}
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
// generate command-specific flags
func
(
a
*
App
)
RunAsSubcommand
(
ctx
*
Context
)
(
err
error
)
{
// append help to commands
if
len
(
a
.
Commands
)
>
0
{
if
a
.
Command
(
helpCommand
.
Name
)
==
nil
&&
!
a
.
HideHelp
{
a
.
Commands
=
append
(
a
.
Commands
,
helpCommand
)
if
(
HelpFlag
!=
BoolFlag
{})
{
a
.
appendFlag
(
HelpFlag
)
}
}
}
newCmds
:=
[]
Command
{}
for
_
,
c
:=
range
a
.
Commands
{
if
c
.
HelpName
==
""
{
c
.
HelpName
=
fmt
.
Sprintf
(
"%s %s"
,
a
.
HelpName
,
c
.
Name
)
}
newCmds
=
append
(
newCmds
,
c
)
}
a
.
Commands
=
newCmds
// parse flags
set
,
err
:=
flagSet
(
a
.
Name
,
a
.
Flags
)
if
err
!=
nil
{
return
err
}
set
.
SetOutput
(
ioutil
.
Discard
)
err
=
set
.
Parse
(
ctx
.
Args
()
.
Tail
())
nerr
:=
normalizeFlags
(
a
.
Flags
,
set
)
context
:=
NewContext
(
a
,
set
,
ctx
)
if
nerr
!=
nil
{
fmt
.
Fprintln
(
a
.
Writer
,
nerr
)
fmt
.
Fprintln
(
a
.
Writer
)
if
len
(
a
.
Commands
)
>
0
{
ShowSubcommandHelp
(
context
)
}
else
{
ShowCommandHelp
(
ctx
,
context
.
Args
()
.
First
())
}
return
nerr
}
if
checkCompletions
(
context
)
{
return
nil
}
if
err
!=
nil
{
if
a
.
OnUsageError
!=
nil
{
err
=
a
.
OnUsageError
(
context
,
err
,
true
)
a
.
handleExitCoder
(
context
,
err
)
return
err
}
fmt
.
Fprintf
(
a
.
Writer
,
"%s %s
\n\n
"
,
"Incorrect Usage."
,
err
.
Error
())
ShowSubcommandHelp
(
context
)
return
err
}
if
len
(
a
.
Commands
)
>
0
{
if
checkSubcommandHelp
(
context
)
{
return
nil
}
}
else
{
if
checkCommandHelp
(
ctx
,
context
.
Args
()
.
First
())
{
return
nil
}
}
if
a
.
After
!=
nil
{
defer
func
()
{
afterErr
:=
a
.
After
(
context
)
if
afterErr
!=
nil
{
a
.
handleExitCoder
(
context
,
err
)
if
err
!=
nil
{
err
=
NewMultiError
(
err
,
afterErr
)
}
else
{
err
=
afterErr
}
}
}()
}
if
a
.
Before
!=
nil
{
beforeErr
:=
a
.
Before
(
context
)
if
beforeErr
!=
nil
{
a
.
handleExitCoder
(
context
,
beforeErr
)
err
=
beforeErr
return
err
}
}
args
:=
context
.
Args
()
if
args
.
Present
()
{
name
:=
args
.
First
()
c
:=
a
.
Command
(
name
)
if
c
!=
nil
{
return
c
.
Run
(
context
)
}
}
// Run default Action
err
=
HandleAction
(
a
.
Action
,
context
)
a
.
handleExitCoder
(
context
,
err
)
return
err
}
// Command returns the named command on App. Returns nil if the command does not exist
func
(
a
*
App
)
Command
(
name
string
)
*
Command
{
for
_
,
c
:=
range
a
.
Commands
{
if
c
.
HasName
(
name
)
{
return
&
c
}
}
return
nil
}
// Categories returns a slice containing all the categories with the commands they contain
func
(
a
*
App
)
Categories
()
CommandCategories
{
return
a
.
categories
}
// VisibleCategories returns a slice of categories and commands that are
// Hidden=false
func
(
a
*
App
)
VisibleCategories
()
[]
*
CommandCategory
{
ret
:=
[]
*
CommandCategory
{}
for
_
,
category
:=
range
a
.
categories
{
if
visible
:=
func
()
*
CommandCategory
{
for
_
,
command
:=
range
category
.
Commands
{
if
!
command
.
Hidden
{
return
category
}
}
return
nil
}();
visible
!=
nil
{
ret
=
append
(
ret
,
visible
)
}
}
return
ret
}
// VisibleCommands returns a slice of the Commands with Hidden=false
func
(
a
*
App
)
VisibleCommands
()
[]
Command
{
ret
:=
[]
Command
{}
for
_
,
command
:=
range
a
.
Commands
{
if
!
command
.
Hidden
{
ret
=
append
(
ret
,
command
)
}
}
return
ret
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func
(
a
*
App
)
VisibleFlags
()
[]
Flag
{
return
visibleFlags
(
a
.
Flags
)
}
func
(
a
*
App
)
hasFlag
(
flag
Flag
)
bool
{
for
_
,
f
:=
range
a
.
Flags
{
if
flag
==
f
{
return
true
}
}
return
false
}
func
(
a
*
App
)
errWriter
()
io
.
Writer
{
// When the app ErrWriter is nil use the package level one.
if
a
.
ErrWriter
==
nil
{
return
ErrWriter
}
return
a
.
ErrWriter
}
func
(
a
*
App
)
appendFlag
(
flag
Flag
)
{
if
!
a
.
hasFlag
(
flag
)
{
a
.
Flags
=
append
(
a
.
Flags
,
flag
)
}
}
func
(
a
*
App
)
handleExitCoder
(
context
*
Context
,
err
error
)
{
if
a
.
ExitErrHandler
!=
nil
{
a
.
ExitErrHandler
(
context
,
err
)
}
else
{
HandleExitCoder
(
err
)
}
}
// Author represents someone who has contributed to a cli project.
type
Author
struct
{
Name
string
// The Authors name
Email
string
// The Authors email
}
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
func
(
a
Author
)
String
()
string
{
e
:=
""
if
a
.
Email
!=
""
{
e
=
" <"
+
a
.
Email
+
">"
}
return
fmt
.
Sprintf
(
"%v%v"
,
a
.
Name
,
e
)
}
// HandleAction attempts to figure out which Action signature was used. If
// it's an ActionFunc or a func with the legacy signature for Action, the func
// is run!
func
HandleAction
(
action
interface
{},
context
*
Context
)
(
err
error
)
{
if
a
,
ok
:=
action
.
(
ActionFunc
);
ok
{
return
a
(
context
)
}
else
if
a
,
ok
:=
action
.
(
func
(
*
Context
)
error
);
ok
{
return
a
(
context
)
}
else
if
a
,
ok
:=
action
.
(
func
(
*
Context
));
ok
{
// deprecated function signature
a
(
context
)
return
nil
}
return
errInvalidActionType
}
shim/vendor/github.com/urfave/cli/appveyor.yml
0 → 100644
浏览文件 @
33a410ee
version
:
"
{build}"
os
:
Windows Server
2016
image
:
Visual Studio
2017
clone_folder
:
c:\gopath\src\github.com\urfave\cli
environment
:
GOPATH
:
C:\gopath
GOVERSION
:
1.8.x
PYTHON
:
C:\Python36-x64
PYTHON_VERSION
:
3.6.x
PYTHON_ARCH
:
64
install
:
-
set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
-
go version
-
go env
-
go get github.com/urfave/gfmrun/...
-
go get -v -t ./...
build_script
:
-
python runtests vet
-
python runtests test
-
python runtests gfmrun
shim/vendor/github.com/urfave/cli/category.go
0 → 100644
浏览文件 @
33a410ee
package
cli
// CommandCategories is a slice of *CommandCategory.
type
CommandCategories
[]
*
CommandCategory
// CommandCategory is a category containing commands.
type
CommandCategory
struct
{
Name
string
Commands
Commands
}
func
(
c
CommandCategories
)
Less
(
i
,
j
int
)
bool
{
return
c
[
i
]
.
Name
<
c
[
j
]
.
Name
}
func
(
c
CommandCategories
)
Len
()
int
{
return
len
(
c
)
}
func
(
c
CommandCategories
)
Swap
(
i
,
j
int
)
{
c
[
i
],
c
[
j
]
=
c
[
j
],
c
[
i
]
}
// AddCommand adds a command to a category.
func
(
c
CommandCategories
)
AddCommand
(
category
string
,
command
Command
)
CommandCategories
{
for
_
,
commandCategory
:=
range
c
{
if
commandCategory
.
Name
==
category
{
commandCategory
.
Commands
=
append
(
commandCategory
.
Commands
,
command
)
return
c
}
}
return
append
(
c
,
&
CommandCategory
{
Name
:
category
,
Commands
:
[]
Command
{
command
}})
}
// VisibleCommands returns a slice of the Commands with Hidden=false
func
(
c
*
CommandCategory
)
VisibleCommands
()
[]
Command
{
ret
:=
[]
Command
{}
for
_
,
command
:=
range
c
.
Commands
{
if
!
command
.
Hidden
{
ret
=
append
(
ret
,
command
)
}
}
return
ret
}
shim/vendor/github.com/urfave/cli/cli.go
0 → 100644
浏览文件 @
33a410ee
// Package cli provides a minimal framework for creating and organizing command line
// Go applications. cli is designed to be easy to understand and write, the most simple
// cli application can be written as follows:
// func main() {
// cli.NewApp().Run(os.Args)
// }
//
// Of course this application does not do much, so let's make this an actual application:
// func main() {
// app := cli.NewApp()
// app.Name = "greet"
// app.Usage = "say a greeting"
// app.Action = func(c *cli.Context) error {
// println("Greetings")
// return nil
// }
//
// app.Run(os.Args)
// }
package
cli
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
shim/vendor/github.com/urfave/cli/command.go
0 → 100644
浏览文件 @
33a410ee
package
cli
import
(
"fmt"
"io/ioutil"
"sort"
"strings"
)
// Command is a subcommand for a cli.App.
type
Command
struct
{
// The name of the command
Name
string
// short name of the command. Typically one character (deprecated, use `Aliases`)
ShortName
string
// A list of aliases for the command
Aliases
[]
string
// A short description of the usage of this command
Usage
string
// Custom text to show on USAGE section of help
UsageText
string
// A longer explanation of how the command works
Description
string
// A short description of the arguments of this command
ArgsUsage
string
// The category the command is part of
Category
string
// The function to call when checking for bash command completions
BashComplete
BashCompleteFunc
// An action to execute before any sub-subcommands are run, but after the context is ready
// If a non-nil error is returned, no sub-subcommands are run
Before
BeforeFunc
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
After
AfterFunc
// The function to call when this command is invoked
Action
interface
{}
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
// of deprecation period has passed, maybe?
// Execute this function if a usage error occurs.
OnUsageError
OnUsageErrorFunc
// List of child commands
Subcommands
Commands
// List of flags to parse
Flags
[]
Flag
// Treat all flags as normal arguments if true
SkipFlagParsing
bool
// Skip argument reordering which attempts to move flags before arguments,
// but only works if all flags appear after all arguments. This behavior was
// removed n version 2 since it only works under specific conditions so we
// backport here by exposing it as an option for compatibility.
SkipArgReorder
bool
// Boolean to hide built-in help command
HideHelp
bool
// Boolean to hide this command from help or completion
Hidden
bool
// Full name of command for help, defaults to full command name, including parent commands.
HelpName
string
commandNamePath
[]
string
// CustomHelpTemplate the text template for the command help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomHelpTemplate
string
}
type
CommandsByName
[]
Command
func
(
c
CommandsByName
)
Len
()
int
{
return
len
(
c
)
}
func
(
c
CommandsByName
)
Less
(
i
,
j
int
)
bool
{
return
c
[
i
]
.
Name
<
c
[
j
]
.
Name
}
func
(
c
CommandsByName
)
Swap
(
i
,
j
int
)
{
c
[
i
],
c
[
j
]
=
c
[
j
],
c
[
i
]
}
// FullName returns the full name of the command.
// For subcommands this ensures that parent commands are part of the command path
func
(
c
Command
)
FullName
()
string
{
if
c
.
commandNamePath
==
nil
{
return
c
.
Name
}
return
strings
.
Join
(
c
.
commandNamePath
,
" "
)
}
// Commands is a slice of Command
type
Commands
[]
Command
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
func
(
c
Command
)
Run
(
ctx
*
Context
)
(
err
error
)
{
if
len
(
c
.
Subcommands
)
>
0
{
return
c
.
startApp
(
ctx
)
}
if
!
c
.
HideHelp
&&
(
HelpFlag
!=
BoolFlag
{})
{
// append help to flags
c
.
Flags
=
append
(
c
.
Flags
,
HelpFlag
,
)
}
set
,
err
:=
flagSet
(
c
.
Name
,
c
.
Flags
)
if
err
!=
nil
{
return
err
}
set
.
SetOutput
(
ioutil
.
Discard
)
if
c
.
SkipFlagParsing
{
err
=
set
.
Parse
(
append
([]
string
{
"--"
},
ctx
.
Args
()
.
Tail
()
...
))
}
else
if
!
c
.
SkipArgReorder
{
firstFlagIndex
:=
-
1
terminatorIndex
:=
-
1
for
index
,
arg
:=
range
ctx
.
Args
()
{
if
arg
==
"--"
{
terminatorIndex
=
index
break
}
else
if
arg
==
"-"
{
// Do nothing. A dash alone is not really a flag.
continue
}
else
if
strings
.
HasPrefix
(
arg
,
"-"
)
&&
firstFlagIndex
==
-
1
{
firstFlagIndex
=
index
}
}
if
firstFlagIndex
>
-
1
{
args
:=
ctx
.
Args
()
regularArgs
:=
make
([]
string
,
len
(
args
[
1
:
firstFlagIndex
]))
copy
(
regularArgs
,
args
[
1
:
firstFlagIndex
])
var
flagArgs
[]
string
if
terminatorIndex
>
-
1
{
flagArgs
=
args
[
firstFlagIndex
:
terminatorIndex
]
regularArgs
=
append
(
regularArgs
,
args
[
terminatorIndex
:
]
...
)
}
else
{
flagArgs
=
args
[
firstFlagIndex
:
]
}
err
=
set
.
Parse
(
append
(
flagArgs
,
regularArgs
...
))
}
else
{
err
=
set
.
Parse
(
ctx
.
Args
()
.
Tail
())
}
}
else
{
err
=
set
.
Parse
(
ctx
.
Args
()
.
Tail
())
}
nerr
:=
normalizeFlags
(
c
.
Flags
,
set
)
if
nerr
!=
nil
{
fmt
.
Fprintln
(
ctx
.
App
.
Writer
,
nerr
)
fmt
.
Fprintln
(
ctx
.
App
.
Writer
)
ShowCommandHelp
(
ctx
,
c
.
Name
)
return
nerr
}
context
:=
NewContext
(
ctx
.
App
,
set
,
ctx
)
context
.
Command
=
c
if
checkCommandCompletions
(
context
,
c
.
Name
)
{
return
nil
}
if
err
!=
nil
{
if
c
.
OnUsageError
!=
nil
{
err
:=
c
.
OnUsageError
(
context
,
err
,
false
)
context
.
App
.
handleExitCoder
(
context
,
err
)
return
err
}
fmt
.
Fprintln
(
context
.
App
.
Writer
,
"Incorrect Usage:"
,
err
.
Error
())
fmt
.
Fprintln
(
context
.
App
.
Writer
)
ShowCommandHelp
(
context
,
c
.
Name
)
return
err
}
if
checkCommandHelp
(
context
,
c
.
Name
)
{
return
nil
}
if
c
.
After
!=
nil
{
defer
func
()
{
afterErr
:=
c
.
After
(
context
)
if
afterErr
!=
nil
{
context
.
App
.
handleExitCoder
(
context
,
err
)
if
err
!=
nil
{
err
=
NewMultiError
(
err
,
afterErr
)
}
else
{
err
=
afterErr
}
}
}()
}
if
c
.
Before
!=
nil
{
err
=
c
.
Before
(
context
)
if
err
!=
nil
{
ShowCommandHelp
(
context
,
c
.
Name
)
context
.
App
.
handleExitCoder
(
context
,
err
)
return
err
}
}
if
c
.
Action
==
nil
{
c
.
Action
=
helpSubcommand
.
Action
}
err
=
HandleAction
(
c
.
Action
,
context
)
if
err
!=
nil
{
context
.
App
.
handleExitCoder
(
context
,
err
)
}
return
err
}
// Names returns the names including short names and aliases.
func
(
c
Command
)
Names
()
[]
string
{
names
:=
[]
string
{
c
.
Name
}
if
c
.
ShortName
!=
""
{
names
=
append
(
names
,
c
.
ShortName
)
}
return
append
(
names
,
c
.
Aliases
...
)
}
// HasName returns true if Command.Name or Command.ShortName matches given name
func
(
c
Command
)
HasName
(
name
string
)
bool
{
for
_
,
n
:=
range
c
.
Names
()
{
if
n
==
name
{
return
true
}
}
return
false
}
func
(
c
Command
)
startApp
(
ctx
*
Context
)
error
{
app
:=
NewApp
()
app
.
Metadata
=
ctx
.
App
.
Metadata
// set the name and usage
app
.
Name
=
fmt
.
Sprintf
(
"%s %s"
,
ctx
.
App
.
Name
,
c
.
Name
)
if
c
.
HelpName
==
""
{
app
.
HelpName
=
c
.
HelpName
}
else
{
app
.
HelpName
=
app
.
Name
}
app
.
Usage
=
c
.
Usage
app
.
Description
=
c
.
Description
app
.
ArgsUsage
=
c
.
ArgsUsage
// set CommandNotFound
app
.
CommandNotFound
=
ctx
.
App
.
CommandNotFound
app
.
CustomAppHelpTemplate
=
c
.
CustomHelpTemplate
// set the flags and commands
app
.
Commands
=
c
.
Subcommands
app
.
Flags
=
c
.
Flags
app
.
HideHelp
=
c
.
HideHelp
app
.
Version
=
ctx
.
App
.
Version
app
.
HideVersion
=
ctx
.
App
.
HideVersion
app
.
Compiled
=
ctx
.
App
.
Compiled
app
.
Author
=
ctx
.
App
.
Author
app
.
Email
=
ctx
.
App
.
Email
app
.
Writer
=
ctx
.
App
.
Writer
app
.
ErrWriter
=
ctx
.
App
.
ErrWriter
app
.
categories
=
CommandCategories
{}
for
_
,
command
:=
range
c
.
Subcommands
{
app
.
categories
=
app
.
categories
.
AddCommand
(
command
.
Category
,
command
)
}
sort
.
Sort
(
app
.
categories
)
// bash completion
app
.
EnableBashCompletion
=
ctx
.
App
.
EnableBashCompletion
if
c
.
BashComplete
!=
nil
{
app
.
BashComplete
=
c
.
BashComplete
}
// set the actions
app
.
Before
=
c
.
Before
app
.
After
=
c
.
After
if
c
.
Action
!=
nil
{
app
.
Action
=
c
.
Action
}
else
{
app
.
Action
=
helpSubcommand
.
Action
}
app
.
OnUsageError
=
c
.
OnUsageError
for
index
,
cc
:=
range
app
.
Commands
{
app
.
Commands
[
index
]
.
commandNamePath
=
[]
string
{
c
.
Name
,
cc
.
Name
}
}
return
app
.
RunAsSubcommand
(
ctx
)
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func
(
c
Command
)
VisibleFlags
()
[]
Flag
{
return
visibleFlags
(
c
.
Flags
)
}
shim/vendor/github.com/urfave/cli/context.go
0 → 100644
浏览文件 @
33a410ee
package
cli
import
(
"errors"
"flag"
"reflect"
"strings"
"syscall"
)
// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type
Context
struct
{
App
*
App
Command
Command
shellComplete
bool
flagSet
*
flag
.
FlagSet
setFlags
map
[
string
]
bool
parentContext
*
Context
}
// NewContext creates a new context. For use in when invoking an App or Command action.
func
NewContext
(
app
*
App
,
set
*
flag
.
FlagSet
,
parentCtx
*
Context
)
*
Context
{
c
:=
&
Context
{
App
:
app
,
flagSet
:
set
,
parentContext
:
parentCtx
}
if
parentCtx
!=
nil
{
c
.
shellComplete
=
parentCtx
.
shellComplete
}
return
c
}
// NumFlags returns the number of flags set
func
(
c
*
Context
)
NumFlags
()
int
{
return
c
.
flagSet
.
NFlag
()
}
// Set sets a context flag to a value.
func
(
c
*
Context
)
Set
(
name
,
value
string
)
error
{
c
.
setFlags
=
nil
return
c
.
flagSet
.
Set
(
name
,
value
)
}
// GlobalSet sets a context flag to a value on the global flagset
func
(
c
*
Context
)
GlobalSet
(
name
,
value
string
)
error
{
globalContext
(
c
)
.
setFlags
=
nil
return
globalContext
(
c
)
.
flagSet
.
Set
(
name
,
value
)
}
// IsSet determines if the flag was actually set
func
(
c
*
Context
)
IsSet
(
name
string
)
bool
{
if
c
.
setFlags
==
nil
{
c
.
setFlags
=
make
(
map
[
string
]
bool
)
c
.
flagSet
.
Visit
(
func
(
f
*
flag
.
Flag
)
{
c
.
setFlags
[
f
.
Name
]
=
true
})
c
.
flagSet
.
VisitAll
(
func
(
f
*
flag
.
Flag
)
{
if
_
,
ok
:=
c
.
setFlags
[
f
.
Name
];
ok
{
return
}
c
.
setFlags
[
f
.
Name
]
=
false
})
// XXX hack to support IsSet for flags with EnvVar
//
// There isn't an easy way to do this with the current implementation since
// whether a flag was set via an environment variable is very difficult to
// determine here. Instead, we intend to introduce a backwards incompatible
// change in version 2 to add `IsSet` to the Flag interface to push the
// responsibility closer to where the information required to determine
// whether a flag is set by non-standard means such as environment
// variables is available.
//
// See https://github.com/urfave/cli/issues/294 for additional discussion
flags
:=
c
.
Command
.
Flags
if
c
.
Command
.
Name
==
""
{
// cannot == Command{} since it contains slice types
if
c
.
App
!=
nil
{
flags
=
c
.
App
.
Flags
}
}
for
_
,
f
:=
range
flags
{
eachName
(
f
.
GetName
(),
func
(
name
string
)
{
if
isSet
,
ok
:=
c
.
setFlags
[
name
];
isSet
||
!
ok
{
return
}
val
:=
reflect
.
ValueOf
(
f
)
if
val
.
Kind
()
==
reflect
.
Ptr
{
val
=
val
.
Elem
()
}
envVarValue
:=
val
.
FieldByName
(
"EnvVar"
)
if
!
envVarValue
.
IsValid
()
{
return
}
eachName
(
envVarValue
.
String
(),
func
(
envVar
string
)
{
envVar
=
strings
.
TrimSpace
(
envVar
)
if
_
,
ok
:=
syscall
.
Getenv
(
envVar
);
ok
{
c
.
setFlags
[
name
]
=
true
return
}
})
})
}
}
return
c
.
setFlags
[
name
]
}
// GlobalIsSet determines if the global flag was actually set
func
(
c
*
Context
)
GlobalIsSet
(
name
string
)
bool
{
ctx
:=
c
if
ctx
.
parentContext
!=
nil
{
ctx
=
ctx
.
parentContext
}
for
;
ctx
!=
nil
;
ctx
=
ctx
.
parentContext
{
if
ctx
.
IsSet
(
name
)
{
return
true
}
}
return
false
}
// FlagNames returns a slice of flag names used in this context.
func
(
c
*
Context
)
FlagNames
()
(
names
[]
string
)
{
for
_
,
flag
:=
range
c
.
Command
.
Flags
{
name
:=
strings
.
Split
(
flag
.
GetName
(),
","
)[
0
]
if
name
==
"help"
{
continue
}
names
=
append
(
names
,
name
)
}
return
}
// GlobalFlagNames returns a slice of global flag names used by the app.
func
(
c
*
Context
)
GlobalFlagNames
()
(
names
[]
string
)
{
for
_
,
flag
:=
range
c
.
App
.
Flags
{
name
:=
strings
.
Split
(
flag
.
GetName
(),
","
)[
0
]
if
name
==
"help"
||
name
==
"version"
{
continue
}
names
=
append
(
names
,
name
)
}
return
}
// Parent returns the parent context, if any
func
(
c
*
Context
)
Parent
()
*
Context
{
return
c
.
parentContext
}
// value returns the value of the flag coressponding to `name`
func
(
c
*
Context
)
value
(
name
string
)
interface
{}
{
return
c
.
flagSet
.
Lookup
(
name
)
.
Value
.
(
flag
.
Getter
)
.
Get
()
}
// Args contains apps console arguments
type
Args
[]
string
// Args returns the command line arguments associated with the context.
func
(
c
*
Context
)
Args
()
Args
{
args
:=
Args
(
c
.
flagSet
.
Args
())
return
args
}
// NArg returns the number of the command line arguments.
func
(
c
*
Context
)
NArg
()
int
{
return
len
(
c
.
Args
())
}
// Get returns the nth argument, or else a blank string
func
(
a
Args
)
Get
(
n
int
)
string
{
if
len
(
a
)
>
n
{
return
a
[
n
]
}
return
""
}
// First returns the first argument, or else a blank string
func
(
a
Args
)
First
()
string
{
return
a
.
Get
(
0
)
}
// Tail returns the rest of the arguments (not the first one)
// or else an empty string slice
func
(
a
Args
)
Tail
()
[]
string
{
if
len
(
a
)
>=
2
{
return
[]
string
(
a
)[
1
:
]
}
return
[]
string
{}
}
// Present checks if there are any arguments present
func
(
a
Args
)
Present
()
bool
{
return
len
(
a
)
!=
0
}
// Swap swaps arguments at the given indexes
func
(
a
Args
)
Swap
(
from
,
to
int
)
error
{
if
from
>=
len
(
a
)
||
to
>=
len
(
a
)
{
return
errors
.
New
(
"index out of range"
)
}
a
[
from
],
a
[
to
]
=
a
[
to
],
a
[
from
]
return
nil
}
func
globalContext
(
ctx
*
Context
)
*
Context
{
if
ctx
==
nil
{
return
nil
}
for
{
if
ctx
.
parentContext
==
nil
{
return
ctx
}
ctx
=
ctx
.
parentContext
}
}
func
lookupGlobalFlagSet
(
name
string
,
ctx
*
Context
)
*
flag
.
FlagSet
{
if
ctx
.
parentContext
!=
nil
{
ctx
=
ctx
.
parentContext
}
for
;
ctx
!=
nil
;
ctx
=
ctx
.
parentContext
{
if
f
:=
ctx
.
flagSet
.
Lookup
(
name
);
f
!=
nil
{
return
ctx
.
flagSet
}
}
return
nil
}
func
copyFlag
(
name
string
,
ff
*
flag
.
Flag
,
set
*
flag
.
FlagSet
)
{
switch
ff
.
Value
.
(
type
)
{
case
*
StringSlice
:
default
:
set
.
Set
(
name
,
ff
.
Value
.
String
())
}
}
func
normalizeFlags
(
flags
[]
Flag
,
set
*
flag
.
FlagSet
)
error
{
visited
:=
make
(
map
[
string
]
bool
)
set
.
Visit
(
func
(
f
*
flag
.
Flag
)
{
visited
[
f
.
Name
]
=
true
})
for
_
,
f
:=
range
flags
{
parts
:=
strings
.
Split
(
f
.
GetName
(),
","
)
if
len
(
parts
)
==
1
{
continue
}
var
ff
*
flag
.
Flag
for
_
,
name
:=
range
parts
{
name
=
strings
.
Trim
(
name
,
" "
)
if
visited
[
name
]
{
if
ff
!=
nil
{
return
errors
.
New
(
"Cannot use two forms of the same flag: "
+
name
+
" "
+
ff
.
Name
)
}
ff
=
set
.
Lookup
(
name
)
}
}
if
ff
==
nil
{
continue
}
for
_
,
name
:=
range
parts
{
name
=
strings
.
Trim
(
name
,
" "
)
if
!
visited
[
name
]
{
copyFlag
(
name
,
ff
,
set
)
}
}
}
return
nil
}
shim/vendor/github.com/urfave/cli/errors.go
0 → 100644
浏览文件 @
33a410ee
package
cli
import
(
"fmt"
"io"
"os"
"strings"
)
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
var
OsExiter
=
os
.
Exit
// ErrWriter is used to write errors to the user. This can be anything
// implementing the io.Writer interface and defaults to os.Stderr.
var
ErrWriter
io
.
Writer
=
os
.
Stderr
// MultiError is an error that wraps multiple errors.
type
MultiError
struct
{
Errors
[]
error
}
// NewMultiError creates a new MultiError. Pass in one or more errors.
func
NewMultiError
(
err
...
error
)
MultiError
{
return
MultiError
{
Errors
:
err
}
}
// Error implements the error interface.
func
(
m
MultiError
)
Error
()
string
{
errs
:=
make
([]
string
,
len
(
m
.
Errors
))
for
i
,
err
:=
range
m
.
Errors
{
errs
[
i
]
=
err
.
Error
()
}
return
strings
.
Join
(
errs
,
"
\n
"
)
}
type
ErrorFormatter
interface
{
Format
(
s
fmt
.
State
,
verb
rune
)
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type
ExitCoder
interface
{
error
ExitCode
()
int
}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type
ExitError
struct
{
exitCode
int
message
interface
{}
}
// NewExitError makes a new *ExitError
func
NewExitError
(
message
interface
{},
exitCode
int
)
*
ExitError
{
return
&
ExitError
{
exitCode
:
exitCode
,
message
:
message
,
}
}
// Error returns the string message, fulfilling the interface required by
// `error`
func
(
ee
*
ExitError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"%v"
,
ee
.
message
)
}
// ExitCode returns the exit code, fulfilling the interface required by
// `ExitCoder`
func
(
ee
*
ExitError
)
ExitCode
()
int
{
return
ee
.
exitCode
}
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
// given exit code. If the given error is a MultiError, then this func is
// called on all members of the Errors slice and calls OsExiter with the last exit code.
func
HandleExitCoder
(
err
error
)
{
if
err
==
nil
{
return
}
if
exitErr
,
ok
:=
err
.
(
ExitCoder
);
ok
{
if
err
.
Error
()
!=
""
{
if
_
,
ok
:=
exitErr
.
(
ErrorFormatter
);
ok
{
fmt
.
Fprintf
(
ErrWriter
,
"%+v
\n
"
,
err
)
}
else
{
fmt
.
Fprintln
(
ErrWriter
,
err
)
}
}
OsExiter
(
exitErr
.
ExitCode
())
return
}
if
multiErr
,
ok
:=
err
.
(
MultiError
);
ok
{
code
:=
handleMultiError
(
multiErr
)
OsExiter
(
code
)
return
}
}
func
handleMultiError
(
multiErr
MultiError
)
int
{
code
:=
1
for
_
,
merr
:=
range
multiErr
.
Errors
{
if
multiErr2
,
ok
:=
merr
.
(
MultiError
);
ok
{
code
=
handleMultiError
(
multiErr2
)
}
else
{
fmt
.
Fprintln
(
ErrWriter
,
merr
)
if
exitErr
,
ok
:=
merr
.
(
ExitCoder
);
ok
{
code
=
exitErr
.
ExitCode
()
}
}
}
return
code
}
shim/vendor/github.com/urfave/cli/flag-types.json
0 → 100644
浏览文件 @
33a410ee
[
{
"name"
:
"Bool"
,
"type"
:
"bool"
,
"value"
:
false
,
"context_default"
:
"false"
,
"parser"
:
"strconv.ParseBool(f.Value.String())"
},
{
"name"
:
"BoolT"
,
"type"
:
"bool"
,
"value"
:
false
,
"doctail"
:
" that is true by default"
,
"context_default"
:
"false"
,
"parser"
:
"strconv.ParseBool(f.Value.String())"
},
{
"name"
:
"Duration"
,
"type"
:
"time.Duration"
,
"doctail"
:
" (see https://golang.org/pkg/time/#ParseDuration)"
,
"context_default"
:
"0"
,
"parser"
:
"time.ParseDuration(f.Value.String())"
},
{
"name"
:
"Float64"
,
"type"
:
"float64"
,
"context_default"
:
"0"
,
"parser"
:
"strconv.ParseFloat(f.Value.String(), 64)"
},
{
"name"
:
"Generic"
,
"type"
:
"Generic"
,
"dest"
:
false
,
"context_default"
:
"nil"
,
"context_type"
:
"interface{}"
},
{
"name"
:
"Int64"
,
"type"
:
"int64"
,
"context_default"
:
"0"
,
"parser"
:
"strconv.ParseInt(f.Value.String(), 0, 64)"
},
{
"name"
:
"Int"
,
"type"
:
"int"
,
"context_default"
:
"0"
,
"parser"
:
"strconv.ParseInt(f.Value.String(), 0, 64)"
,
"parser_cast"
:
"int(parsed)"
},
{
"name"
:
"IntSlice"
,
"type"
:
"*IntSlice"
,
"dest"
:
false
,
"context_default"
:
"nil"
,
"context_type"
:
"[]int"
,
"parser"
:
"(f.Value.(*IntSlice)).Value(), error(nil)"
},
{
"name"
:
"Int64Slice"
,
"type"
:
"*Int64Slice"
,
"dest"
:
false
,
"context_default"
:
"nil"
,
"context_type"
:
"[]int64"
,
"parser"
:
"(f.Value.(*Int64Slice)).Value(), error(nil)"
},
{
"name"
:
"String"
,
"type"
:
"string"
,
"context_default"
:
"
\"\"
"
,
"parser"
:
"f.Value.String(), error(nil)"
},
{
"name"
:
"StringSlice"
,
"type"
:
"*StringSlice"
,
"dest"
:
false
,
"context_default"
:
"nil"
,
"context_type"
:
"[]string"
,
"parser"
:
"(f.Value.(*StringSlice)).Value(), error(nil)"
},
{
"name"
:
"Uint64"
,
"type"
:
"uint64"
,
"context_default"
:
"0"
,
"parser"
:
"strconv.ParseUint(f.Value.String(), 0, 64)"
},
{
"name"
:
"Uint"
,
"type"
:
"uint"
,
"context_default"
:
"0"
,
"parser"
:
"strconv.ParseUint(f.Value.String(), 0, 64)"
,
"parser_cast"
:
"uint(parsed)"
}
]
shim/vendor/github.com/urfave/cli/flag.go
0 → 100644
浏览文件 @
33a410ee
此差异已折叠。
点击以展开。
shim/vendor/github.com/urfave/cli/flag_generated.go
0 → 100644
浏览文件 @
33a410ee
此差异已折叠。
点击以展开。
shim/vendor/github.com/urfave/cli/funcs.go
0 → 100644
浏览文件 @
33a410ee
package
cli
// BashCompleteFunc is an action to execute when the bash-completion flag is set
type
BashCompleteFunc
func
(
*
Context
)
// BeforeFunc is an action to execute before any subcommands are run, but after
// the context is ready if a non-nil error is returned, no subcommands are run
type
BeforeFunc
func
(
*
Context
)
error
// AfterFunc is an action to execute after any subcommands are run, but after the
// subcommand has finished it is run even if Action() panics
type
AfterFunc
func
(
*
Context
)
error
// ActionFunc is the action to execute when no subcommands are specified
type
ActionFunc
func
(
*
Context
)
error
// CommandNotFoundFunc is executed if the proper command cannot be found
type
CommandNotFoundFunc
func
(
*
Context
,
string
)
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
// customized usage error messages. This function is able to replace the
// original error messages. If this function is not set, the "Incorrect usage"
// is displayed and the execution is interrupted.
type
OnUsageErrorFunc
func
(
context
*
Context
,
err
error
,
isSubcommand
bool
)
error
// ExitErrHandlerFunc is executed if provided in order to handle ExitError values
// returned by Actions and Before/After functions.
type
ExitErrHandlerFunc
func
(
context
*
Context
,
err
error
)
// FlagStringFunc is used by the help generation to display a flag, which is
// expected to be a single line.
type
FlagStringFunc
func
(
Flag
)
string
// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix
// text for a flag's full name.
type
FlagNamePrefixFunc
func
(
fullName
,
placeholder
string
)
string
// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help
// with the environment variable details.
type
FlagEnvHintFunc
func
(
envVar
,
str
string
)
string
shim/vendor/github.com/urfave/cli/generate-flag-types
0 → 100644
浏览文件 @
33a410ee
#
!/usr/bin/env python
"""
The flag types that ship with the cli library have many things in common, and
so we can take advantage of the `go generate` command to create much of the
source code from a list of definitions. These definitions attempt to cover
the parts that vary between flag types, and should evolve as needed.
An example of the minimum definition needed is:
{
"
name
": "
SomeType
",
"
type
": "
sometype
",
"
context_default
": "
nil
"
}
In this example, the code generated for the `cli` package will include a type
named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
Fetching values by name via `*cli.Context` will default to a value of `nil`.
A more complete, albeit somewhat redundant, example showing all available
definition keys is:
{
"
name
": "
VeryMuchType
",
"
type
": "
*
VeryMuchType
",
"
value
": true,
"
dest
": false,
"
doctail
": "
which
really
only
wraps
a
[]
float64
,
oh
well
!",
"context_type"
:
"[]float64"
,
"context_default"
:
"nil"
,
"parser"
:
"parseVeryMuchType(f.Value.String())"
,
"parser_cast"
:
"[]float64(parsed)"
}
The
meaning
of
each
field
is
as
follows
:
name
(
string
)
-
The
type
"name"
,
which
will
be
suffixed
with
`
Flag
`
when
generating
the
type
definition
for
`
cli
`
and
the
wrapper
type
for
`
altsrc
`
type
(
string
)
-
The
type
that
the
generated
`
Flag
`
type
for
`
cli
`
is
expected
to
"contain"
as
its
`.
Value
`
member
value
(
bool
)
-
Should
the
generated
`
cli
`
type
have
a
`
Value
`
member
?
dest
(
bool
)
-
Should
the
generated
`
cli
`
type
support
a
destination
pointer
?
doctail
(
string
)
-
Additional
docs
for
the
`
cli
`
flag
type
comment
context_type
(
string
)
-
The
literal
type
used
in
the
`*
cli
.
Context
`
reader
func
signature
context_default
(
string
)
-
The
literal
value
used
as
the
default
by
the
`*
cli
.
Context
`
reader
funcs
when
no
value
is
present
parser
(
string
)
-
Literal
code
used
to
parse
the
flag
`
f
`,
expected
to
have
a
return
signature
of
(
value
,
error
)
parser_cast
(
string
)
-
Literal
code
used
to
cast
the
`
parsed
`
value
returned
from
the
`
parser
`
code
"""
from __future__ import print_function, unicode_literals
import argparse
import json
import os
import subprocess
import sys
import tempfile
import textwrap
class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
argparse.RawDescriptionHelpFormatter):
pass
def main(sysargs=sys.argv[:]):
parser = argparse.ArgumentParser(
description='Generate flag type code!',
formatter_class=_FancyFormatter)
parser.add_argument(
'package',
type=str, default='cli', choices=_WRITEFUNCS.keys(),
help='Package for which flag types will be generated'
)
parser.add_argument(
'-i', '--in-json',
type=argparse.FileType('r'),
default=sys.stdin,
help='Input JSON file which defines each type to be generated'
)
parser.add_argument(
'-o', '--out-go',
type=argparse.FileType('w'),
default=sys.stdout,
help='Output file/stream to which generated source will be written'
)
parser.epilog = __doc__
args = parser.parse_args(sysargs[1:])
_generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
return 0
def _generate_flag_types(writefunc, output_go, input_json):
types = json.load(input_json)
tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False)
writefunc(tmp, types)
tmp.close()
new_content = subprocess.check_output(
['goimports', tmp.name]
).decode('utf-8')
print(new_content, file=output_go, end='')
output_go.flush()
os.remove(tmp.name)
def _set_typedef_defaults(typedef):
typedef.setdefault('doctail', '')
typedef.setdefault('context_type', typedef['type'])
typedef.setdefault('dest', True)
typedef.setdefault('value', True)
typedef.setdefault('parser', 'f.Value, error(nil)')
typedef.setdefault('parser_cast', 'parsed')
def _write_cli_flag_types(outfile, types):
_fwrite(outfile, """
\
package
cli
//
WARNING
:
This
file
is
generated
!
""")
for typedef in types:
_set_typedef_defaults(typedef)
_fwrite(outfile, """
\
//
{
name
}
Flag
is
a
flag
with
type
{
type
}{
doctail
}
type
{
name
}
Flag
struct
{{
Name
string
Usage
string
EnvVar
string
Hidden
bool
""".format(**typedef))
if typedef['value']:
_fwrite(outfile, """
\
Value
{
type
}
""".format(**typedef))
if typedef['dest']:
_fwrite(outfile, """
\
Destination
*{
type
}
""".format(**typedef))
_fwrite(outfile, "
\
n
}\
n
\
n
")
_fwrite(outfile, """
\
//
String
returns
a
readable
representation
of
this
value
//
(
for
usage
defaults
)
func
(
f
{
name
}
Flag
)
String
()
string
{{
return
FlagStringer
(
f
)
}}
//
GetName
returns
the
name
of
the
flag
func
(
f
{
name
}
Flag
)
GetName
()
string
{{
return
f
.
Name
}}
//
{
name
}
looks
up
the
value
of
a
local
{
name
}
Flag
,
returns
//
{
context_default
}
if
not
found
func
(
c
*
Context
)
{
name
}(
name
string
)
{
context_type
}
{{
return
lookup
{
name
}(
name
,
c
.
flagSet
)
}}
//
Global
{
name
}
looks
up
the
value
of
a
global
{
name
}
Flag
,
returns
//
{
context_default
}
if
not
found
func
(
c
*
Context
)
Global
{
name
}(
name
string
)
{
context_type
}
{{
if
fs
:=
lookupGlobalFlagSet
(
name
,
c
);
fs
!= nil {{
return
lookup
{
name
}(
name
,
fs
)
}}
return
{
context_default
}
}}
func
lookup
{
name
}(
name
string
,
set
*
flag
.
FlagSet
)
{
context_type
}
{{
f
:=
set
.
Lookup
(
name
)
if
f
!= nil {{
parsed
,
err
:=
{
parser
}
if
err
!= nil {{
return
{
context_default
}
}}
return
{
parser_cast
}
}}
return
{
context_default
}
}}
""".format(**typedef))
def _write_altsrc_flag_types(outfile, types):
_fwrite(outfile, """
\
package
altsrc
import
(
"gopkg.in/urfave/cli.v1"
)
//
WARNING
:
This
file
is
generated
!
""")
for typedef in types:
_set_typedef_defaults(typedef)
_fwrite(outfile, """
\
//
{
name
}
Flag
is
the
flag
type
that
wraps
cli
.{
name
}
Flag
to
allow
//
for
other
values
to
be
specified
type
{
name
}
Flag
struct
{{
cli
.{
name
}
Flag
set
*
flag
.
FlagSet
}}
//
New
{
name
}
Flag
creates
a
new
{
name
}
Flag
func
New
{
name
}
Flag
(
fl
cli
.{
name
}
Flag
)
*{
name
}
Flag
{{
return
&{
name
}
Flag
{{{
name
}
Flag
:
fl
,
set
:
nil
}}
}}
//
Apply
saves
the
flagSet
for
later
usage
calls
,
then
calls
the
//
wrapped
{
name
}
Flag
.
Apply
func
(
f
*{
name
}
Flag
)
Apply
(
set
*
flag
.
FlagSet
)
{{
f
.
set
=
set
f
.{
name
}
Flag
.
Apply
(
set
)
}}
//
ApplyWithError
saves
the
flagSet
for
later
usage
calls
,
then
calls
the
//
wrapped
{
name
}
Flag
.
ApplyWithError
func
(
f
*{
name
}
Flag
)
ApplyWithError
(
set
*
flag
.
FlagSet
)
error
{{
f
.
set
=
set
return
f
.{
name
}
Flag
.
ApplyWithError
(
set
)
}}
""".format(**typedef))
def _fwrite(outfile, text):
print(textwrap.dedent(text), end='', file=outfile)
_WRITEFUNCS = {
'cli': _write_cli_flag_types,
'altsrc': _write_altsrc_flag_types
}
if __name__ == '__main__':
sys.exit(main())
shim/vendor/github.com/urfave/cli/help.go
0 → 100644
浏览文件 @
33a410ee
此差异已折叠。
点击以展开。
shim/vendor/github.com/urfave/cli/runtests
0 → 100644
浏览文件 @
33a410ee
此差异已折叠。
点击以展开。
shim/vendor/modules.txt
浏览文件 @
33a410ee
...
...
@@ -47,6 +47,7 @@ github.com/containerd/containerd/api/types/task
github.com/containerd/containerd/archive
github.com/containerd/containerd/archive/compression
github.com/containerd/containerd/cio
github.com/containerd/containerd/cmd/ctr/commands
github.com/containerd/containerd/containers
github.com/containerd/containerd/content
github.com/containerd/containerd/content/proxy
...
...
@@ -189,6 +190,8 @@ github.com/stretchr/testify/assert
github.com/syndtr/gocapability/capability
# github.com/ugorji/go/codec v1.1.7
github.com/ugorji/go/codec
# github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5
github.com/urfave/cli
# go.opencensus.io v0.22.0
go.opencensus.io
go.opencensus.io/internal
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录