Instead of hard-coding two instances of the hostpathplugin which listen on
certain socket paths, the hostpathplugin now gets started through Pod exec as
needed. The advantage is that the helper code is in charge of socket naming,
just like it would be in real deployment.
One nuisance is that exec.StreamWithContext always complains in copyFromStdout
and copyFromStderr when the remote hostpathplugin gets killed via context
cancellation:
E0312 11:56:31.637669 289446 v2.go:167] "Unhandled Error" err="next reader: read tcp [::1]:59006->[::1]:6444: use of closed network connection" logger="UnhandledError"
E0312 11:56:31.637749 289446 v2.go:150] "Unhandled Error" err="next reader: read tcp [::1]:59006->[::1]:6444: use of closed network connection" logger="UnhandledError"
These can be ignored.
When supporting rolling updates, we cannot use the same fixed socket paths for
old and new pod. With the revised API, the caller no longer specifies the full
socket paths, only directories. The logic about how to name sockets then can be
in the helper.
While at it, avoid passing a context to the gRPC helper code when
all that the helper code needs is a logger. That leads to confusion
about whether cancellation has an effect.
The goal is to simplify writing DRA drivers. This is also a first step towards
supporting seamless upgrades.
DRA drivers no longer need to implement the kubelet plugin API
directly. Instead, the helper wraps an implementation of an interface. The
helper then provides common functionality:
- retrieve and validate ResourceClaims
- serialize gRPC calls (enabled by default, can be opted out)
- gRPC logging
The definition of that interface is meant to be comprehensive enough that a
correct DRA driver can be implemented by following the documentation of the
package, without having to cross-reference KEPs.
The DRAPlugin interface used to be the abstract API of the helper. Now it's
what the DRA driver kubelet plugin needs to implement. The helper is a concrete
Server struct with no exported fields. It only exports the methods that
drivers need when using the helper.
While at it, support for the v1alpha4 API gets removed from the helper, which
implies removing the corresponding E2E tests. The kubelet implementation will
be dropped separately.
Introduce a test suite that ensures declarative test cases
are fully tested and that validation errors are compared
with handwritten validation to ensure consistency.
Co-authored-by: Tim Hockin <thockin@google.com>
Co-authored-by: Aaron Prindle <aprindle@google.com>
Co-authored-by: Yongrui Lin <yongrlin@google.com>
After declarative validation is enabled in the ReplicationController
strategy in this way, the generated declarative validation code
in pkg/apis/core/v1/zz.generated.validations.go will be run
when the strategy validates ReplicationController.
Co-authored-by: Tim Hockin <thockin@google.com>
Co-authored-by: Aaron Prindle <aprindle@google.com>
Co-authored-by: Yongrui Lin <yongrlin@google.com>
Co-authored-by: David Eads <deads@redhat.com>
Ignore pre-existing bad IP/CIDR values in:
- pod.spec.podIP(s)
- pod.spec.hostIP(s)
- service.spec.externalIPs
- service.spec.clusterIP(s)
- service.spec.loadBalancerSourceRanges (and corresponding annotation)
- service.status.loadBalancer.ingress[].ip
- endpoints.subsets
- endpointslice.endpoints
- networkpolicy.spec.{ingress[].from[],egress[].to[]}.ipBlock
- ingress.status.loadBalancer.ingress[].ip
In the Endpoints and EndpointSlice case, if *any* endpoint IP is
changed, then the entire object must be valid; invalid IPs are only
allowed to remain in place for updates that don't change any IPs.
(e.g., changing the labels or annotations).
In most of the other cases, when the invalid IP is part of an array,
it can be moved around within the array without triggering
revalidation.
Add validation.IsValidIPForLegacyField and
validation.IsValidCIDRForLegacyField, which validate "legacy" IP/CIDR
fields correctly. Use them for all such fields (indirectly, via a
wrapper in pkg/apis/core/validation that handles the
StrictIPCIDRValidation feature gate correctly).
Change IsValidIP and IsValidCIDR to require strict parsing and
canonical form, and update the IPAddr, ServiceCIDR, and
NetworkDeviceData validation to make use of them.
This PR changes the TestListOptions setup to execute compaction before
we start apiserver allowing the test work with cache snapshots from
KEP-4988 by preventing creation of snapshots for compacted revisions.
While etcd compaction removes access to old revision, with KEP-4988
those revisions will be still available in watch cache. Implementing
compaction for watch cache doesn't make sense as it would only be
used for testing, making it unreliable.
To properly test how etcd and watch cache behaves on
compacted revisions we need to compact etcd before we start apiserver.
Because it used both IsValidIPv4Address and ValidateEndpointIP,
EndpointSlice validation produced duplicate error messages when given
an invalid IP. Fix this by calling IsValidIP first, and only doing the
other checks if that one fails.
Also, since no one else was using the IsValidIPv4Address and
IsValidIPv6Address methods anyway, just inline them into the
EndpointSlice validation, so we don't have to worry about "should they
do legacy or strict validation" later.
Split "ifaddr"-style ("192.168.1.5/24") validation out of IsValidCIDR.
Since there is currently only one field that uses this format, and it
already requires canonical form, IsValidInterfaceAddress requires
canonical form unconditionally.
Fix some incorrect test case names.
Use t.Run() in a few more places (to facilitate using
SetFeatureGateDuringTest later).
Clarify TestPodIPsValidation/TestHostIPsValidation (and fix
weird indentation).
There is not a single definition of "non-special IP" that makes sense
in all contexts. Rename ValidateNonSpecialIP to ValidateEndpointIP and
clarify that it shouldn't be used for other validations.
Also add a few more unit tests.