args.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright 2015 CNI authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package invoke
  15. import (
  16. "fmt"
  17. "os"
  18. "strings"
  19. )
  20. type CNIArgs interface {
  21. // For use with os/exec; i.e., return nil to inherit the
  22. // environment from this process
  23. // For use in delegation; inherit the environment from this
  24. // process and allow overrides
  25. AsEnv() []string
  26. }
  27. type inherited struct{}
  28. var inheritArgsFromEnv inherited
  29. func (_ *inherited) AsEnv() []string {
  30. return nil
  31. }
  32. func ArgsFromEnv() CNIArgs {
  33. return &inheritArgsFromEnv
  34. }
  35. type Args struct {
  36. Command string
  37. ContainerID string
  38. NetNS string
  39. PluginArgs [][2]string
  40. PluginArgsStr string
  41. IfName string
  42. Path string
  43. }
  44. // Args implements the CNIArgs interface
  45. var _ CNIArgs = &Args{}
  46. func (args *Args) AsEnv() []string {
  47. env := os.Environ()
  48. pluginArgsStr := args.PluginArgsStr
  49. if pluginArgsStr == "" {
  50. pluginArgsStr = stringify(args.PluginArgs)
  51. }
  52. // Duplicated values which come first will be overrided, so we must put the
  53. // custom values in the end to avoid being overrided by the process environments.
  54. env = append(env,
  55. "CNI_COMMAND="+args.Command,
  56. "CNI_CONTAINERID="+args.ContainerID,
  57. "CNI_NETNS="+args.NetNS,
  58. "CNI_ARGS="+pluginArgsStr,
  59. "CNI_IFNAME="+args.IfName,
  60. "CNI_PATH="+args.Path,
  61. )
  62. return dedupEnv(env)
  63. }
  64. // taken from rkt/networking/net_plugin.go
  65. func stringify(pluginArgs [][2]string) string {
  66. entries := make([]string, len(pluginArgs))
  67. for i, kv := range pluginArgs {
  68. entries[i] = strings.Join(kv[:], "=")
  69. }
  70. return strings.Join(entries, ";")
  71. }
  72. // DelegateArgs implements the CNIArgs interface
  73. // used for delegation to inherit from environments
  74. // and allow some overrides like CNI_COMMAND
  75. var _ CNIArgs = &DelegateArgs{}
  76. type DelegateArgs struct {
  77. Command string
  78. }
  79. func (d *DelegateArgs) AsEnv() []string {
  80. env := os.Environ()
  81. // The custom values should come in the end to override the existing
  82. // process environment of the same key.
  83. env = append(env,
  84. "CNI_COMMAND="+d.Command,
  85. )
  86. return dedupEnv(env)
  87. }
  88. // dedupEnv returns a copy of env with any duplicates removed, in favor of later values.
  89. // Items not of the normal environment "key=value" form are preserved unchanged.
  90. func dedupEnv(env []string) []string {
  91. out := make([]string, 0, len(env))
  92. envMap := map[string]string{}
  93. for _, kv := range env {
  94. // find the first "=" in environment, if not, just keep it
  95. eq := strings.Index(kv, "=")
  96. if eq < 0 {
  97. out = append(out, kv)
  98. continue
  99. }
  100. envMap[kv[:eq]] = kv[eq+1:]
  101. }
  102. for k, v := range envMap {
  103. out = append(out, fmt.Sprintf("%s=%s", k, v))
  104. }
  105. return out
  106. }