github.com/form3tech-oss/cilium@v1.6.3/daemon/state_test.go (about) 1 // Copyright 2016-2019 Authors of Cilium 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 15 // +build !privileged_tests 16 17 package main 18 19 import ( 20 "context" 21 "encoding/binary" 22 "fmt" 23 "io/ioutil" 24 "net" 25 "os" 26 "path/filepath" 27 "sort" 28 "sync" 29 30 "github.com/cilium/cilium/common/addressing" 31 "github.com/cilium/cilium/pkg/checker" 32 "github.com/cilium/cilium/pkg/completion" 33 linuxDatapath "github.com/cilium/cilium/pkg/datapath/linux" 34 e "github.com/cilium/cilium/pkg/endpoint" 35 "github.com/cilium/cilium/pkg/endpoint/regeneration" 36 "github.com/cilium/cilium/pkg/identity" 37 "github.com/cilium/cilium/pkg/identity/identitymanager" 38 "github.com/cilium/cilium/pkg/labels" 39 "github.com/cilium/cilium/pkg/lock" 40 "github.com/cilium/cilium/pkg/mac" 41 monitorAPI "github.com/cilium/cilium/pkg/monitor/api" 42 "github.com/cilium/cilium/pkg/option" 43 "github.com/cilium/cilium/pkg/policy" 44 "github.com/cilium/cilium/pkg/revert" 45 46 . "gopkg.in/check.v1" 47 ) 48 49 func (ds *DaemonSuite) createEndpoints() ([]*e.Endpoint, map[uint16]*e.Endpoint) { 50 epsWanted := []*e.Endpoint{ 51 ds.endpointCreator(256, identity.NumericIdentity(1256)), 52 ds.endpointCreator(257, identity.NumericIdentity(1257)), 53 ds.endpointCreator(258, identity.NumericIdentity(1258)), 54 ds.endpointCreator(259, identity.NumericIdentity(1259)), 55 } 56 epsMap := map[uint16]*e.Endpoint{ 57 epsWanted[0].ID: epsWanted[0], 58 epsWanted[1].ID: epsWanted[1], 59 epsWanted[2].ID: epsWanted[2], 60 epsWanted[3].ID: epsWanted[3], 61 } 62 return epsWanted, epsMap 63 } 64 65 func getStrID(id uint16) string { 66 return fmt.Sprintf("%05d", id) 67 } 68 69 func (ds *DaemonSuite) endpointCreator(id uint16, secID identity.NumericIdentity) *e.Endpoint { 70 strID := getStrID(id) 71 b := make([]byte, 2) 72 binary.LittleEndian.PutUint16(b, id) 73 74 identity := &identity.Identity{ 75 ID: secID, 76 Labels: labels.Labels{ 77 "foo" + strID: labels.NewLabel("foo"+strID, "", ""), 78 }, 79 } 80 identity.Sanitize() 81 82 repo := ds.d.GetPolicyRepository() 83 repo.GetPolicyCache().LocalEndpointIdentityAdded(identity) 84 85 ep := e.NewEndpointWithState(ds.d, id, e.StateReady) 86 // Random network ID and docker endpoint ID with 59 hex chars + 5 strID = 64 hex chars 87 ep.DockerNetworkID = "603e047d2268a57f5a5f93f7f9e1263e9207e348a06654bf64948def001" + strID 88 ep.DockerEndpointID = "93529fda8c401a071d21d6bd46fdf5499b9014dcb5a35f2e3efaa8d8002" + strID 89 ep.IfName = "lxc" + strID 90 ep.LXCMAC = mac.MAC([]byte{0x01, 0xff, 0xf2, 0x12, b[0], b[1]}) 91 ep.IPv4 = addressing.DeriveCiliumIPv4(net.IP{0xc0, 0xa8, b[0], b[1]}) 92 ep.IPv6 = addressing.DeriveCiliumIPv6(net.IP{0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, b[0], b[1]}) 93 ep.IfIndex = 1 94 ep.SetNodeMACLocked(mac.MAC([]byte{0x02, 0xff, 0xf2, 0x12, 0x0, 0x0})) 95 ep.SecurityIdentity = identity 96 ep.OpLabels = labels.NewOpLabels() 97 return ep 98 } 99 100 // generateEPs is a helper function to create dummy endpoints in the given 101 // baseDirectory. This function regenerates the endpoints and creates the bpf 102 // and header files in the endpoint's directory 103 func (ds *DaemonSuite) generateEPs(baseDir string, epsWanted []*e.Endpoint, epsMap map[uint16]*e.Endpoint) ([]string, error) { 104 var err error 105 defer func() { 106 if err != nil { 107 os.RemoveAll(baseDir) 108 } 109 }() 110 111 ds.d.compilationMutex = new(lock.RWMutex) 112 113 builders := 0 114 defer func() { 115 if builders != 0 { 116 log.Fatal("Endpoint Build Queue leaks") 117 } 118 }() 119 120 ds.OnQueueEndpointBuild = func(ctx context.Context, epID uint64) (func(), error) { 121 builders++ 122 var once sync.Once 123 doneFunc := func() { 124 once.Do(func() { 125 builders-- 126 }) 127 } 128 return doneFunc, nil 129 } 130 131 ds.OnTracingEnabled = func() bool { 132 return false 133 } 134 ds.OnGetPolicyRepository = func() *policy.Repository { 135 return ds.d.GetPolicyRepository() 136 } 137 ds.OnAlwaysAllowLocalhost = func() bool { 138 return false 139 } 140 141 ds.OnGetCompilationLock = func() *lock.RWMutex { 142 return ds.d.compilationMutex 143 } 144 145 ds.OnSendNotification = func(typ monitorAPI.AgentNotification, text string) error { 146 return nil 147 } 148 149 ds.OnUpdateNetworkPolicy = func(e regeneration.EndpointUpdater, policy *policy.L4Policy, 150 proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc) { 151 return nil, nil 152 } 153 154 ds.OnRemoveNetworkPolicy = func(e regeneration.EndpointInfoSource) {} 155 156 // Since all owner's funcs are implemented we can regenerate every endpoint. 157 epsNames := []string{} 158 for _, ep := range epsWanted { 159 fullDirName := filepath.Join(baseDir, ep.DirectoryPath()) 160 os.MkdirAll(fullDirName, 777) 161 ep.UnconditionalLock() 162 163 // The identities must be tracked in identitymanager to 164 // regenerate the policy for them. 165 identitymanager.Add(ep.SecurityIdentity) 166 defer identitymanager.Remove(ep.SecurityIdentity) 167 168 ready := ep.SetStateLocked(e.StateWaitingToRegenerate, "test") 169 ep.Unlock() 170 if ready { 171 <-ep.Regenerate(regenerationMetadata) 172 } 173 174 switch ep.ID { 175 case 256, 257: 176 err := os.Rename(fullDirName, filepath.Join(baseDir, ep.FailedDirectoryPath())) 177 if err != nil { 178 return nil, err 179 } 180 epsNames = append(epsNames, ep.FailedDirectoryPath()) 181 182 // create one failed and the other non failed directory for ep 256. 183 if ep.ID == 256 { 184 fullDirName := filepath.Join(baseDir, ep.DirectoryPath()) 185 os.MkdirAll(fullDirName, 777) 186 187 ep.UnconditionalLock() 188 // Change endpoint a little bit so we know which endpoint is in 189 // "256_next_fail" and with one is in the "256" directory. 190 ep.SetNodeMACLocked(mac.MAC([]byte{0x02, 0xff, 0xf2, 0x12, 0xc1, 0xc1})) 191 ready := ep.SetStateLocked(e.StateWaitingToRegenerate, "test") 192 ep.Unlock() 193 if ready { 194 <-ep.Regenerate(regenerationMetadata) 195 } 196 epsNames = append(epsNames, ep.DirectoryPath()) 197 } 198 default: 199 epsNames = append(epsNames, ep.DirectoryPath()) 200 } 201 } 202 return epsNames, nil 203 } 204 205 func (ds *DaemonSuite) TestReadEPsFromDirNames(c *C) { 206 // For this test, the real linux datapath is necessary to properly 207 // serialize config files to disk and test the restore. 208 oldDatapath := ds.d.datapath 209 defer func() { 210 ds.d.datapath = oldDatapath 211 }() 212 ds.d.datapath = linuxDatapath.NewDatapath(linuxDatapath.DatapathConfiguration{}, nil) 213 214 epsWanted, epsMap := ds.createEndpoints() 215 tmpDir, err := ioutil.TempDir("", "cilium-tests") 216 defer func() { 217 os.RemoveAll(tmpDir) 218 }() 219 220 os.Chdir(tmpDir) 221 222 oldStateDir := option.Config.StateDir 223 option.Config.StateDir = tmpDir 224 defer func() { 225 os.Chdir(oldStateDir) 226 option.Config.StateDir = oldStateDir 227 }() 228 c.Assert(err, IsNil) 229 epsNames, err := ds.generateEPs(tmpDir, epsWanted, epsMap) 230 c.Assert(err, IsNil) 231 eps := e.ReadEPsFromDirNames(ds.d, tmpDir, epsNames) 232 c.Assert(len(eps), Equals, len(epsWanted)) 233 234 sort.Slice(epsWanted, func(i, j int) bool { return epsWanted[i].ID < epsWanted[j].ID }) 235 var restoredEPs []*e.Endpoint 236 for _, ep := range eps { 237 restoredEPs = append(restoredEPs, ep) 238 } 239 sort.Slice(restoredEPs, func(i, j int) bool { return restoredEPs[i].ID < restoredEPs[j].ID }) 240 241 c.Assert(len(restoredEPs), Equals, len(epsWanted)) 242 for i, restoredEP := range restoredEPs { 243 // We probably shouldn't modify these, but the status will 244 // naturally differ between the wanted endpoint and the version 245 // that's restored, because the restored version has log 246 // messages relating to the restore. 247 restoredEP.Status = nil 248 wanted := epsWanted[i] 249 wanted.Status = nil 250 c.Assert(restoredEP.String(), checker.DeepEquals, wanted.String()) 251 } 252 }