fake.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2019 the Kilo 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 iptables
  15. import (
  16. "fmt"
  17. "strings"
  18. "sync/atomic"
  19. "github.com/coreos/go-iptables/iptables"
  20. )
  21. type statusExiter interface {
  22. ExitStatus() int
  23. }
  24. var _ statusExiter = (*iptables.Error)(nil)
  25. var _ statusExiter = statusError(0)
  26. type statusError int
  27. func (s statusError) Error() string {
  28. return fmt.Sprintf("%d", s)
  29. }
  30. func (s statusError) ExitStatus() int {
  31. return int(s)
  32. }
  33. type fakeClient struct {
  34. calls uint64
  35. storage []Rule
  36. }
  37. var _ Client = &fakeClient{}
  38. func (f *fakeClient) AppendUnique(table, chain string, spec ...string) error {
  39. atomic.AddUint64(&f.calls, 1)
  40. exists, err := f.Exists(table, chain, spec...)
  41. if err != nil {
  42. return err
  43. }
  44. if exists {
  45. return nil
  46. }
  47. f.storage = append(f.storage, &rule{table: table, chain: chain, spec: spec})
  48. return nil
  49. }
  50. func (f *fakeClient) Delete(table, chain string, spec ...string) error {
  51. atomic.AddUint64(&f.calls, 1)
  52. r := &rule{table: table, chain: chain, spec: spec}
  53. for i := range f.storage {
  54. if f.storage[i].String() == r.String() {
  55. copy(f.storage[i:], f.storage[i+1:])
  56. f.storage[len(f.storage)-1] = nil
  57. f.storage = f.storage[:len(f.storage)-1]
  58. break
  59. }
  60. }
  61. return nil
  62. }
  63. func (f *fakeClient) Exists(table, chain string, spec ...string) (bool, error) {
  64. atomic.AddUint64(&f.calls, 1)
  65. r := &rule{table: table, chain: chain, spec: spec}
  66. for i := range f.storage {
  67. if f.storage[i].String() == r.String() {
  68. return true, nil
  69. }
  70. }
  71. return false, nil
  72. }
  73. func (f *fakeClient) List(table, chain string) ([]string, error) {
  74. atomic.AddUint64(&f.calls, 1)
  75. var rs []string
  76. for i := range f.storage {
  77. switch r := f.storage[i].(type) {
  78. case *rule:
  79. if r.table == table && r.chain == chain {
  80. rs = append(rs, strings.TrimSpace(strings.TrimPrefix(r.String(), table)))
  81. }
  82. }
  83. }
  84. return rs, nil
  85. }
  86. func (f *fakeClient) ClearChain(table, name string) error {
  87. atomic.AddUint64(&f.calls, 1)
  88. for i := range f.storage {
  89. r, ok := f.storage[i].(*rule)
  90. if !ok {
  91. continue
  92. }
  93. if table == r.table && name == r.chain {
  94. if err := f.Delete(table, name, r.spec...); err != nil {
  95. return nil
  96. }
  97. }
  98. }
  99. if err := f.DeleteChain(table, name); err != nil {
  100. return err
  101. }
  102. return f.NewChain(table, name)
  103. }
  104. func (f *fakeClient) DeleteChain(table, name string) error {
  105. atomic.AddUint64(&f.calls, 1)
  106. for i := range f.storage {
  107. r, ok := f.storage[i].(*rule)
  108. if !ok {
  109. continue
  110. }
  111. if table == r.table && name == r.chain {
  112. return fmt.Errorf("cannot delete chain %s; rules exist", name)
  113. }
  114. }
  115. c := &chain{table: table, chain: name}
  116. for i := range f.storage {
  117. if f.storage[i].String() == c.String() {
  118. copy(f.storage[i:], f.storage[i+1:])
  119. f.storage[len(f.storage)-1] = nil
  120. f.storage = f.storage[:len(f.storage)-1]
  121. break
  122. }
  123. }
  124. return nil
  125. }
  126. func (f *fakeClient) NewChain(table, name string) error {
  127. atomic.AddUint64(&f.calls, 1)
  128. c := &chain{table: table, chain: name}
  129. for i := range f.storage {
  130. if f.storage[i].String() == c.String() {
  131. return statusError(1)
  132. }
  133. }
  134. f.storage = append(f.storage, c)
  135. return nil
  136. }
  137. func (f *fakeClient) ListChains(table string) ([]string, error) {
  138. atomic.AddUint64(&f.calls, 1)
  139. var cs []string
  140. for i := range f.storage {
  141. switch c := f.storage[i].(type) {
  142. case *chain:
  143. if c.table == table {
  144. cs = append(cs, c.chain)
  145. }
  146. }
  147. }
  148. return cs, nil
  149. }