Skip to content

Commit

Permalink
Merge pull request #689 from njhale/fix-ip-race
Browse files Browse the repository at this point in the history
fix(subscriptions): fix race between subscription sync and cache
  • Loading branch information
openshift-merge-robot authored Jan 29, 2019
2 parents 5eb7ae5 + d899968 commit 88ecace
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 38 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ container-mockgen:
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/client-go/listers/. ./pkg/fakes/client-go/listers
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/operatorlisterfakes/. ./pkg/lib/operatorlister/operatorlisterfakes
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient/mock_client.go ./pkg/lib/operatorclient/mock_client.go
docker cp temp-mockgen:/go/src/github.com/operator-framework/operator-lifecycle-manager/pkg/fakes/. ./pkg/fakes/.
docker rm temp-mockgen

# Must be run in gopath: https://github.com/kubernetes/kubernetes/issues/67566
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module github.com/operator-framework/operator-lifecycle-manager

require (
github.com/coreos/bbolt v1.3.2 // indirect
github.com/coreos/etcd v3.3.10+incompatible // indirect
github.com/coreos/go-semver v0.2.0
github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 // indirect
Expand All @@ -12,6 +13,7 @@ require (
github.com/go-openapi/strfmt v0.18.0 // indirect
github.com/go-openapi/validate v0.18.0 // indirect
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
github.com/golang/mock v1.1.1
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf // indirect
Expand All @@ -37,6 +39,7 @@ require (
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.etcd.io/bbolt v1.3.2 // indirect
go.uber.org/atomic v1.3.2 // indirect
go.uber.org/multierr v1.1.0 // indirect
go.uber.org/zap v1.9.1 // indirect
Expand Down
12 changes: 9 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.0 h1:HIgH5xUWXT914HCI671AxuTTqjj64UOFr7pHn48LUTI=
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.9+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
github.com/coreos/etcd v3.3.10+incompatible h1:KjVWqrZ5U0wa3CxY2AxlH6/UcB+PK2td1DcsYhA+HRs=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
Expand Down Expand Up @@ -89,6 +91,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff h1:kOkM9whyQYodu09SJ6W3NCsHG7crFaJILQ22Gozp3lg=
github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand All @@ -107,7 +111,7 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f h1:ShTPMJQes6tubcjzGMODIVG5hlrCeImaBnZzKF2N8SM=
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:BWIsLfhgKhV5g/oF34aRjniBHLTZe5DNekSjbAjIS6c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
Expand Down Expand Up @@ -206,6 +210,8 @@ github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljT
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
Expand Down Expand Up @@ -294,5 +300,5 @@ k8s.io/kube-aggregator v0.0.0-20181204002017-122bac39d429/go.mod h1:8sbzT4QQKDEm
k8s.io/kube-openapi v0.0.0-20181031203759-72693cb1fadd h1:ggv/Vfza0i5xuhUZyYyxcc25AmQvHY8Zi1C2m8WgBvA=
k8s.io/kube-openapi v0.0.0-20181031203759-72693cb1fadd/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kubernetes v1.11.7-beta.0.0.20181219023948-b875d52ea96d/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2 h1:CzIOMOEjH+sQw35LY1Gl0jwthkyOojzaq2HIeYZYOrM=
k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2 h1:Q4hIsjqTbRprTaPk+gVDUuVipXpGJtTz7Lg2FS3xpmw=
k8s.io/kubernetes v1.11.8-beta.0.0.20190124204751-3a10094374f2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
37 changes: 37 additions & 0 deletions pkg/api/apis/operators/v1alpha1/installplan_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,43 @@ type Step struct {
Status StepStatus `json:"status"`
}

// ManifestsMatch returns true if the CSV manifests in the StepResources of the given list of steps
// matches those in the InstallPlanStatus.
func (s *InstallPlanStatus) CSVManifestsMatch(steps []*Step) bool {
if s.Plan == nil && steps == nil {
return true
}
if s.Plan == nil || steps == nil {
return false
}

manifests := make(map[string]struct{})
for _, step := range s.Plan {
resource := step.Resource
if resource.Kind != ClusterServiceVersionKind {
continue
}
manifests[resource.Manifest] = struct{}{}
}

for _, step := range steps {
resource := step.Resource
if resource.Kind != ClusterServiceVersionKind {
continue
}
if _, ok := manifests[resource.Manifest]; !ok {
return false
}
delete(manifests, resource.Manifest)
}

if len(manifests) == 0 {
return true
}

return false
}

func (s *Step) String() string {
return fmt.Sprintf("%s: %s (%s)", s.Resolving, s.Resource, s.Status)
}
Expand Down
70 changes: 47 additions & 23 deletions pkg/controller/operators/catalog/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const (
serviceKind = "Service"
roleKind = "Role"
roleBindingKind = "RoleBinding"
generatedByKey = "olm.generated-by"
)

// for test stubbing and for ensuring standardization of timezones to UTC
Expand Down Expand Up @@ -578,9 +579,9 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
break
}
}
installplanReference, err := o.createInstallPlan(namespace, subs, installPlanApproval, steps)
installplanReference, err := o.ensureInstallPlan(logger, namespace, subs, installPlanApproval, steps)
if err != nil {
logger.WithError(err).Debug("error creating installplan")
logger.WithError(err).Debug("error ensuring installplan")
return err
}

Expand Down Expand Up @@ -675,33 +676,27 @@ func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub

// check if there's an installplan that created this subscription (only if it doesn't have a reference yet)
// this indicates it was newly resolved by another operator, and we should reference that installplan in the status
ips, err := o.lister.OperatorsV1alpha1().InstallPlanLister().InstallPlans(sub.GetNamespace()).List(labels.Everything())
if err != nil {
logger.WithError(err).Debug("couldn't get installplans")
// if we can't list, just continue processing
ipName, ok := sub.GetAnnotations()[generatedByKey]
if !ok {
return sub, nil
}

out := sub.DeepCopy()
ip, err := o.lister.OperatorsV1alpha1().InstallPlanLister().InstallPlans(sub.GetNamespace()).Get(ipName)
if err != nil {
logger.WithField("installplan", ipName).Warn("unable to get installplan from cache")
return nil, err
}
logger.WithField("installplan", ipName).Debug("found installplan that generated subscription")

for _, ip := range ips {
for _, step := range ip.Status.Plan {
// TODO: is this enough? should we check equality of pkg/channel?
if step != nil && step.Resource.Kind == v1alpha1.SubscriptionKind && step.Resource.Name == sub.GetName() {
logger.WithField("installplan", ip.GetName()).Debug("found subscription in steps of existing installplan")
out.Status.Install = o.referenceForInstallPlan(ip)
out.Status.State = v1alpha1.SubscriptionStateUpgradePending
if updated, err := o.client.OperatorsV1alpha1().Subscriptions(sub.GetNamespace()).UpdateStatus(out); err != nil {
return nil, err
} else {
return updated, nil
}
}
}
out := sub.DeepCopy()
out.Status.Install = o.referenceForInstallPlan(ip)
out.Status.State = v1alpha1.SubscriptionStateUpgradePending
updated, err := o.client.OperatorsV1alpha1().Subscriptions(sub.GetNamespace()).UpdateStatus(out)
if err != nil {
return nil, err
}
logger.Debug("did not find subscription in steps of existing installplan")

return sub, nil
return updated, nil
}

func (o *Operator) ensureSubscriptionCSVState(logger *logrus.Entry, sub *v1alpha1.Subscription) (*v1alpha1.Subscription, error) {
Expand Down Expand Up @@ -746,6 +741,28 @@ func (o *Operator) updateSubscriptionSetInstallPlanState(namespace string, subs
return nil
}

func (o *Operator) ensureInstallPlan(logger *logrus.Entry, namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step) (*v1alpha1.InstallPlanReference, error) {
if len(steps) == 0 {
return nil, nil
}

// Check if any existing installplans are creating the same resources
installPlans, err := o.lister.OperatorsV1alpha1().InstallPlanLister().InstallPlans(namespace).List(labels.Everything())
if err != nil {
return nil, err
}

for _, installPlan := range installPlans {
if installPlan.Status.CSVManifestsMatch(steps) {
logger.Infof("found InstallPlan with matching manifests: %s", installPlan.GetName())
return o.referenceForInstallPlan(installPlan), nil
}
}
logger.Warn("no installplan found with matching manifests, creating new one")

return o.createInstallPlan(namespace, subs, installPlanApproval, steps)
}

func (o *Operator) createInstallPlan(namespace string, subs []*v1alpha1.Subscription, installPlanApproval v1alpha1.Approval, steps []*v1alpha1.Step) (*v1alpha1.InstallPlanReference, error) {
if len(steps) == 0 {
return nil, nil
Expand Down Expand Up @@ -1001,6 +1018,13 @@ func (o *Operator) ExecutePlan(plan *v1alpha1.InstallPlan) error {
return errorwrap.Wrapf(err, "error parsing step manifest: %s", step.Resource.Name)
}

// Add the InstallPlan's name as an annotation
if annotations := sub.GetAnnotations(); annotations != nil {
annotations[generatedByKey] = plan.GetName()
} else {
sub.SetAnnotations(map[string]string{generatedByKey: plan.GetName()})
}

// Attempt to create the Subscription
sub.SetNamespace(namespace)
_, err = o.client.OperatorsV1alpha1().Subscriptions(sub.GetNamespace()).Create(&sub)
Expand Down
5 changes: 4 additions & 1 deletion pkg/controller/operators/catalog/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,8 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
podInformer := informerFactory.Core().V1().Pods()
configMapInformer := informerFactory.Core().V1().ConfigMaps()
subscriptionInformer := externalversions.NewSharedInformerFactoryWithOptions(clientFake, wakeupInterval, externalversions.WithNamespace(namespace)).Operators().V1alpha1().Subscriptions()

installPlanInformer := externalversions.NewSharedInformerFactoryWithOptions(clientFake, wakeupInterval, externalversions.WithNamespace(namespace)).Operators().V1alpha1().InstallPlans()

// register informers
registryInformers := []cache.SharedIndexInformer{
roleInformer.Informer(),
Expand All @@ -498,6 +499,7 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
podInformer.Informer(),
configMapInformer.Informer(),
subscriptionInformer.Informer(),
installPlanInformer.Informer(),
}

// register listers
Expand All @@ -509,6 +511,7 @@ func NewFakeOperator(clientObjs []runtime.Object, k8sObjs []runtime.Object, extO
lister.CoreV1().RegisterPodLister(namespace, podInformer.Lister())
lister.CoreV1().RegisterConfigMapLister(namespace, configMapInformer.Lister())
lister.OperatorsV1alpha1().RegisterSubscriptionLister(namespace, subscriptionInformer.Lister())
lister.OperatorsV1alpha1().RegisterInstallPlanLister(namespace, installPlanInformer.Lister())

// Create the new operator
queueOperator, err := queueinformer.NewOperatorFromClient(opClientFake, logrus.New())
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/registry/reconciler/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ func (s *configMapCatalogSourceDecorator) Pod(image string) *v1.Pod {
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
},
},
InitialDelaySeconds: 5,
InitialDelaySeconds: 1,
},
LivenessProbe: &v1.Probe{
Handler: v1.Handler{
Exec: &v1.ExecAction{
Command: []string{"grpc_health_probe", "-addr=localhost:50051"},
},
},
InitialDelaySeconds: 10,
InitialDelaySeconds: 2,
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/lib/operatorclient/mock_client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions test/e2e/installplan_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
fetchedInstallPlan, err := fetchInstallPlan(t, crc, installPlanName, completeOrFailedFunc)
require.NoError(t, err)
t.Logf("Install plan %s fetched with status %s", fetchedInstallPlan.GetName(), fetchedInstallPlan.Status.Phase)
require.True(t, completeOrFailedFunc(fetchedInstallPlan))
require.Equal(t, v1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase)

// Ensure that the desired resources have been created
expectedSteps := map[registry.ResourceKey]struct{}{
Expand Down Expand Up @@ -561,7 +561,7 @@ func TestCreateInstallPlanWithPreExistingCRDOwners(t *testing.T) {
require.Equal(t, 0, len(expectedSteps), "Actual resource steps do not match expected")

// Update the subscription resource to point to the beta CSV
err = crc.OperatorsV1alpha1().Subscriptions(testNamespace).Delete(subscriptionName, metav1.NewDeleteOptions(0))
err = crc.OperatorsV1alpha1().Subscriptions(testNamespace).DeleteCollection(metav1.NewDeleteOptions(0), metav1.ListOptions{})
require.NoError(t, err)

// existing cleanup should remove this
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func createFieldNotEqualSelector(field string, names ...string) string {
func cleanupOLM(t *testing.T, namespace string) {
var immediate int64 = 0
crc := newCRClient(t)
//c := newKubeClient(t)
c := newKubeClient(t)

// Cleanup non persistent OLM CRs
t.Log("cleaning up any remaining non persistent resources...")
Expand All @@ -250,7 +250,7 @@ func cleanupOLM(t *testing.T, namespace string) {

// error: the server does not allow this method on the requested resource
// Cleanup non persistent configmaps
//require.NoError(t, c.KubernetesInterface().CoreV1().ConfigMaps(namespace).DeleteCollection(deleteOptions, metav1.ListOptions{FieldSelector: nonPersistentConfigMapsFieldSelector}))
require.NoError(t, c.KubernetesInterface().CoreV1().Pods(namespace).DeleteCollection(deleteOptions, metav1.ListOptions{}))
}

func buildCatalogSourceCleanupFunc(t *testing.T, crc versioned.Interface, namespace string, catalogSource *v1alpha1.CatalogSource) cleanupFunc {
Expand Down
2 changes: 1 addition & 1 deletion vendor/github.com/golang/groupcache/lru/lru.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
# github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/glog
# github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff
# github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef
github.com/golang/groupcache/lru
# github.com/golang/mock v1.1.1
github.com/golang/mock/mockgen
Expand Down Expand Up @@ -336,20 +336,21 @@ k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/validation
k8s.io/apimachinery/pkg/util/yaml
k8s.io/apimachinery/pkg/util/framer
k8s.io/apimachinery/pkg/util/rand
k8s.io/apimachinery/pkg/apis/meta/v1beta1
k8s.io/apimachinery/pkg/util/mergepatch
k8s.io/apimachinery/third_party/forked/golang/json
k8s.io/apimachinery/pkg/api/validation/path
k8s.io/apimachinery/pkg/apis/meta/v1/validation
k8s.io/apimachinery/pkg/util/uuid
k8s.io/apimachinery/third_party/forked/golang/reflect
k8s.io/apimachinery/pkg/util/rand
# k8s.io/apiserver v0.0.0-20181026151315-13cfe3978170
k8s.io/apiserver/pkg/server
k8s.io/apiserver/pkg/util/logs
k8s.io/apiserver/pkg/authentication/serviceaccount
k8s.io/apiserver/pkg/authentication/user
k8s.io/apiserver/pkg/authorization/authorizer
k8s.io/apiserver/pkg/storage/names
k8s.io/apiserver/pkg/endpoints/openapi
k8s.io/apiserver/pkg/registry/rest
k8s.io/apiserver/pkg/server/options
Expand Down Expand Up @@ -379,7 +380,6 @@ k8s.io/apiserver/pkg/server/mux
k8s.io/apiserver/pkg/server/routes
k8s.io/apiserver/pkg/server/storage
k8s.io/apiserver/pkg/util/feature
k8s.io/apiserver/pkg/storage/names
k8s.io/apiserver/pkg/admission/initializer
k8s.io/apiserver/pkg/admission/metrics
k8s.io/apiserver/pkg/apis/apiserver
Expand Down

0 comments on commit 88ecace

Please sign in to comment.