Skip to content

Latest commit

 

History

History
205 lines (145 loc) · 7.17 KB

CONTRIBUTING.md

File metadata and controls

205 lines (145 loc) · 7.17 KB

Contributing

Pull requests

Make sure all the following are true when creating a pull-request:

  • The coding style guide was followed when creating the change.
  • The PR has a meaningful title guidelines.
  • The PR is labeled accordingly with a single label.
  • Unit tests have been updated/added.
  • Relevant documentation has been updated/added.

Quick start

  1. Read the coding style guide.

  2. Fork the dynatrace-operator repository and get the source code:

    git clone https://github.com/<your_username>/dynatrace-operator
    cd dynatrace-operator
  3. Install development prerequisites:

    make prerequisites
  4. Create a new branch to work on:

    Group your branch into a category using a prefix for your branch name, like feature/, ci/, bugfix/, doc/.

    git checkout -b feature/your-branch
  5. Once the changes are finished, make sure there are no warnings in the code. For debugging you can run the unit tests and end-to-end tests.

    NOTE: Unit tests can also be automatically run via pre-commit hook, installed by running make prerequisites/setup-pre-commit. With the pre-commit hook can only commit code that passes all checks.

    make go/test
    make test/e2e/<scope_of_the_changes>
  6. To test your changes on a cluster use

    Pushing to the default container registry (quay.io/dynatrace/dynatrace-operator) requires specific permissions. You can use your own container registry by setting the IMAGE environment variable to a different value.

    1. Connect to a cluster using kubectl
    2. Use make commands to build and deploy your operator as follows:
    make build && make deploy
  7. Create a pull request from the fork (see guide), with a proper title and fill out the description template. Once everything is ready, set the PR ready for review.

  8. A maintainer will review the pull request and make comments. It's preferable to add additional commits over amending and force-pushing since it can be difficult to follow code reviews when the commit history changes. Commits will be squashed when they're merged.

Unit tests

Run the go unit tests via make:

make go/test

Mocking

For our mocking needs we trust in testify while using mockery to generate our mocks. We check in our mocks to improve code readability especially when reading via GitHub and to remove the dependency on make scripts to run our tests. Mockery only has to be run when adding new mocks or have to be updated to changed interfaces.

Installing mockery

Mockery is installed by running (see docs for further information)

make prerequisites/mockery

Adding a mock

When adding a mock you have to add the mocked interface to .mockery.yaml. Take the following example of the builder package with the interfaces Builder and Modifier:

quiet: False
disable-version-string: True
with-expecter: True
mockname: "{{.InterfaceName}}"
filename: "{{.MockName}}.go"
outpkg: mocks
dir: "test/mocks{{.InterfaceDirRelative}}"
packages:
  github.com/Dynatrace/dynatrace-operator/pkg/util/builder:
    config:
      recursive: true
     # all: true // or use all if mocks for all interfaces in a package/dir should be created
    interfaces:
      Builder:
      Modifier:

then run mockery by simple running

make go/gen_mocks

Migrating to Mockery

To move our existing codebase to mockery you have to look out for these pitfalls:

  1. As a rule o thumb, use mocks.NewXYZ(t) function instead of mocks.XYZ{} struct when any expectation is defined (On(..)). It allows to easily detect cases when no expectations are need or new ones should be added.

  2. Mocks require a reference parameter to testingT:

    //...
    b := GenericBuilder[mocks.Data]{}
    
    modifierMock := mocks.NewModifier[mocks.Data](t) // <- t required here
    //...
  3. Add call to Maybe() to return if it should be tested if the function is called at all:

    modifierMock.On("Modify", mock.Anything).Return(nil).Maybe()
    modifierMock.On("Enabled").Return(false)
    
    actual, _ := b.AddModifier(modifierMock).Build()
    modifierMock.AssertNotCalled(t, "Modify")
    //modifierMock.AssertNumberOfCalls(t, "Modify", 0)

❗ In the case of using multiple mock packages in the same test file, the standard package alias naming is {struct}mock, e.g. clientmock.

clientmock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/clients/dynatrace"
installermock "github.com/Dynatrace/dynatrace-operator/test/mocks/pkg/injection/codemodule/installer"
reconcilermock "github.com/Dynatrace/dynatrace-operator/test/mocks/sigs.k8s.io/controller-runtime/pkg/reconcile"

E2E tests

Prerequisites:

  • Existing kube config with the context of a test K8s cluster
  • Cleanup the cluster using make undeploy
  • Configured Dynatrace tenant(s) with an access token (see /test/testdata/secrets-samples). Read more about Access tokens on the official documentation.

Check the available E2E tests via make command:

make help | grep 'e2e'

We recommended to only execute the ones related to the changes as each one can take some minutes to finish.

Useful commands

Remove all Dynatrace pods in force mode (useful debugging E2E tests)

kubectl delete pods --all --force --grace-period=0 -n dynatrace

Copy CSI driver database to localhost for introspection via sqlite command

kubectl cp dynatrace/dynatrace-oneagent-csi-driver-<something>:/data/csi.db csi.sqlite

Add debug suffix on E2E tests to avoid removing pods

make test/e2e/cloudnative/proxy/debug

Debug cluster nodes by opening a shell prompt

Details here

oc debug node/<node-name>