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

protobuf loses distinction between nil and empty slice #13419

Closed
liggitt opened this issue Mar 16, 2017 · 18 comments
Closed

protobuf loses distinction between nil and empty slice #13419

liggitt opened this issue Mar 16, 2017 · 18 comments
Assignees
Milestone

Comments

@liggitt
Copy link
Contributor

liggitt commented Mar 16, 2017

See kubernetes/kubernetes#43203

Origin has more resources that make use of that distinction than kube does

Need to resolve this before we release with protobuf storage enabled (or ship with controllers speaking protobuf)

Interesting fields

In this table, "Differentiated" indicates whether Origin treats nil and [] interchangeably.

Field Shipped omitempty Nil-persistable Differentiated Fix Notes
v1.BrokerTemplateInstanceSpec.BindingIDs No No No No Add omitempty Enforced by generated internal→external conversion
v1.BuildConfigSpec.Triggers Yes No No No False positive; Enforced by custom external→internal conversion
v1.BuildRequest.TriggeredBy Yes No No No False positive; Enforced by generated internal→external conversion
v1.BuildSpec.TriggeredBy Yes No No No False positive; Enforced by generated internal→external conversion
v1.ClusterRole.Rules Yes No No No False positive; Enforced by generated internal→external conversion
v1.ClusterRoleBinding.Subjects Yes No No No False positive; Enforced by generated internal→external conversion
v1.ClusterRoleScopeRestriction.Namespaces Yes No No No False positive; Enforced by generated internal→external conversion
v1.ClusterRoleScopeRestriction.RoleNames Yes No No No False positive; Enforced by generated internal→external conversion
v1.DeploymentDetails.Causes Yes No No No False positive; Enforced by generated internal→external conversion
v1.EgressNetworkPolicySpec.Egress Yes No No No False positive; Enforced by generated internal→external conversion
v1.ExecNewPodHook.Command Yes No No No False positive; Enforced by generated internal→external conversion
v1.GroupRestriction.Groups Yes No No No False positive; Enforced by generated internal→external conversion
v1.GroupRestriction.Selectors Yes No No No False positive; Enforced by generated internal→external conversion
v1.Image.DockerImageLayers Yes No Yes No TBD None
v1.ImageSignature.Content Yes No No No False positive; Enforced by generated internal→external conversion
v1.ImageSource.Paths Yes No No No False positive; Enforced by generated internal→external conversion
v1.LocalSubjectAccessReview.GroupsSlice Yes No No No False positive; Enforced by generated internal→external conversion
v1.PodSecurityPolicyReviewStatus.AllowedServiceAccounts Yes No No No False positive; Enforced by generated internal→external conversion
v1.PolicyRule.APIGroups Yes No No No False positive; Enforced by generated internal→external conversion
v1.PolicyRule.Resources Yes No No No False positive; Enforced by generated internal→external conversion
v1.PolicyRule.Verbs Yes No No No False positive; Enforced by generated internal→external conversion
v1.ResourceAccessReviewResponse.GroupsSlice Yes No No No False positive; Enforced by generated internal→external conversion
v1.ResourceAccessReviewResponse.UsersSlice Yes No No No False positive; Enforced by generated internal→external conversion
v1.Role.Rules Yes No No No False positive; Enforced by generated internal→external conversion
v1.RoleBinding.Subjects Yes No No No False positive; Enforced by generated internal→external conversion
v1.RouteStatus.Ingress Yes No No No False positive; Enforced by generated internal→external conversion
v1.ServiceAccountRestriction.Namespaces Yes No No No False positive; Enforced by generated internal→external conversion
v1.ServiceAccountRestriction.ServiceAccounts Yes No No No False positive; Enforced by generated internal→external conversion
v1.SubjectAccessReview.GroupsSlice Yes No No No False positive; Enforced by generated internal→external conversion
v1.SubjectRulesReviewSpec.Groups Yes No No No False positive; Enforced by generated internal→external conversion
v1.SubjectRulesReviewStatus.Rules Yes No No No False positive; Enforced by generated internal→external conversion
v1.Template.Objects Yes No No No False positive; Enforced by generated internal→external conversion
v1.TemplateInstanceStatus.Conditions Yes No No No False positive; Enforced by generated internal→external conversion
v1.User.Groups Yes No No No False positive; Enforced by generated internal→external conversion
v1.User.Identities Yes No No No False positive; Enforced by generated internal→external conversion
v1.UserRestriction.Groups Yes No No No False positive; Enforced by generated internal→external conversion
v1.UserRestriction.Users Yes No No No False positive; Enforced by generated internal→external conversion
v1.UserRestriction.Selectors Yes No No No False positive; Enforced by generated internal→external conversion
@liggitt liggitt added this to the 1.6.0 milestone Mar 16, 2017
@pweil- pweil- added component/restapi kind/bug Categorizes issue or PR as related to a bug. priority/P1 labels Mar 20, 2017
@liggitt
Copy link
Contributor Author

