| // Copyright 2020 The Monogon Project Authors. |
| // |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // 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 memory |
| |
| import ( |
| "context" |
| "fmt" |
| "net" |
| "time" |
| ) |
| |
| // NetworkStatus is example data that will be stored in a Value. |
| type NetworkStatus struct { |
| ExternalAddress net.IP |
| DefaultGateway net.IP |
| } |
| |
| // NetworkService is a fake/example network service that is responsible for |
| // communicating the newest information about a machine's network configuration |
| // to consumers/watchers. |
| type NetworkService struct { |
| Provider Value[NetworkStatus] |
| } |
| |
| // Run pretends to execute the network service's main logic loop, in which it |
| // pretends to have received an IP address over DHCP, and communicates that to |
| // consumers/watchers. |
| func (s *NetworkService) Run(ctx context.Context) { |
| s.Provider.Set(NetworkStatus{ |
| ExternalAddress: nil, |
| DefaultGateway: nil, |
| }) |
| |
| select { |
| case <-time.After(100 * time.Millisecond): |
| case <-ctx.Done(): |
| return |
| } |
| |
| fmt.Printf("NS: Got DHCP Lease\n") |
| s.Provider.Set(NetworkStatus{ |
| ExternalAddress: net.ParseIP("203.0.113.24"), |
| DefaultGateway: net.ParseIP("203.0.113.1"), |
| }) |
| |
| select { |
| case <-time.After(100 * time.Millisecond): |
| case <-ctx.Done(): |
| return |
| } |
| |
| fmt.Printf("NS: DHCP Address changed\n") |
| s.Provider.Set(NetworkStatus{ |
| ExternalAddress: net.ParseIP("203.0.113.103"), |
| DefaultGateway: net.ParseIP("203.0.113.1"), |
| }) |
| |
| time.Sleep(100 * time.Millisecond) |
| } |
| |
| // ExampleValue_full demonstrates a typical usecase for Event Values, in which |
| // a mock network service lets watchers know that the machine on which the code |
| // is running has received a new network configuration. |
| // It also shows the typical boilerplate required in order to wrap a Value (eg. |
| // MemoryValue) within a typesafe wrapper. |
| func ExampleValue_full() { |
| ctx, ctxC := context.WithCancel(context.Background()) |
| defer ctxC() |
| |
| // Create a fake NetworkService. |
| ns := NetworkService{} |
| |
| // Run an /etc/hosts updater. It will watch for updates from the NetworkService |
| // about the current IP address of the node. |
| go func() { |
| w := ns.Provider.Watch() |
| for { |
| status, err := w.Get(ctx) |
| if err != nil { |
| break |
| } |
| if status.ExternalAddress == nil { |
| continue |
| } |
| // Pretend to write /etc/hosts with the newest ExternalAddress. |
| // In production code, you would also check for whether ExternalAddress has |
| // changed from the last written value, if writing to /etc/hosts is expensive. |
| fmt.Printf("/etc/hosts: foo.example.com is now %s\n", status.ExternalAddress.String()) |
| } |
| }() |
| |
| // Run fake network service. |
| ns.Run(ctx) |
| |
| // Output: |
| // NS: Got DHCP Lease |
| // /etc/hosts: foo.example.com is now 203.0.113.24 |
| // NS: DHCP Address changed |
| // /etc/hosts: foo.example.com is now 203.0.113.103 |
| } |