blob: 583650ca2bf47cc647a6cd8075a8bfc412dffcbf [file] [log] [blame]
Serge Bazanskic00318e2021-03-03 12:39:24 +01001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020017package memory
Serge Bazanskic00318e2021-03-03 12:39:24 +010018
19import (
20 "context"
21 "fmt"
22 "net"
23 "time"
24)
25
26// NetworkStatus is example data that will be stored in a Value.
27type NetworkStatus struct {
28 ExternalAddress net.IP
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020029 DefaultGateway net.IP
Serge Bazanskic00318e2021-03-03 12:39:24 +010030}
31
Serge Bazanskic00318e2021-03-03 12:39:24 +010032// NetworkService is a fake/example network service that is responsible for
33// communicating the newest information about a machine's network configuration
34// to consumers/watchers.
35type NetworkService struct {
Serge Bazanski37110c32023-03-01 13:57:27 +000036 Provider Value[NetworkStatus]
Serge Bazanskic00318e2021-03-03 12:39:24 +010037}
38
39// Run pretends to execute the network service's main logic loop, in which it
40// pretends to have received an IP address over DHCP, and communicates that to
41// consumers/watchers.
42func (s *NetworkService) Run(ctx context.Context) {
43 s.Provider.Set(NetworkStatus{
44 ExternalAddress: nil,
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020045 DefaultGateway: nil,
Serge Bazanskic00318e2021-03-03 12:39:24 +010046 })
47
48 select {
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020049 case <-time.After(100 * time.Millisecond):
Serge Bazanskic00318e2021-03-03 12:39:24 +010050 case <-ctx.Done():
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020051 return
Serge Bazanskic00318e2021-03-03 12:39:24 +010052 }
53
54 fmt.Printf("NS: Got DHCP Lease\n")
55 s.Provider.Set(NetworkStatus{
56 ExternalAddress: net.ParseIP("203.0.113.24"),
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020057 DefaultGateway: net.ParseIP("203.0.113.1"),
Serge Bazanskic00318e2021-03-03 12:39:24 +010058 })
59
60 select {
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020061 case <-time.After(100 * time.Millisecond):
Serge Bazanskic00318e2021-03-03 12:39:24 +010062 case <-ctx.Done():
63 return
64 }
65
66 fmt.Printf("NS: DHCP Address changed\n")
67 s.Provider.Set(NetworkStatus{
68 ExternalAddress: net.ParseIP("203.0.113.103"),
Serge Bazanski68ca5ee2021-04-27 16:09:16 +020069 DefaultGateway: net.ParseIP("203.0.113.1"),
Serge Bazanskic00318e2021-03-03 12:39:24 +010070 })
71
72 time.Sleep(100 * time.Millisecond)
73}
74
75// ExampleValue_full demonstrates a typical usecase for Event Values, in which
76// a mock network service lets watchers know that the machine on which the code
77// is running has received a new network configuration.
78// It also shows the typical boilerplate required in order to wrap a Value (eg.
79// MemoryValue) within a typesafe wrapper.
80func ExampleValue_full() {
81 ctx, ctxC := context.WithCancel(context.Background())
82 defer ctxC()
83
84 // Create a fake NetworkService.
85 ns := NetworkService{}
86
87 // Run an /etc/hosts updater. It will watch for updates from the NetworkService
88 // about the current IP address of the node.
89 go func() {
Serge Bazanski37110c32023-03-01 13:57:27 +000090 w := ns.Provider.Watch()
Serge Bazanskic00318e2021-03-03 12:39:24 +010091 for {
92 status, err := w.Get(ctx)
93 if err != nil {
94 break
95 }
96 if status.ExternalAddress == nil {
97 continue
98 }
99 // Pretend to write /etc/hosts with the newest ExternalAddress.
100 // In production code, you would also check for whether ExternalAddress has
101 // changed from the last written value, if writing to /etc/hosts is expensive.
102 fmt.Printf("/etc/hosts: foo.example.com is now %s\n", status.ExternalAddress.String())
103 }
104 }()
105
106 // Run fake network service.
107 ns.Run(ctx)
108
109 // Output:
110 // NS: Got DHCP Lease
111 // /etc/hosts: foo.example.com is now 203.0.113.24
112 // NS: DHCP Address changed
113 // /etc/hosts: foo.example.com is now 203.0.113.103
114}