Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws/boostrap: add boostrap node only security group rules #1105

Merged

Conversation

abhinavdahiya
Copy link
Contributor

Thies opens up

  • 19531 so that we can fetch the logs using the journald-gateway
    example,
$ curl --insecure --silent --connect-timeout 5 --retry 3 --cert dev/tls/journal-gatewayd.crt --key dev/tls/journal-gatewayd.key --url "https://54.236.241.128:19531/entries?_SYSTEMD_UNIT=bootkube.service"
Jan 21 18:04:54 ip-10-0-2-210 bootkube.sh[4461]: Pulling release image...
Jan 21 18:04:54 ip-10-0-2-210 bootkube.sh[4461]: Trying to pull registry.svc.ci.openshift.org/openshift/origin-release:v4.0...Getting image source signatures
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob a02a4930cb5d: 0 B / 71.68 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob 2332fbb5f18d: 0 B / 9.57 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob 84bc44c0bb13: 0 B / 10.10 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob fe1e349f5ed8: 0 B / 35.11 KiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: [52B blob data]
...
  • 10250 so that we can fetch logs from kubelet using the secure port server.
    example,
$ curl --insecure --silent --connect-timeout 5 --retry 3 --url "https://54.236.241.128:10250/pods/"
{"kind":"PodList","apiVersion":"v1","metadata":{},"items":[{"metadata":{"name":"bootstrap-cluster-version-operator-ip-10-0-2-210","namespace":"openshift-cluster-version","selfLink":"/api/v1/namespaces/openshift-cluster-version/pods/bootstrap-cluster-version-operator-ip-10-0-2-210","uid":"99cad0c02d66ec3224641a68bf9eafe7","creationTimestamp":null,"labels":{"k8s-app":"cluster-version-operator"},"annotations":{"kubernetes.io/config.hash":"99cad0c02d66ec3224641a68bf9eafe7","kubernetes.io/config.seen":"2019-01-21T18:11:12.525217521Z","kubernetes.io/config.source":"file"}},"spec":{"volumes":[{"name":"kubeconfig","hostPath":{"path":"/etc/kubernetes/kubeconfig","type":""}},{"name":"etc-ssl-certs","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"cluster-version-operator","image":"registry.svc.ci.openshift.org/openshift/origin-release@sha256:b7d00ac59cbdb0abc85a9dab7af896af1a1e58a977872da8b74da2c9fa24ed0d","args":["start","--release-image=registry.svc.ci.openshift.org/openshift/origin-release@sha256:b7d00ac59cbdb0abc85a9dab7af896af1a1e58a977872da8b74da2c9fa24ed0d","--enable-auto-update=false","--v=4","--kubeconfig=/etc/kubernetes/kubeconfig"],"env":[{"name":"KUBERNETES_SERVICE_PORT","value":"6443"},{"name":"KUBERNETES_SERVICE_HOST","value":"127.0.0.1"},{"name":"NODE_NAME","valueFrom":{"fieldRef":{"apiVersion":"v1","fieldPath":"spec.nodeName"}}}],"resources":{},"volumeMounts":[{"name":"etc-ssl-certs","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"kubeconfig","readOnly":true,"mountPath":"/etc/kubernetes/kubeconfig"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always","securityContext":{"privileged":true}}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-apiserver-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-apiserver-ip-10-0-2-210","uid":"8d8a1ad433c37ead36187e51790a045b","creationTimestamp":null,"labels":{"openshift.io/component":"api","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"8d8a1ad433c37ead36187e51790a045b","kubernetes.io/config.seen":"2019-01-21T18:11:12.527108477Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}},{"name":"etc-kubernetes-cloud","hostPath":{"path":"/etc/kubernetes/cloud","type":""}},{"name":"config","hostPath":{"path":"/etc/kubernetes/bootstrap-configs","type":""}},{"name":"ssl-certs-host","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"kube-apiserver","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:fc9ef7e68f05cbc110b817f01b5ed620c7902ebad6675829ee6f09a744b9d381","command":["hypershift","openshift-kube-apiserver"],"args":["--config=/etc/kubernetes/config/kube-apiserver-config.yaml"],"resources":{},"volumeMounts":[{"name":"ssl-certs-host","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"},{"name":"etc-kubernetes-cloud","readOnly":true,"mountPath":"/etc/kubernetes/cloud"},{"name":"config","readOnly":true,"mountPath":"/etc/kubernetes/config"}],"livenessProbe":{"httpGet":{"path":"healthz","port":6443,"scheme":"HTTPS"},"initialDelaySeconds":45,"timeoutSeconds":10,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"readinessProbe":{"httpGet":{"path":"healthz","port":6443,"scheme":"HTTPS"},"initialDelaySeconds":10,"timeoutSeconds":10,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-controller-manager-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-controller-manager-ip-10-0-2-210","uid":"740f40480c6583e97adc20a3db98d95f","creationTimestamp":null,"labels":{"openshift.io/component":"controller-manager","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"740f40480c6583e97adc20a3db98d95f","kubernetes.io/config.seen":"2019-01-21T18:11:12.529495295Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}},{"name":"etc-kubernetes-cloud","hostPath":{"path":"/etc/kubernetes/cloud","type":""}},{"name":"config","hostPath":{"path":"/etc/kubernetes/bootstrap-configs","type":""}},{"name":"ssl-certs-host","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"kube-controller-manager","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:b5bb3c2de540de94d1ae56073e7351038fdb69d0a2f5b302dd49516d60dd4b0a","command":["/bin/bash","-c"],"args":["exec hyperkube kube-controller-manager --openshift-config=/etc/kubernetes/config/kube-controller-manager-config.yaml --kubeconfig=/etc/kubernetes/secrets/kubeconfig"],"resources":{},"volumeMounts":[{"name":"ssl-certs-host","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"},{"name":"etc-kubernetes-cloud","readOnly":true,"mountPath":"/etc/kubernetes/cloud"},{"name":"config","readOnly":true,"mountPath":"/etc/kubernetes/config"}],"livenessProbe":{"httpGet":{"path":"healthz","port":10252,"scheme":"HTTP"},"timeoutSeconds":1,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-scheduler-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-scheduler-ip-10-0-2-210","uid":"7f2dcea195c76e1b916c2b2c982ce45b","creationTimestamp":null,"labels":{"openshift.io/component":"scheduler","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"7f2dcea195c76e1b916c2b2c982ce45b","kubernetes.io/config.seen":"2019-01-21T18:11:12.53217079Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}}],"containers":[{"name":"kube-scheduler","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:b5bb3c2de540de94d1ae56073e7351038fdb69d0a2f5b302dd49516d60dd4b0a","command":["/bin/bash","-c"],"args":["exec hyperkube kube-scheduler --kubeconfig=/etc/kubernetes/secrets/kubeconfig --leader-elect=true"],"resources":{},"volumeMounts":[{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}}]}

/cc @wking @crawford
This helps move openshift/release#2633 forward.

@openshift-ci-robot openshift-ci-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. approved Indicates a PR has been approved by an approver from all required OWNERS files. labels Jan 21, 2019
Thies opens up
- `19531` so that we can fetch the logs using the `journald-gateway`
example,
```console
$ curl --insecure --silent --connect-timeout 5 --retry 3 --cert dev/tls/journal-gatewayd.crt --key dev/tls/journal-gatewayd.key --url "https://54.236.241.128:19531/entries?_SYSTEMD_UNIT=bootkube.service"
Jan 21 18:04:54 ip-10-0-2-210 bootkube.sh[4461]: Pulling release image...
Jan 21 18:04:54 ip-10-0-2-210 bootkube.sh[4461]: Trying to pull registry.svc.ci.openshift.org/openshift/origin-release:v4.0...Getting image source signatures
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob a02a4930cb5d: 0 B / 71.68 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob 2332fbb5f18d: 0 B / 9.57 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob 84bc44c0bb13: 0 B / 10.10 MiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: Copying blob fe1e349f5ed8: 0 B / 35.11 KiB
Jan 21 18:04:55 ip-10-0-2-210 bootkube.sh[4461]: [52B blob data]
...
```

- `10250` so that we can fetch logs from kubelet using the secure port server.
example,
```console
$ curl --insecure --silent --connect-timeout 5 --retry 3 --url "https://54.236.241.128:10250/pods/"
{"kind":"PodList","apiVersion":"v1","metadata":{},"items":[{"metadata":{"name":"bootstrap-cluster-version-operator-ip-10-0-2-210","namespace":"openshift-cluster-version","selfLink":"/api/v1/namespaces/openshift-cluster-version/pods/bootstrap-cluster-version-operator-ip-10-0-2-210","uid":"99cad0c02d66ec3224641a68bf9eafe7","creationTimestamp":null,"labels":{"k8s-app":"cluster-version-operator"},"annotations":{"kubernetes.io/config.hash":"99cad0c02d66ec3224641a68bf9eafe7","kubernetes.io/config.seen":"2019-01-21T18:11:12.525217521Z","kubernetes.io/config.source":"file"}},"spec":{"volumes":[{"name":"kubeconfig","hostPath":{"path":"/etc/kubernetes/kubeconfig","type":""}},{"name":"etc-ssl-certs","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"cluster-version-operator","image":"registry.svc.ci.openshift.org/openshift/origin-release@sha256:b7d00ac59cbdb0abc85a9dab7af896af1a1e58a977872da8b74da2c9fa24ed0d","args":["start","--release-image=registry.svc.ci.openshift.org/openshift/origin-release@sha256:b7d00ac59cbdb0abc85a9dab7af896af1a1e58a977872da8b74da2c9fa24ed0d","--enable-auto-update=false","--v=4","--kubeconfig=/etc/kubernetes/kubeconfig"],"env":[{"name":"KUBERNETES_SERVICE_PORT","value":"6443"},{"name":"KUBERNETES_SERVICE_HOST","value":"127.0.0.1"},{"name":"NODE_NAME","valueFrom":{"fieldRef":{"apiVersion":"v1","fieldPath":"spec.nodeName"}}}],"resources":{},"volumeMounts":[{"name":"etc-ssl-certs","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"kubeconfig","readOnly":true,"mountPath":"/etc/kubernetes/kubeconfig"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always","securityContext":{"privileged":true}}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-apiserver-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-apiserver-ip-10-0-2-210","uid":"8d8a1ad433c37ead36187e51790a045b","creationTimestamp":null,"labels":{"openshift.io/component":"api","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"8d8a1ad433c37ead36187e51790a045b","kubernetes.io/config.seen":"2019-01-21T18:11:12.527108477Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}},{"name":"etc-kubernetes-cloud","hostPath":{"path":"/etc/kubernetes/cloud","type":""}},{"name":"config","hostPath":{"path":"/etc/kubernetes/bootstrap-configs","type":""}},{"name":"ssl-certs-host","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"kube-apiserver","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:fc9ef7e68f05cbc110b817f01b5ed620c7902ebad6675829ee6f09a744b9d381","command":["hypershift","openshift-kube-apiserver"],"args":["--config=/etc/kubernetes/config/kube-apiserver-config.yaml"],"resources":{},"volumeMounts":[{"name":"ssl-certs-host","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"},{"name":"etc-kubernetes-cloud","readOnly":true,"mountPath":"/etc/kubernetes/cloud"},{"name":"config","readOnly":true,"mountPath":"/etc/kubernetes/config"}],"livenessProbe":{"httpGet":{"path":"healthz","port":6443,"scheme":"HTTPS"},"initialDelaySeconds":45,"timeoutSeconds":10,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"readinessProbe":{"httpGet":{"path":"healthz","port":6443,"scheme":"HTTPS"},"initialDelaySeconds":10,"timeoutSeconds":10,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-controller-manager-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-controller-manager-ip-10-0-2-210","uid":"740f40480c6583e97adc20a3db98d95f","creationTimestamp":null,"labels":{"openshift.io/component":"controller-manager","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"740f40480c6583e97adc20a3db98d95f","kubernetes.io/config.seen":"2019-01-21T18:11:12.529495295Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}},{"name":"etc-kubernetes-cloud","hostPath":{"path":"/etc/kubernetes/cloud","type":""}},{"name":"config","hostPath":{"path":"/etc/kubernetes/bootstrap-configs","type":""}},{"name":"ssl-certs-host","hostPath":{"path":"/etc/ssl/certs","type":""}}],"containers":[{"name":"kube-controller-manager","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:b5bb3c2de540de94d1ae56073e7351038fdb69d0a2f5b302dd49516d60dd4b0a","command":["/bin/bash","-c"],"args":["exec hyperkube kube-controller-manager --openshift-config=/etc/kubernetes/config/kube-controller-manager-config.yaml --kubeconfig=/etc/kubernetes/secrets/kubeconfig"],"resources":{},"volumeMounts":[{"name":"ssl-certs-host","readOnly":true,"mountPath":"/etc/ssl/certs"},{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"},{"name":"etc-kubernetes-cloud","readOnly":true,"mountPath":"/etc/kubernetes/cloud"},{"name":"config","readOnly":true,"mountPath":"/etc/kubernetes/config"}],"livenessProbe":{"httpGet":{"path":"healthz","port":10252,"scheme":"HTTP"},"timeoutSeconds":1,"periodSeconds":10,"successThreshold":1,"failureThreshold":3},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}},{"metadata":{"name":"bootstrap-kube-scheduler-ip-10-0-2-210","namespace":"kube-system","selfLink":"/api/v1/namespaces/kube-system/pods/bootstrap-kube-scheduler-ip-10-0-2-210","uid":"7f2dcea195c76e1b916c2b2c982ce45b","creationTimestamp":null,"labels":{"openshift.io/component":"scheduler","openshift.io/control-plane":"true"},"annotations":{"kubernetes.io/config.hash":"7f2dcea195c76e1b916c2b2c982ce45b","kubernetes.io/config.seen":"2019-01-21T18:11:12.53217079Z","kubernetes.io/config.source":"file","openshift.io/run-level":"0"}},"spec":{"volumes":[{"name":"secrets","hostPath":{"path":"/etc/kubernetes/bootstrap-secrets","type":""}}],"containers":[{"name":"kube-scheduler","image":"registry.svc.ci.openshift.org/openshift/origin-v4.0-2019-01-21-133143@sha256:b5bb3c2de540de94d1ae56073e7351038fdb69d0a2f5b302dd49516d60dd4b0a","command":["/bin/bash","-c"],"args":["exec hyperkube kube-scheduler --kubeconfig=/etc/kubernetes/secrets/kubeconfig --leader-elect=true"],"resources":{},"volumeMounts":[{"name":"secrets","readOnly":true,"mountPath":"/etc/kubernetes/secrets"}],"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","nodeName":"ip-10-0-2-210","hostNetwork":true,"securityContext":{},"schedulerName":"default-scheduler","tolerations":[{"operator":"Exists","effect":"NoExecute"}]},"status":{"phase":"Pending"}}]}
```
@crawford
Copy link
Contributor

Approved to be merged during the freeze.

/approve

@wking
Copy link
Member

wking commented Jan 21, 2019

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jan 21, 2019
@openshift-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: abhinavdahiya, crawford, wking

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [abhinavdahiya,crawford,wking]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@abhinavdahiya
Copy link
Contributor Author

@smarterclayton i forgot to ping you on this... do you think it might be security concerns opening bootstrap node kubelet 10250 port to 0.0.0.0 😇

@smarterclayton
Copy link
Contributor

smarterclayton commented Jan 22, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants