Skip to content

Generated protobuf and pb.go for batch/v1alpha1/Job does not compile #220

@zwx4d6

Description

@zwx4d6

Describe the bug

I'm trying to use the batch/Job as part of protobuf-based API and golang service. Different from k8s.io/api packages, this package does not provide pre-built protobuf nor generated pb.go files, so I have to generate them by myself. The following descriptions are tested on v1.12.2, but as of v1.13.0 the corresponding lines are not changed.

The generator is k8s.io/code-generator/cmd/go-to-protobuf@v0.32.0.

  1. JobSpec.Plugins is typed as map[string][]string, whose value type []string cannot be directly translated to protobuf. repeated string is not a valid protobuf map value type, as specified in protocol buffers documentation. The generated type is map[string]string, so pb.go does not compile. K8s protobuf generator does have corresponding (old) issues like Cannot generate protobuf for map[string][]string, blocks authorization from being generated kubernetes/kubernetes#27259, and the mitigation is an extra layer of type definition type PluginArgs []string, like in Cannot generate protobuf for map[string][]string kubernetes/kubernetes#46024 (comment).
    Generated message piece:
// JobSpec describes how the job execution will look like and when it will actually run.
message JobSpec {
  //...

  // Specifies the plugin of job
  // Key is plugin name, value is the arguments of the plugin
  // +optional
  map<string, string> plugins = 6;

  // ...
}

Generated go code piece, commented by me:

			if m.Plugins == nil {
				m.Plugins = make(map[string]string) // type error here, m.Plugins is `map[string][]string`
			}
			var mapkey string
			var mapvalue string
// parsing byte buffer omitted
			m.Plugins[mapkey] = mapvalue
  1. NetworkTopologySpec.HighestTierAllowed is typed as *int, but in the generated protobuf (thus pb.go) it is considered a int64, so go compiler fails to assign int64 to int. This might be easier to fix by explicitly assigning fixed width type int32 or int64.
    Generated message:
message NetworkTopologySpec {
  // Mode specifies the mode of the network topology constrain.
  // +kubebuilder:default=hard
  // +optional
  optional string mode = 1;

  // HighestTierAllowed specifies the highest tier that a job allowed to cross when scheduling.
  // +kubebuilder:default=1
  // +optional
  optional int64 highestTierAllowed = 2;
}

Generated go code piece, commented by me:

			var v int64 // here defines value
// parsing byte buffer omitted
			m.HighestTierAllowed = &v // type error here, m.HighestTierAllowed is `*int`

Proposed Fix

I'm not sure whether the changes are possible because they may be breaking.

  1. Add type definition type PluginArgs []string with proper annotations and change type of JobSpec.Plugins to map[string]PluginArgs.
  2. Change type of NetworkTopologySpec.HighestTierAllowed to int32 or int64.
19a20,21
>       "fmt"
> 
78c80
<       Plugins map[string][]string `json:"plugins,omitempty" protobuf:"bytes,6,opt,name=plugins"`
---
>       Plugins map[string]PluginArgs `json:"plugins,omitempty" protobuf:"bytes,6,opt,name=plugins"`
116a119,127
> // PluginArgs represents plugin argument list.
> // +protobuf.nullable=true
> // +protobuf.options.(gogoproto.goproto_stringer)=false
> type PluginArgs []string
> 
> func (a PluginArgs) String() string {
>       return fmt.Sprintf("%v", []string(a))
> }
> 
139c150
<       HighestTierAllowed *int `json:"highestTierAllowed,omitempty" protobuf:"bytes,2,opt,name=highestTierAllowed"`
---
>       HighestTierAllowed *int32 `json:"highestTierAllowed,omitempty" protobuf:"bytes,2,opt,name=highestTierAllowed"`

To Reproduce

Steps to reproduce the behavior:

  1. Create a folder layout like K8s project, e.g. /code/staging/src/{k8s.io/api, k8s.io/apimachinery, volcano.sh/apis, github.com/gogo/protobuf} and copy corresponding source files. Absolute path is needed in later commands.

Though github.com/gogo/protobuf is archived, the removal from k8s proto generator is still in progress.

  1. Install k8s.io/code-generator/cmd/go-to-protobuf and the plugin k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo, and make sure protoc finds the plugin.
  2. Inside the staging/src/volcano.sh/apis dir, run the generator: go-to-protobuf -v 5 --packages volcano.sh/apis/pkg/apis/bus/v1alpha1,volcano.sh/apis/pkg/apis/batch/v1alpha1 --apimachinery-packages -k8s.io/apimachinery/pkg/apis/meta/v1,-k8s.io/apimachinery/pkg/util/intstr,-k8s.io/apimachinery/pkg/api/resource,-k8s.io/apimachinery/pkg/runtime/schema,-k8s.io/apimachinery/pkg/runtime,-k8s.io/apimachinery/pkg/apis/meta/v1beta1,-k8s.io/apimachinery/pkg/apis/testapigroup/v1,-k8s.io/api/core/v1 --output-dir /code/staging/src --proto-import /code/staging/src --proto-import /code/staging/src/github.com/gogo/protobuf/protobuf. The leading - of k8s packages means their proto should not be generated (because they are already there).
  3. Navigate to staging/src/volcano.sh/apis/pkg/apis/batch/v1alpha1, check generated.proto and generated.pb.go files, or just try to compile with go build:
❯ go build ./...
# volcano.sh/apis/pkg/apis/batch/v1alpha1
pkg/apis/batch/v1alpha1/generated.pb.go:767:13: invalid argument: arguments to copy dAtA[i:] (value of type []byte) and v (variable of type []string) have different element types byte and string
pkg/apis/batch/v1alpha1/generated.pb.go:2546:17: cannot use make(map[string]string) (value of type map[string]string) as map[string][]string value in assignment
pkg/apis/batch/v1alpha1/generated.pb.go:2641:24: cannot use mapvalue (variable of type string) as []string value in assignment
pkg/apis/batch/v1alpha1/generated.pb.go:3900:27: cannot use &v (value of type *int64) as *int value in assignment

Expected behavior

The generated protobuf aligns with CRD structs and generated go code compiles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions