github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/DEVELOPING.md (about) 1 # Developing Telepresence 2 2 3 ## Set up your environment 4 5 ### Development environment 6 7 - `TELEPRESENCE_REGISTRY` (required) is the Docker registry that 8 `make push-images` pushes the `tel2` and `telepresence` image to. 9 For most developers, the easiest thing is to set it to 10 `docker.io/USERNAME`. 11 12 - `TELEPRESENCE_VERSION` (optional) is the "vSEMVER" string to 13 compile-in to the binary and Docker image, if set. Otherwise, 14 `make` will automatically set this based on the current Git commit 15 and the current time. 16 17 - `DTEST_KUBECONFIG` (optional) is the cluster that is used by tests, 18 if set. Otherwise the tests will automatically use a K3s cluster 19 running locally in Docker. It is not normally necessary to set 20 this, but it is useful to set it in order to test against different 21 Kubernetes versions/configurations than what 22 https://github.com/datawire/dtest uses. 23 24 - `DTEST_REGISTRY` (optional) is the Docker registry that images are 25 pushed to by the tests, if set. Otherwise, the tests will 26 automatically use a registry running locally in Docker 27 ("localhost:5000"). The tests will push images named `tel2` with 28 various version tags. It is not necessary to set this unless you 29 have set `DTEST_KUBECONFIG`. 30 31 If `DTEST_KUBECONFIG` is pointing to a pre-existing cluster, and you 32 would like the `DTEST_REGISTRY` to point to a private registry that is 33 hosted in that cluster, then you can use `make private-registry`. It 34 will deploy a registry and set it up so that it is reachable at 35 `localhost:5000`, both from the cluster and from the local workstation. 36 37 - `DEV_TELEPRESENCE_VERSION` (optional) if set to a version such as 38 `v2.12.1-alpha.0`, the integration tests will assume that this version 39 is pre-built and available, both as a CLI client (accessible from the 40 current runtime path), and also pre-pushed into a pre-existing cluster 41 accessible from `DTEST_KUBECONFIG`. In other words, if this is set, no 42 no binaries will be built or pushed so the development + test cycle 43 can be quit rapid. 44 45 - `DEV_CLIENT_IMAGE` (optional) can be set to the fully qualified name of 46 an alternative image to use for the docker image used for the containerized 47 daemon when running in docker mode. 48 49 - `DEV_MANAGER_IMAGE` (optional) can be set to the fully qualified name of 50 an alternative image to use for the traffic manager. 51 52 - `DEV_AGENT_IMAGE` (optional) can be set to the fully qualified name of 53 an alternative image to use for the traffic agent. 54 55 - `DEV_USERD_PROFILING_PORT` and `DEV_ROOTD_PROFILING_PORT` (optional) if 56 set, will cause the `telepresence connect` calls in the integration tests 57 to start daemons where pprof is enabled (see 58 [Profiling the daemons](#profiling_the_daemons) below). 59 60 The above environment can optionally be provided in a `itest.yml` file 61 that is placed adjacent to the normal `config.yml` file used to configure 62 Telepresence. The `itest.yml` currently has only one single entry, the 63 `Env` which is a map. It can look something like this: 64 65 ```yaml 66 Env: 67 DEV_TELEPRESENCE_VERSION: v2.12.1-alpha.0 68 DTEST_KUBECONFIG: /home/thhal/.kube/testconfig 69 ``` 70 71 The output of `make help` has a bit more information. 72 73 ### Running integration tests 74 75 Integration tests can be run using `go test ./integration_test/...`. For 76 individual tests, use the `-m.testify=<pattern>` flag. Verbose output using 77 the `-v` flag is also recommended, because the tests are built with human 78 readable output in mind and timestamps can be compared to timestamps found 79 in the telepresence logs. 80 81 Example of running one test with existing cluster and registry: 82 ``` 83 make private-registry 84 export DTEST_KUBECONFIG=<your kubeconfig> 85 export DTEST_REGISTRY=localhost:5000 86 go test ./integration_test/... -v -testify.m=Test_InterceptDetailedOutput 87 ``` 88 89 If you run these tests on a Mac, localhost won't work. Please use the docker hub, or this value for the registry: 90 91 ```cli 92 export DTEST_REGISTRY=host.docker.internal:5000 93 ``` 94 95 You must also set this in your docker engine settings: 96 97 ```json 98 { 99 "insecure-registries": [ 100 "host.docker.internal:5000" 101 ] 102 } 103 ``` 104 105 The test takes about a minute to complete when using an existing cluster 106 and a private registry created by `make private-registry`. During that time 107 it: 108 - builds the traffic-manager image 109 - pushes the image to the registry 110 - builds the client binary 111 - creates two namespaces for the test 112 - performs a helm install of a namespace scoped traffic-manager 113 - runs the test 114 - uninstalls the traffic-manager 115 - deletes the namespaces 116 117 The first two can be omitted (and are omitted when the tests run 118 from CI) by building the binary using `make build`. 119 Example of running test with existing client and traffic-mananager: 120 121 ``` 122 make private-registry 123 export TELEPRESENCE_VERSION=v2.12.1-alpha.0 124 export TELEPRESENCE_REGISTRY=localhost:5000 125 make build 126 make push-images 127 export DTEST_KUBECONFIG=<your kubeconfig> 128 export DTEST_REGISTRY=$TELEPRESENCE_REGISTRY 129 export DEV_TELEPRESENCE_VERSION=$TELEPRESENCE_VERSION 130 131 # Run any number of indivitual test with this setup 132 go test ./integration_test/... -v -testify.m=Test_InterceptDetailedOutput 133 ``` 134 135 The `DEV_TELEPRESENCE_VERSION` tells the integration test that a client and 136 a traffic-manager of that version has been prebuilt and pushed. This usually 137 shortens the time for the test with about 20 seconds. 138 139 ### Runtime environment 140 141 - The main thing is that in your `~/.config/telepresence/config.yml` 142 (`~/Library/Application Support/telepresence/config.yml` on macOS) 143 file you set `images.registry` to match the `TELEPRESENCE_REGISTRY` 144 environment variable. See 145 https://www.getambassador.io/docs/telepresence/latest/reference/config/ 146 for more information. 147 148 - `TELEPRESENCE_VERSION` is is the "vSEMVER" string used by the 149 `telepresence` binary *if* one was not compiled in (for example, if 150 you're running it with `go run ./cmd/telepresence` rather than 151 having built it with `make build`). 152 153 - `TELEPRESENCE_AGENT_IMAGE` is is the "name:vSEMVER" string used when 154 the telepresence auto-installs the traffic-manager unless the config.yml 155 overrides it by defining `images.agentImage`. 156 157 - You will need have a `~/.kube/config` file (or set `KUBECONFIG` to 158 point to a different file) file in order to connect to a cluster; 159 same as any other Kubernetes tool. 160 161 - You will need to have [mockgen](https://github.com/golang/mock) installed 162 to generate new or updated testing mocks for interfaces. 163 164 ## Blocking Ambassador telemetry 165 Telemetry to Ambassador Labs can be disabled by having your os resolve the `metriton.datawire.io` to `127.0.0.1`. 166 167 ### Windows 168 `echo "127.0.0.1 metriton.datawire.io" >> c:\windows\system32\drivers\etc\hosts` 169 170 ### Linux and MacOS 171 `echo "127.0.0.1 metriton.datawire.io" | sudo tee -a /etc/hosts` 172 173 ## Build the binary, push the image 174 175 The easiest thing to do to get going: 176 177 ```console 178 $ TELEPRESENCE_REGISTRY=docker.io/thhal make build push-images # use .\build-aux\winmake.bat build on windows 179 [make] TELEPRESENCE_VERSION=v2.12.1-19-g37085c2d7-1655891839 180 ... # Lots of output 181 2.12.1-19-g37085c2d7-1655891839: digest: sha256:40fe852f8d8026a89f196293f37ae8c462c765c85572150d26263d78c43cdd4b size: 1157 182 ``` 183 184 This has 3 primary outputs: 185 1. The `./build-output/bin/telepresence` executable binary 186 2. The `${TELEPRESENCE_REGISTRY}/tel2` Docker image 187 3. The `${TELEPRESENCE_REGISTRY}/telepresence` Docker image 188 189 It essentially does 4 separate tasks: 190 1. `make build` to build the `./build-output/bin/telepresence` 191 executable binary 192 2. `make tel2-image` to build the `${TELEPRESENCE_REGISTRY}/tel2` Docker 193 image. 194 3. `make client-image` to build the `${TELEPRESENCE_REGISTRY}/telepresence` Docker 195 image. 196 4. `make push-images` to push the `${TELEPRESENCE_REGISTRY}/tel2` and `${TELEPRESENCE_REGISTRY}/telepresence` 197 Docker images. 198 199 You can run any of those tasks separately, but be warned: The 200 `TELEPRESENCE_VERSION` for all 4 needs to agree, and `make` includes a 201 timestamp in the default `TELEPRESENCE_VERSION`; if you run the tasks 202 separately you will need to explicitly set the `TELEPRESENCE_VERSION` 203 environment variable so that they all agree. 204 205 When working on just the command-line binary, it is often useful to 206 run it simply using `go run ./cmd/telepresence` rather than compiling 207 it first; but be warned: When run this way it won't know its own 208 version number (`telepresence version` will report "v0.0.0-devel") 209 unless you set the `TELEPRESENCE_VERSION` environment variable, you 210 will want to set it to the version of a previously-pushed Docker 211 image. 212 213 You may think that the initial suggestion of running `make build 214 push-images` all the time (so that every build gets new matching 215 version numbers) would be terribly slow. However, This is not as slow 216 as you might think; both `go` and `docker` are very good about reusing 217 existing builds and avoiding unnecessary work. 218 219 ## Run the tests 220 221 Running the tests does *not* require having previously built or pushed 222 anything. 223 224 The tests make use of `sudo`; it is useful to get in the habit of 225 running a no-op `sudo` command to pre-emptively prompt for your 226 password to avoid having to notice when the prompt appears in the test 227 output. 228 229 ```console 230 $ sudo id 231 [sudo] password for lukeshu: 232 uid=0(root) gid=0(root) groups=0(root) 233 234 $ make check-unit 235 [make] TELEPRESENCE_VERSION=v2.6.7-20-g9de10e316-1655892249 236 ... 237 ``` 238 239 The first time you run the tests, you should use `make check`, to get 240 `make` to automatically create the requisite `heml` tool 241 binaries. However, after that initial run, you can instead use 242 `gotestsum` or `go test` if you prefer. 243 244 ### Test metric collection 245 246 **When running in CI,** `make check-unit` and `make check-integration` will report the result of test 247 runs to metriton, Ambassador Labs' metrics store. These reports include test name, running time, and 248 result. They are reported by the tool at `tools/src/test-report`. This `test-report` tool will also 249 visually modify test output; this happens even running locally, since the json output to go test 250 is piped to the tool anyway: 251 252 ```console 253 $ make check-unit 254 ``` 255 256 ## Building for Release 257 258 See https://www.notion.so/datawire/To-Release-Telepresence-2-x-x-2752ef26968444b99d807979cde06f2f 259 260 ## Updating license documentation 261 262 Run `make generate` and commit changes to `DEPENDENCY_LICENSES.md` and `DEPENDENCIES.md` 263 264 ## Developing on Windows 265 266 ### Building on Windows 267 268 We do not currently support using `make` directly to build on Windows. Instead, use `build-aux\winmake.bat` and pass it the same parameters 269 you would pass to make. `winmake.bat` will run `make` from inside a Docker container, with appropriate parameters to build windows binaries. 270 271 ## Debugging and Troubleshooting 272 273 ### Log output 274 275 There are two logs: 276 - the `connector.log` log file which contains output from the 277 background-daemon parts of Telepresence that run as your regular 278 user: the interaction with the traffic-manager and the cluster 279 (traffic-manager and traffic-agent installs, intercepts, port 280 forwards, etc.), and 281 - the `daemon.log` log file which contains output from the parts of 282 telepresence that run as the "root" administrator user: the 283 networking changes and services that happen on your workstation. 284 285 The location of both logs is: 286 287 - on macOS: `~/Library/Logs/telepresence/` 288 - on GNU/Linux: `~/.cache/telepresence/logs/` 289 - on Windows `"%USERPROFILE%\AppData\Local\logs"` 290 291 The logs are rotating and a new log is created every time Telepresence 292 creates a new connection to the cluster, e.g. on `telepresence 293 connect` after a `telepresence quit` that terminated the last session. 294 295 #### Watching the logs 296 297 A convenient way to watch rotating logs is to use `tail -F 298 <filename>`. It will automatically and seamlessly follow the 299 rotation. 300 301 #### Debugging early-initialization errors 302 303 If there's an error from the connector or daemon during early 304 initialization, it might quit before the logfiles are set up. Perhaps 305 the problem is even with setting up the logfile itself. 306 307 You can run the `connector-foreground` or `daemon-foreground` commands 308 directly, to see what they spit out on stderr before dying: 309 310 ```console 311 $ telepresence connector-foreground # or daemon-foreground 312 ``` 313 314 If stdout is a TTY device, they don't set up logfiles and instead log 315 to stderr. In order to debug the logfile setup, simply pipe the 316 command to `cat` to trigger the usual logfile setup: 317 318 ```console 319 $ telepresence connector-foreground | cat 320 ``` 321 322 ### Profiling the daemons 323 324 The daemons can be profiled using [pprof](https://pkg.go.dev/net/http/pprof). 325 The profiling is initialized using the following flags: 326 327 ```console 328 $ telepresence quit -s 329 $ telepresence connect --userd-profiling-port 6060 --rootd-profiling-port 6061 330 ``` 331 332 If a daemon is started with pprof, then the goroutine stacks and much other 333 info can be found by connecting your browser to http://localhost:6060/debug/pprof/ 334 (swap 6060 for whatever port you used with the flags) 335 336 #### Dumping the goroutine stacks 337 338 A dump will be produced in the respective logs for the daemon simply by killing it 339 with a SIGQUIT signal. On Windows however, using profiling is the only option. 340 341 ### RBAC issues 342 343 If you are debugging or working on RBAC-related feature work with 344 Telepresence, it can be helpful to have a user with limited RBAC 345 privileges/roles. There are many ways you can do this, but the way we 346 do it in our tests is like so: 347 348 ```console 349 $ kubectl apply -f k8s/client_rbac.yaml 350 serviceaccount/telepresence-test-developer created 351 clusterrole.rbac.authorization.k8s.io/telepresence-role created 352 clusterrolebinding.rbac.authorization.k8s.io/telepresence-clusterrolebinding created 353 354 $ kubectl get sa telepresence-test-developer -o "jsonpath={.secrets[0].name}" 355 telepresence-test-developer-token-<hash> 356 357 $ kubectl get secret telepresence-test-developer-token-<hash> -o "jsonpath={.data.token}" > b64_token 358 $ cat b64_token | base64 --decode 359 <plaintext token> 360 361 $ kubectl config set-credentials telepresence-test-developer --token <plaintext token> 362 ``` 363 364 This creates a ServiceAccount, ClusterRole, and ClusterRoleBinding 365 which can be used with kubectl (`kubectl config use-context 366 telepresence-test-developer`) to work in a RBAC-restricted 367 environment. 368 369 ### Errors from `make generate` 370 371 #### Missing go.sum entries 372 If you get an error like this: 373 374 ``` 375 cd tools/src/go-mkopensource && GOOS= GOARCH= go build -o /home/andres/source/production/telepresence/tools/bin/go-mkopensource $(sed -En 's,^import "(.*)".*,\1,p' pin.go) 376 missing go.sum entry for module providing package github.com/datawire/go-mkopensource; to add: 377 go mod download github.com/datawire/go-mkopensource 378 ``` 379 380 Add the missing entries by going to the folder that caused the failure (in this case it's 381 /home/andres/source/production/telepresence/tools/bin/go-mkopensource) and run the command provided by go: 382 383 ``` 384 go mod download github.com/datawire/go-mkopensource 385 ```