github.com/inspektor-gadget/inspektor-gadget@v0.28.1/docs/devel/CONTRIBUTING.md (about)

     1  ---
     2  title: Contributing
     3  weight: 50
     4  description: >
     5    How to contribute to Inspektor Gadget.
     6  ---
     7  
     8  Here you can learn how you can contribute to Inspektor Gadget.
     9  
    10  ## Getting started
    11  
    12  To better understand how the pieces fit together, we recommend reading the
    13  [architecture](../core-concepts/architecture.md) documentation before starting to play with
    14  Inspektor Gadget.
    15  
    16  ### Setup developer environment
    17  
    18  - [Fork](https://github.com/inspektor-gadget/inspektor-gadget/fork) and clone this repo:
    19      - `git clone git@github.com:your_account/inspektor-gadget.git`.
    20  - Install [Docker](https://docs.docker.com/get-docker/), [Docker Buildx](https://docs.docker.com/buildx/working-with-buildx) and [Golang](https://golang.org/doc/install).
    21  - To be able to cross build our different container images, you will also need [`qemu-user-static`](https://github.com/multiarch/qemu-user-static).
    22  
    23  ## Building the code
    24  
    25  Inspektor Gadget is composed of a client executable that runs on the
    26  operator's machine, and a container image that runs in the Kubernetes
    27  cluster. They can be built together or independently.
    28  
    29  ### Building the client executable
    30  
    31  You can compile the client executable for your platform by running `make kubectl-gadget`.
    32  
    33  To cross compile for all supported platforms, you can run `make
    34  kubectl-gadget-all` or select a specific one with `make
    35  kubectl-gadget-linux-amd64` or `make kubectl-gadget-darwin-amd64`.
    36  
    37  ### Building the gadget container image
    38  
    39  You can build and push the container gadget image by running the following commands:
    40  
    41  ```bash
    42  $ make gadget-container
    43  $ make push-gadget-container
    44  ```
    45  
    46  The eBPF code is built using a Docker container, so you don't have to worry
    47  installing the compilers to build it.
    48  
    49  If you push the container images to another registry, you can use the `--image`
    50  argument when deploying to the Kubernetes cluster.
    51  
    52  #### Notes
    53  
    54  - Using a locally built container image requires pushing it to a container
    55  registry, either local or remote. The default registry can be overridden by
    56  changing the value of the `CONTAINER_REPO` env variable, which defaults to
    57  `ghcr.io/inspektor-gadget/inspektor-gadget` if not defined.
    58  - The compilation uses `tools/image-tag` to choose the tag of the container
    59  image to use according to the branch that you are compiling.
    60  - It is also possible to change the BCC to be used as described in
    61  [BCC](#Updating-BCC-from-upstream) section.
    62  - You can generate the required BTF information for some well known
    63    kernel versions by setting `ENABLE_BTFGEN=true`
    64  
    65  
    66  ### Building the eBPF object files
    67  
    68  If you need to compile the eBPF code of the gadgets, the ebpf-objects target
    69  will help you in this task:
    70  
    71  ```bash
    72  $ make ebpf-objects
    73  ...
    74  go: downloading github.com/giantswarm/crd-docs-generator v0.7.1
    75  ...
    76  Wrote /work/pkg/gadgettracermanager/containers-map/containersmap_bpfel.go
    77  ```
    78  
    79  ### Building `ig`
    80  
    81  Inspektor Gadget also provides the [`ig`](../ig.md) tool to
    82  trace containers without Kubernetes. It can be built independently from the
    83  `kubectl-gadget` and the gadget container image.
    84  
    85  ```bash
    86  $ make ig
    87  ```
    88  
    89  ## Testing
    90  
    91  ### Development environment on minikube
    92  
    93  For faster iteration, it's possible to make changes to Inspektor Gadget and
    94  test them on minikube locally without pushing container images to any
    95  registry.
    96  
    97  * Follow the specific [installation instructions](../getting-started/install-kubernetes.md#minikube) for minikube or use `make minikube-start` to start it.
    98  * Deploy the locally modified version of Inspektor Gadget to an already
    99    running minikube cluster with `make minikube-deploy`.
   100  
   101  ### Unit tests
   102  
   103  You can run the different unit tests with:
   104  
   105  ```bash
   106  $ make test
   107  ```
   108  
   109  ### Regenerating testdata
   110  
   111  Some unit tests depend on precompiled files on [testdata](../../testdata/). These files can be
   112  regenerated by running
   113  
   114  ```bash
   115  $ make testdata
   116  ```
   117  
   118  ### Integration tests
   119  
   120  The integration tests use a Kubernetes cluster to deploy and test Inspektor Gadget.
   121  Be sure that you have a valid kubeconfig and run:
   122  
   123  ```bash
   124  $ export KUBECONFIG=... # not needed if valid config in $HOME/.kube/config
   125  $ make integration-tests
   126  ```
   127  
   128  ### Integration tests for `ig`
   129  
   130  #### Kubernetes
   131  
   132  The integration tests for `ig` uses minikube for testing different container runtimes.
   133  The default minikube driver used for testing is `docker`. Currently supported
   134  container runtimes are `docker`, `containerd` and `cri-o`. You can start minikube using:
   135  
   136  ```bash
   137  $ make minikube-start-all
   138  # for single container runtime e.g containerd
   139  $ make CONTAINER_RUNTIME=containerd minikube-start
   140  # for minikube driver other than docker e.g kvm2
   141  $ make MINIKUBE_DRIVER=kvm2 minikube-start
   142  ```
   143  
   144  And run the test using:
   145  
   146  ```bash
   147  $ make -C integration/k8s test-all
   148  # for single container runtime e.g containerd
   149  $ make -C integration/k8s CONTAINER_RUNTIME=containerd test
   150  ```
   151  
   152  if no `CONTAINER_RUNTIME` is specified `docker` will be used as a default runtime.
   153  
   154  #### Non-Kubernetes
   155  
   156  The `ig` integration tests for non-Kubernetes containers directly interact
   157  with container runtime. The tests assume that you already have the desired container
   158  runtime installed. Currently supported runtime is `docker` only, You can run the test using:
   159  
   160  ```bash
   161  $ make -C integration/ig/non-k8s test-docker
   162  ```
   163  
   164  ### Benchmarks
   165  
   166  You can run the different benchmark tests with:
   167  
   168  ```bash
   169  $ make gadgets-benchmarks
   170  ```
   171  
   172  Or you can run an individual test with:
   173  
   174  ```bash
   175  $ go test -exec sudo \
   176      -bench='BenchmarkAllGadgetsWithContainers/container10$/trace-tcpconnect' \
   177      -run=Benchmark \
   178      ./internal/benchmarks/...
   179  ```
   180  
   181  Records of previous benchmarks are available [here](https://inspektor-gadget.github.io/ig-benchmarks/dev/bench/index.html).
   182  See details in the [CI documentation (benchmarks)](ci.md#benchmarks).
   183  
   184  #### Explaining performance improvements in a PR
   185  
   186  If you want to contribute a performance improvement, it is useful to use benchmarks to explain the impact on
   187  performances. I will use the example of an improvement on the networking gadgets from
   188  [#1430](https://github.com/inspektor-gadget/inspektor-gadget/pull/1430):
   189  
   190  * Run the benchmarks both on the `main` and the feature branches and saving the output in two files.
   191  ```bash
   192  $ git checkout main
   193  $ go test -exec sudo \
   194      -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/trace-(dns|sni)' \
   195      -run=Benchmark \
   196      ./internal/benchmarks/... \
   197      -count 10 | tee main.bench
   198  $ git checkout myfeature
   199  $ go test -exec sudo \
   200      -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/trace-(dns|sni)' \
   201      -run=Benchmark \
   202      ./internal/benchmarks/... \
   203      -count 10 | tee patched.bench
   204  ```
   205  
   206  Please use `-count` to gather a statistically significant sample of results.
   207  The [benchstat's documentation](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat) recommends 10 times.
   208  
   209  * Compare the results with `benchstat`:
   210  ```bash
   211  $ go install golang.org/x/perf/cmd/benchstat@latest # if not already installed
   212  $ benchstat main.bench patched.bench
   213  goos: linux
   214  goarch: amd64
   215  pkg: github.com/inspektor-gadget/inspektor-gadget/internal/benchmarks
   216  cpu: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
   217                                                    │ main.bench  │           patched.bench            │
   218                                                    │   sec/op    │   sec/op    vs base                │
   219  AllGadgetsWithContainers/container100/trace-dns-4   2.941 ±  3%   1.489 ± 4%  -49.38% (p=0.000 n=10)
   220  AllGadgetsWithContainers/container100/trace-sni-4   4.440 ± 19%   1.495 ± 6%  -66.34% (p=0.000 n=10)
   221  geomean                                             3.613         1.492       -58.72%
   222  ```
   223  
   224  * Include the commands used and the output of `benchstat` in your pull request description
   225  
   226  #### Profiling benchmarks
   227  
   228  You can run the different benchmark tests while using the
   229  [bcc profile tool](https://github.com/iovisor/bcc/blob/master/tools/profile_example.txt).
   230  To be able to see the symbols in the profile, you need to build the binary with
   231  `-ldflags="-s=false"`.
   232  
   233  ```bash
   234  $ go test -exec sudo \
   235      -ldflags="-s=false" \
   236      -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/snapshot-socket' \
   237      -run=Benchmark \
   238      ./internal/benchmarks/... \
   239      -count 100
   240  ```
   241  
   242  Example of output showing a stack trace including both the userspace and kernel parts:
   243  
   244  ```bash
   245  $ sudo /usr/share/bcc/tools/profile -p $(pidof benchmarks.test)
   246      b'established_get_first'
   247      b'established_get_first'
   248      b'tcp_seek_last_pos'
   249      b'bpf_iter_tcp_batch'
   250      b'bpf_iter_tcp_seq_next'
   251      b'bpf_seq_read'
   252      b'vfs_read'
   253      b'ksys_read'
   254      b'do_syscall_64'
   255      b'entry_SYSCALL_64_after_hwframe'
   256      runtime/internal/syscall.Syscall6
   257      syscall.Syscall
   258      syscall.read
   259      internal/poll.(*FD).Read
   260      os.(*File).Read
   261      bufio.(*Scanner).Scan
   262      github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/snapshot/socket/tracer.(*Tracer).RunCollector.func1
   263      github.com/inspektor-gadget/inspektor-gadget/pkg/netnsenter.NetnsEnter
   264      github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/snapshot/socket/tracer.(*Tracer).RunCollector
   265      github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/snapshot/socket/tracer.(*Tracer).Run
   266      github.com/inspektor-gadget/inspektor-gadget/pkg/runtime/local.(*Runtime).RunGadget
   267      github.com/inspektor-gadget/inspektor-gadget/internal/benchmarks.BenchmarkAllGadgetsWithContainers.func1.1
   268      testing.(*B).runN
   269      testing.(*B).launch
   270      testing.(*B).doBench.func1
   271      runtime.goexit.abi0
   272      -                benchmarks.test (3452330)
   273          22
   274  ```
   275  
   276  It is also possible to use [pprof](https://pkg.go.dev/runtime/pprof) to profile
   277  the benchmarks with the `-cpuprofile` and `-memprofile` flags.
   278  
   279  ```bash
   280  go test \
   281      -cpuprofile cpu.prof -memprofile mem.prof \
   282      -exec sudo \
   283      -ldflags="-s=false" \
   284      -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/snapshot-socket' \
   285      -run=Benchmark ./internal/benchmarks/... \
   286      -count 5
   287  $ go tool pprof -top cpu.prof
   288  $ go tool pprof -top mem.prof
   289  ```
   290  
   291  ### Continuous Integration
   292  
   293  Inspektor Gadget uses GitHub Actions as CI. Please check dedicated [CI
   294  documentation](ci.md) for more details.
   295  
   296  Some integration tests (like AKS and ARO) are only run when a commit is pushed to the main branch or
   297  a new tag is pushed. It's also possible to run those by pusing a branch named `citest/...`. Please
   298  notice that the container images will be pushed to
   299  https://github.com/inspektor-gadget/inspektor-gadget/pkgs/container/inspektor-gadget and those
   300  should be manually cleaned up.
   301  
   302  ## Getting Help
   303  
   304  If you are having any issues with your contribution, or want to discuss anything about it, feel free
   305  to reach out to us on [Slack](https://kubernetes.slack.com/messages/inspektor-gadget/) or on our
   306  [community
   307  meeting](https://docs.google.com/document/d/1cbPYvYTsdRXd41PEDcwC89IZbcA8WneNt34oiu5s9VA/edit)
   308  
   309  ## Contribution Guidelines
   310  
   311  ### Code of Conduct
   312  
   313  Inspektor Gadget follows the CNCF
   314  [Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
   315  
   316  ### Authoring PRs
   317  
   318  For making PRs/commits consistent and easier to review, please check out
   319  Kinvolk's [contribution guidelines on git](https://github.com/kinvolk/contribution/blob/master/topics/git.md).
   320  
   321  We require all commits on a PR to be signed off certifying the [Developer Certificate of Origin](https://developercertificate.org/):
   322  
   323  
   324  ```
   325  Developer Certificate of Origin
   326  Version 1.1
   327  
   328  Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
   329  
   330  Everyone is permitted to copy and distribute verbatim copies of this
   331  license document, but changing it is not allowed.
   332  
   333  
   334  Developer's Certificate of Origin 1.1
   335  
   336  By making a contribution to this project, I certify that:
   337  
   338  (a) The contribution was created in whole or in part by me and I
   339      have the right to submit it under the open source license
   340      indicated in the file; or
   341  
   342  (b) The contribution is based upon previous work that, to the best
   343      of my knowledge, is covered under an appropriate open source
   344      license and I have the right under that license to submit that
   345      work with modifications, whether created in whole or in part
   346      by me, under the same open source license (unless I am
   347      permitted to submit under a different license), as indicated
   348      in the file; or
   349  
   350  (c) The contribution was provided directly to me by some other
   351      person who certified (a), (b) or (c) and I have not modified
   352      it.
   353  
   354  (d) I understand and agree that this project and the contribution
   355      are public and that a record of the contribution (including all
   356      personal information I submit with it, including my sign-off) is
   357      maintained indefinitely and may be redistributed consistent with
   358      this project or the open source license(s) involved.
   359  ```
   360  
   361  It can be done by using `git commit -s`, `git commit --sign-off` or by manually adding a line like
   362  to the commit message.
   363  
   364  ```
   365  Signed-off-by: Joe Smith <joe.smith@email.com>
   366  ```
   367  
   368  ### Good first issues
   369  
   370  If you're looking where to start, you can check the issues with the
   371  `good first issue` label on
   372  [Inspektor Gadget](https://github.com/inspektor-gadget/inspektor-gadget/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
   373  Don't hesitate to
   374  [talk to us](https://github.com/inspektor-gadget/inspektor-gadget#discussions)
   375  if you need further help.
   376  
   377  ### Proposing new features
   378  
   379  If you want to propose a new feature or do a big change in the architecture
   380  it's highly recommended to open an issue first to discuss it with the team.
   381  
   382  ### Writing tests
   383  
   384  We use `github.com/stretchr/testify` to make tests less verbose.
   385  
   386  ## Planning
   387  
   388  Our planning is published through two different project boards:
   389  
   390   * [Inspektor Gadget Roadmap](https://github.com/orgs/inspektor-gadget/projects/1)
   391     has the high level view of the big issues that we are planning to tackle
   392     in the upcoming months.
   393   * [Inspektor Gadget Sprint Planning](https://github.com/orgs/inspektor-gadget/projects/2)
   394     has the week-to-week plans of which bugs we are currently working on,
   395     and the different priorities of the issues involved.
   396  
   397  ## BCC
   398  
   399  ### Porting BCC gadgets
   400  
   401  This project uses some gadgets based on [BCC](https://github.com/iovisor/bcc/). In the past, we
   402  modified the BCC gadgets and executed them from our process, however it was very inflexible and we
   403  decided to integrate those gadgets directly into our code base by rewriting their control plane in
   404  Golang.
   405  
   406  If you want to implement support for a BCC gadget, please read the [Rewriting the Control Plane of
   407  BCC Tools in Golang](https://www.inspektor-gadget.io/blog/2022/09/rewriting-the-control-plane-of-bcc-tools-in-golang/)
   408  blogpost that contains all the details about this process.
   409  
   410  ## Security
   411  
   412  For security, we invite you to take at look at the [dedicated document](../SECURITY.md).