liggitt commented Mar 21, 2017

Security Context Constraints needs the protobuf wrapper fix to make this nullable

	// assume a nil volume slice is allowing everything for backwards compatibility
	if defaultAllowedVolumes == nil {
		defaultAllowedVolumes = sets.NewString(string(FSTypeAll))
	}

@liggitt
Copy link
Contributor Author

liggitt commented Mar 21, 2017

type SelfSubjectRulesReviewSpec struct {
	// Scopes to use for the evaluation.  Empty means "use the unscoped (full) permissions of the user/groups".
	// Nil for a self-SubjectRulesReview, means "use the scopes on this request".
	// Nil for a regular SubjectRulesReview, means the same as empty.
	Scopes []string
}

edit: nevermind, already has proto nullable fix

@liggitt
Copy link
Contributor Author

liggitt commented Mar 21, 2017

func SetDefaults_DeploymentConfigSpec(obj *DeploymentConfigSpec) {
	if obj.Triggers == nil {
		obj.Triggers = []DeploymentTriggerPolicy{
			{Type: DeploymentTriggerOnConfigChange},
		}
	}

edit: nevermind, already has proto nullable fix

@0xmichalis
Copy link
Contributor

This seems like a problem for triggers because empty slice means "no triggers". Will DCs with "no triggers" end up being defaulted to ConfigChange once they do the first round trip with the new storage format?

@liggitt
Copy link
Contributor Author

liggitt commented Mar 22, 2017

triggers aliases the slice to a different type, and annotates it as nullable for protobuf, which does crazy things to make protobuf be able to distinguish between null and []

@0xmichalis
Copy link
Contributor

Ok, that change makes sense now.

@mfojtik
Copy link
Contributor

mfojtik commented Mar 24, 2017

@liggitt i guess we need to pick kubernetes/kubernetes#43422 for 1.6?

@sttts @ncdc can you pick this for the rebase?

@ncdc
Copy link
Contributor

ncdc commented Mar 24, 2017 via email

@mfojtik mfojtik assigned ncdc and unassigned mfojtik Mar 27, 2017
@mfojtik
Copy link
Contributor

mfojtik commented Mar 27, 2017

@ncdc feel free to close it via rebase PR merge

@ncdc
Copy link
Contributor

ncdc commented Mar 28, 2017

Not a release blocker right now (but it will be once the 1.6 rebase lands). Lowering priority to get this off the blocker list in the immediate term.

@sttts sttts mentioned this issue Apr 6, 2017
13 tasks
@ncdc
Copy link
Contributor

ncdc commented Apr 19, 2017

From build's CommonSpec:

        // NodeSelector is a selector which must be true for the build pod to fit on a node
	// If nil, it can be overridden by default build nodeselector values for the cluster.
	// If set to an empty map or a map with any values, default build nodeselector values
	// are ignored.
	NodeSelector map[string]string

@liggitt
Copy link
Contributor Author

liggitt commented May 13, 2017

SCC Volumes field is still missing the nullable fix

@liggitt
Copy link
Contributor Author

liggitt commented May 13, 2017

here's the list of all slice fields in origin that do not specify omitempty. we need to review this list and:

  1. mark as false positives any which validation does not allow to be persisted empty
  2. add omitempty to as many as we can compatibly
  3. add wrapper types to marshal the rest to [], even when nil (and figure out if that breaks protobuf for old clients)
  • v1.BrokerTemplateInstanceSpec.BindingIDs is a slice of type []string
  • v1.BuildConfigSpec.Triggers is a slice of type []v1.BuildTriggerPolicy
  • v1.BuildRequest.TriggeredBy is a slice of type []v1.BuildTriggerCause
  • v1.BuildSpec.TriggeredBy is a slice of type []v1.BuildTriggerCause
  • v1.ClusterRole.Rules is a slice of type []v1.PolicyRule
  • v1.ClusterRoleBinding.Subjects is a slice of type []v1.ObjectReference
  • v1.ClusterRoleScopeRestriction.Namespaces is a slice of type []string
  • v1.ClusterRoleScopeRestriction.RoleNames is a slice of type []string
  • v1.DeploymentDetails.Causes is a slice of type []v1.DeploymentCause
  • v1.EgressNetworkPolicySpec.Egress is a slice of type []v1.EgressNetworkPolicyRule
  • v1.ExecNewPodHook.Command is a slice of type []string
  • v1.GroupRestriction.Groups is a slice of type []string
  • v1.GroupRestriction.Selectors is a slice of type []v1.LabelSelector
  • v1.Image.DockerImageLayers is a slice of type []v1.ImageLayer
  • v1.ImageSignature.Content is a slice of type []uint8
  • v1.ImageSource.Paths is a slice of type []v1.ImageSourcePath
  • v1.LocalSubjectAccessReview.GroupsSlice is a slice of type []string
  • v1.PodSecurityPolicyReviewStatus.AllowedServiceAccounts is a slice of type []v1.ServiceAccountPodSecurityPolicyReviewStatus
  • v1.PolicyRule.APIGroups is a slice of type []string
  • v1.PolicyRule.Resources is a slice of type []string
  • v1.PolicyRule.Verbs is a slice of type []string
  • v1.ResourceAccessReviewResponse.GroupsSlice is a slice of type []string
  • v1.ResourceAccessReviewResponse.UsersSlice is a slice of type []string
  • v1.Role.Rules is a slice of type []v1.PolicyRule
  • v1.RoleBinding.Subjects is a slice of type []v1.ObjectReference
  • v1.RouteStatus.Ingress is a slice of type []v1.RouteIngress
  • v1.SecurityContextConstraints.AllowedCapabilities is a slice of type []v1.Capability
  • v1.SecurityContextConstraints.DefaultAddCapabilities is a slice of type []v1.Capability
  • v1.SecurityContextConstraints.RequiredDropCapabilities is a slice of type []v1.Capability
  • v1.SecurityContextConstraints.Volumes is a slice of type []v1.FSType
  • v1.ServiceAccountRestriction.Namespaces is a slice of type []string
  • v1.ServiceAccountRestriction.ServiceAccounts is a slice of type []v1.ServiceAccountReference
  • v1.SubjectAccessReview.GroupsSlice is a slice of type []string
  • v1.SubjectRulesReviewSpec.Groups is a slice of type []string
  • v1.SubjectRulesReviewStatus.Rules is a slice of type []v1.PolicyRule
  • v1.Template.Objects is a slice of type []runtime.RawExtension
  • v1.TemplateInstanceStatus.Conditions is a slice of type []v1.TemplateInstanceCondition
  • v1.User.Groups is a slice of type []string
  • v1.User.Identities is a slice of type []string
  • v1.UserRestriction.Groups is a slice of type []string
  • v1.UserRestriction.Selectors is a slice of type []v1.LabelSelector
  • v1.UserRestriction.Users is a slice of type []string

@liggitt
Copy link
Contributor Author

liggitt commented May 15, 2017

@bparees is it important for the build instantiate API to treat nil TriggeredBy fields differently than set-but-empty TriggeredBy fields?

// Create instantiates a new build from a build configuration
func (s *InstantiateREST) Create(ctx apirequest.Context, obj runtime.Object) (runtime.Object, error) {
	if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil {
		return nil, err
	}

	request := obj.(*buildapi.BuildRequest)
	if request.TriggeredBy == nil {
		buildTriggerCauses := []buildapi.BuildTriggerCause{}
		request.TriggeredBy = append(buildTriggerCauses,
			buildapi.BuildTriggerCause{
				Message: buildapi.BuildTriggerCauseManualMsg,
			},
		)
	}
	return s.generator.Instantiate(ctx, request)
}

@bparees
Copy link
Contributor

bparees commented May 15, 2017

No, I don't think so. If it's set-but-empty we'd want to do the same thing as we're doing for nil here, add in the "manual cause" triggercause.

@0xmichalis
Copy link
Contributor

v1.DeploymentDetails.Causes is a slice of type []v1.DeploymentCause

doesn't care about nil vs empty

@sdodson
Copy link
Member

sdodson commented May 30, 2017

@ingvagabund relevant to your interests

@liggitt
Copy link
Contributor Author

liggitt commented Jun 20, 2017

fixed SCC.Volumes field, release noted the behavior change for other fields in openshift/openshift-docs#4021 (comment)

@liggitt liggitt closed this as completed Jun 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants