From 78d6dad21f3400ceb764f7ca7b035dbebfaa9404 Mon Sep 17 00:00:00 2001 From: dplore Date: Mon, 18 Nov 2024 13:38:13 -0800 Subject: [PATCH] clean up additional feature.textproto tools, fix static checks --- .github/workflows/protobufs.yml | 45 ++ Makefile | 8 - .../otg_config_helpers/otgconfighelpers.go | 8 + proto/feature.proto | 109 --- proto/feature_go_proto/feature.pb.go | 682 ------------------ tools/clone_oc_public.sh | 7 - tools/validate_paths.go | 422 ----------- 7 files changed, 53 insertions(+), 1228 deletions(-) create mode 100644 .github/workflows/protobufs.yml delete mode 100644 proto/feature.proto delete mode 100644 proto/feature_go_proto/feature.pb.go delete mode 100755 tools/clone_oc_public.sh delete mode 100644 tools/validate_paths.go diff --git a/.github/workflows/protobufs.yml b/.github/workflows/protobufs.yml new file mode 100644 index 00000000000..ead10627204 --- /dev/null +++ b/.github/workflows/protobufs.yml @@ -0,0 +1,45 @@ +name: Protobufs + +on: + push: + branches: [ main ] + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + validate_protobufs: + name: Validate Protobufs + runs-on: ubuntu-latest + steps: + - name: Install go + uses: actions/setup-go@v2 + with: + go-version: '1.21' + - name: Checkout code + uses: actions/checkout@v3 + - name: Cache + uses: actions/cache@v3 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ github.job }}-${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} + - name: Install protobuf + uses: arduino/setup-protoc@v1 + with: + version: '3.x' + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Lint protobufs + run: | + go install github.com/googleapis/api-linter/cmd/api-linter@latest + make protoimports + cd protobuf-import + find github.com/openconfig/featureprofiles/ -name \*.proto -exec api-linter --disable-rule all --enable-rule core {} \+ + - name: Validate textprotos + run: | + go install github.com/bstoll/textproto-validator@latest + make protoimports + for i in `find . -name \*.textproto`; do + textproto-validator -I ./protobuf-import $i + done diff --git a/Makefile b/Makefile index c2232e85166..1e869a2aa69 100644 --- a/Makefile +++ b/Makefile @@ -18,9 +18,6 @@ GO_PROTOS:=proto/feature_go_proto/feature.pb.go proto/metadata_go_proto/metadata .PHONY: all clean protos validate_paths protoimports all: openconfig_public protos validate_paths -openconfig_public: - tools/clone_oc_public.sh openconfig_public - protos: $(GO_PROTOS) protoimports: @@ -39,11 +36,6 @@ protoimports: go list -f '{{ .Dir }} protobuf-import/{{ .Path }}' -m github.com/openconfig/kne | xargs -L1 -- ln -s ln -s $(ROOT_DIR) protobuf-import/github.com/openconfig/featureprofiles -proto/feature_go_proto/feature.pb.go: proto/feature.proto - mkdir -p proto/feature_go_proto - protoc --proto_path=proto --go_out=./ --go_opt=Mfeature.proto=proto/feature_go_proto feature.proto - goimports -w proto/feature_go_proto/feature.pb.go - proto/metadata_go_proto/metadata.pb.go: proto/metadata.proto protoimports mkdir -p proto/metadata_go_proto protoc -I='protobuf-import' --proto_path=proto --go_out=./ --go_opt=Mmetadata.proto=proto/metadata_go_proto metadata.proto diff --git a/internal/otg_helpers/otg_config_helpers/otgconfighelpers.go b/internal/otg_helpers/otg_config_helpers/otgconfighelpers.go index 862d5381fa6..b7676ef05c8 100644 --- a/internal/otg_helpers/otg_config_helpers/otgconfighelpers.go +++ b/internal/otg_helpers/otg_config_helpers/otgconfighelpers.go @@ -64,6 +64,8 @@ type InterfaceProperties struct { // ConfigureOtgNetworkInterface configures the network interface. func ConfigureOtgNetworkInterface(t *testing.T, top gosnappi.Config, ate *ondatra.ATEDevice, a *Port) { + t.Helper() + if a.Islag { ConfigureOtgLag(t, top, ate, a) } else { @@ -76,6 +78,8 @@ func ConfigureOtgNetworkInterface(t *testing.T, top gosnappi.Config, ate *ondatr // ConfigureOtgLag configures the aggregate port. func ConfigureOtgLag(t *testing.T, top gosnappi.Config, ate *ondatra.ATEDevice, a *Port) { + t.Helper() + agg := top.Lags().Add().SetName(a.Name) agg.Protocol().Lacp().SetActorKey(1).SetActorSystemPriority(1).SetActorSystemId(a.AggMAC) for index, portName := range a.MemberPorts { @@ -87,6 +91,8 @@ func ConfigureOtgLag(t *testing.T, top gosnappi.Config, ate *ondatra.ATEDevice, // ConfigureOtgLagMemberPort configures the member port in the LAG. func ConfigureOtgLagMemberPort(agg gosnappi.Lag, portID string, a *Port, index int) { + t.Helper() + lagPort := agg.Ports().Add().SetPortName(portID) lagPort.Ethernet().SetMac(a.AggMAC).SetName(a.Name + "-" + portID) lagPort.Lacp().SetActorActivity("active").SetActorPortNumber(uint32(index) + 1).SetActorPortPriority(1).SetLacpduTimeout(0) @@ -94,6 +100,8 @@ func ConfigureOtgLagMemberPort(agg gosnappi.Lag, portID string, a *Port, index i // ConfigureOtgInterface configures the Ethernet for the LAG or subinterface. func ConfigureOtgInterface(t *testing.T, top gosnappi.Config, intf *InterfaceProperties, a *Port) { + t.Helper() + dev := top.Devices().Add().SetName(intf.Name + ".Dev") eth := dev.Ethernets().Add().SetName(intf.Name + ".Eth").SetMac(intf.Mac) if a.Islag { diff --git a/proto/feature.proto b/proto/feature.proto deleted file mode 100644 index 265b02c391f..00000000000 --- a/proto/feature.proto +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -// Feature Profile - A low level feature, typically a networking protocol, -// supported by a vendor platform. -// -// Generally feature profiles are either baseline protocols (BGP base), -// additional optional features supported with the protocol (BGP Add path), or -// specific scale requirements (Full FIB support with BGP). A feature profile -// can be dependent on one or more other feature profiles. -// -// Example feature profile: -// -// feature_profile { -// id { -// name: 'bgp_base' -// version: 1 -// } -// openconfig_path: -// '/network-instance//protocols/INSTALL_PROTOCOL_TYPE_BGP/...' -// } - -//Comment for Staticcheck linter: -//lint:file-ignore U1000 Ignore all unused code, it's generated -syntax = "proto2"; - -package openconfig.profiles; - -message FeatureProfileID { - // Unique name for the feature profile. - // - // Example: bgp_base - optional string name = 1; - - // Version number for this instantiation of the profile. - optional int32 version = 2; -} - -message TelemetryPath { - optional string path = 1; -} - -message ConfigPath { - optional string path = 1; -} - -message GNOIService { - // Service name for the GNOI endpoint - // - // Example: gnoi.bgp.BGP - optional string service_name = 1; - - // Method name for GNOI endpoint - // - // Example: ClearBGPNeighbor - optional string method_name = 2; -} - -// GNMIService describes compliance with the gNMI service. -message GNMIService { - // method_name specifies the name of the method that is - // being tested. The methods are from the gnmi service (e.g., Get). - enum Method { - MD_INVALID = 0; - MD_GET = 1; // gNMI.Get - MD_CAPABILITIES = 2; // gNMI.Capabilities - MD_SUBSCRIBE = 3; // gNMI.Subscribe - MD_SET = 4; // gNMI.Set - } - - // The method that is covered within the gNMI protocol. - optional Method method_name = 2; - - // TODO(robjs): for some RPCs, like Subscribe, we may want - // further description of modes (e.g., POLL, STREAM, ONCE). -} - -message FeatureProfile { - // Unique identifier for the service profile. - optional FeatureProfileID id = 1; - - // A list of configuration and state paths that compose the feature profile. - repeated ConfigPath config_path = 2; - - // A list of configuration and state paths that compose the feature profile. - repeated TelemetryPath telemetry_path = 3; - - // A list of feature profiles this feature profile depends on. For example, - // A iBGP feature profile might depend on the BGP base feature profile. - repeated FeatureProfileID feature_profile_dependency = 4; - - // A list of GNOI operational commands that compose the feature profile. - repeated GNOIService gnoi_service = 5; - - // A list of GNMI methods that compose the feature profile. - repeated GNMIService gnmi_service = 6; -} diff --git a/proto/feature_go_proto/feature.pb.go b/proto/feature_go_proto/feature.pb.go deleted file mode 100644 index 2b735eb81c9..00000000000 --- a/proto/feature_go_proto/feature.pb.go +++ /dev/null @@ -1,682 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -// Feature Profile - A low level feature, typically a networking protocol, -// supported by a vendor platform. -// -// Generally feature profiles are either baseline protocols (BGP base), -// additional optional features supported with the protocol (BGP Add path), or -// specific scale requirements (Full FIB support with BGP). A feature profile -// can be dependent on one or more other feature profiles. -// -// Example feature profile: -// -// feature_profile { -// id { -// name: 'bgp_base' -// version: 1 -// } -// openconfig_path: -// '/network-instance//protocols/INSTALL_PROTOCOL_TYPE_BGP/...' -// } - -//Comment for Staticcheck linter: -//lint:file-ignore U1000 Ignore all unused code, it's generated - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: feature.proto - -package feature_go_proto - -import ( - reflect "reflect" - sync "sync" - - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// method_name specifies the name of the method that is -// being tested. The methods are from the gnmi service (e.g., Get). -type GNMIService_Method int32 - -const ( - GNMIService_MD_INVALID GNMIService_Method = 0 - GNMIService_MD_GET GNMIService_Method = 1 // gNMI.Get - GNMIService_MD_CAPABILITIES GNMIService_Method = 2 // gNMI.Capabilities - GNMIService_MD_SUBSCRIBE GNMIService_Method = 3 // gNMI.Subscribe - GNMIService_MD_SET GNMIService_Method = 4 // gNMI.Set -) - -// Enum value maps for GNMIService_Method. -var ( - GNMIService_Method_name = map[int32]string{ - 0: "MD_INVALID", - 1: "MD_GET", - 2: "MD_CAPABILITIES", - 3: "MD_SUBSCRIBE", - 4: "MD_SET", - } - GNMIService_Method_value = map[string]int32{ - "MD_INVALID": 0, - "MD_GET": 1, - "MD_CAPABILITIES": 2, - "MD_SUBSCRIBE": 3, - "MD_SET": 4, - } -) - -func (x GNMIService_Method) Enum() *GNMIService_Method { - p := new(GNMIService_Method) - *p = x - return p -} - -func (x GNMIService_Method) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GNMIService_Method) Descriptor() protoreflect.EnumDescriptor { - return file_feature_proto_enumTypes[0].Descriptor() -} - -func (GNMIService_Method) Type() protoreflect.EnumType { - return &file_feature_proto_enumTypes[0] -} - -func (x GNMIService_Method) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *GNMIService_Method) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = GNMIService_Method(num) - return nil -} - -// Deprecated: Use GNMIService_Method.Descriptor instead. -func (GNMIService_Method) EnumDescriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{4, 0} -} - -type FeatureProfileID struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Unique name for the feature profile. - // - // Example: bgp_base - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - // Version number for this instantiation of the profile. - Version *int32 `protobuf:"varint,2,opt,name=version" json:"version,omitempty"` -} - -func (x *FeatureProfileID) Reset() { - *x = FeatureProfileID{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureProfileID) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureProfileID) ProtoMessage() {} - -func (x *FeatureProfileID) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureProfileID.ProtoReflect.Descriptor instead. -func (*FeatureProfileID) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{0} -} - -func (x *FeatureProfileID) GetName() string { - if x != nil && x.Name != nil { - return *x.Name - } - return "" -} - -func (x *FeatureProfileID) GetVersion() int32 { - if x != nil && x.Version != nil { - return *x.Version - } - return 0 -} - -type TelemetryPath struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Path *string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` -} - -func (x *TelemetryPath) Reset() { - *x = TelemetryPath{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TelemetryPath) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TelemetryPath) ProtoMessage() {} - -func (x *TelemetryPath) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TelemetryPath.ProtoReflect.Descriptor instead. -func (*TelemetryPath) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{1} -} - -func (x *TelemetryPath) GetPath() string { - if x != nil && x.Path != nil { - return *x.Path - } - return "" -} - -type ConfigPath struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Path *string `protobuf:"bytes,1,opt,name=path" json:"path,omitempty"` -} - -func (x *ConfigPath) Reset() { - *x = ConfigPath{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConfigPath) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConfigPath) ProtoMessage() {} - -func (x *ConfigPath) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ConfigPath.ProtoReflect.Descriptor instead. -func (*ConfigPath) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{2} -} - -func (x *ConfigPath) GetPath() string { - if x != nil && x.Path != nil { - return *x.Path - } - return "" -} - -type GNOIService struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Service name for the GNOI endpoint - // - // Example: gnoi.bgp.BGP - ServiceName *string `protobuf:"bytes,1,opt,name=service_name,json=serviceName" json:"service_name,omitempty"` - // Method name for GNOI endpoint - // - // Example: ClearBGPNeighbor - MethodName *string `protobuf:"bytes,2,opt,name=method_name,json=methodName" json:"method_name,omitempty"` -} - -func (x *GNOIService) Reset() { - *x = GNOIService{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GNOIService) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GNOIService) ProtoMessage() {} - -func (x *GNOIService) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GNOIService.ProtoReflect.Descriptor instead. -func (*GNOIService) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{3} -} - -func (x *GNOIService) GetServiceName() string { - if x != nil && x.ServiceName != nil { - return *x.ServiceName - } - return "" -} - -func (x *GNOIService) GetMethodName() string { - if x != nil && x.MethodName != nil { - return *x.MethodName - } - return "" -} - -// GNMIService describes compliance with the gNMI service. -type GNMIService struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The method that is covered within the gNMI protocol. - MethodName *GNMIService_Method `protobuf:"varint,2,opt,name=method_name,json=methodName,enum=openconfig.profiles.GNMIService_Method" json:"method_name,omitempty"` -} - -func (x *GNMIService) Reset() { - *x = GNMIService{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GNMIService) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GNMIService) ProtoMessage() {} - -func (x *GNMIService) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GNMIService.ProtoReflect.Descriptor instead. -func (*GNMIService) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{4} -} - -func (x *GNMIService) GetMethodName() GNMIService_Method { - if x != nil && x.MethodName != nil { - return *x.MethodName - } - return GNMIService_MD_INVALID -} - -type FeatureProfile struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Unique identifier for the service profile. - Id *FeatureProfileID `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"` - // A list of configuration and state paths that compose the feature profile. - ConfigPath []*ConfigPath `protobuf:"bytes,2,rep,name=config_path,json=configPath" json:"config_path,omitempty"` - // A list of configuration and state paths that compose the feature profile. - TelemetryPath []*TelemetryPath `protobuf:"bytes,3,rep,name=telemetry_path,json=telemetryPath" json:"telemetry_path,omitempty"` - // A list of feature profiles this feature profile depends on. For example, - // A iBGP feature profile might depend on the BGP base feature profile. - FeatureProfileDependency []*FeatureProfileID `protobuf:"bytes,4,rep,name=feature_profile_dependency,json=featureProfileDependency" json:"feature_profile_dependency,omitempty"` - // A list of GNOI operational commands that compose the feature profile. - GnoiService []*GNOIService `protobuf:"bytes,5,rep,name=gnoi_service,json=gnoiService" json:"gnoi_service,omitempty"` - // A list of GNMI methods that compose the feature profile. - GnmiService []*GNMIService `protobuf:"bytes,6,rep,name=gnmi_service,json=gnmiService" json:"gnmi_service,omitempty"` -} - -func (x *FeatureProfile) Reset() { - *x = FeatureProfile{} - if protoimpl.UnsafeEnabled { - mi := &file_feature_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FeatureProfile) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FeatureProfile) ProtoMessage() {} - -func (x *FeatureProfile) ProtoReflect() protoreflect.Message { - mi := &file_feature_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FeatureProfile.ProtoReflect.Descriptor instead. -func (*FeatureProfile) Descriptor() ([]byte, []int) { - return file_feature_proto_rawDescGZIP(), []int{5} -} - -func (x *FeatureProfile) GetId() *FeatureProfileID { - if x != nil { - return x.Id - } - return nil -} - -func (x *FeatureProfile) GetConfigPath() []*ConfigPath { - if x != nil { - return x.ConfigPath - } - return nil -} - -func (x *FeatureProfile) GetTelemetryPath() []*TelemetryPath { - if x != nil { - return x.TelemetryPath - } - return nil -} - -func (x *FeatureProfile) GetFeatureProfileDependency() []*FeatureProfileID { - if x != nil { - return x.FeatureProfileDependency - } - return nil -} - -func (x *FeatureProfile) GetGnoiService() []*GNOIService { - if x != nil { - return x.GnoiService - } - return nil -} - -func (x *FeatureProfile) GetGnmiService() []*GNMIService { - if x != nil { - return x.GnmiService - } - return nil -} - -var File_feature_proto protoreflect.FileDescriptor - -var file_feature_proto_rawDesc = []byte{ - 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x13, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x22, 0x40, 0x0a, 0x10, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x23, 0x0a, 0x0d, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x74, 0x72, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x20, 0x0a, 0x0a, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x51, 0x0a, - 0x0b, 0x47, 0x4e, 0x4f, 0x49, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, - 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x47, 0x4e, 0x4d, 0x49, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47, 0x4e, 0x4d, 0x49, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x0a, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x57, 0x0a, 0x06, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x44, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x44, 0x5f, 0x47, 0x45, 0x54, 0x10, 0x01, - 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x44, 0x5f, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, - 0x49, 0x45, 0x53, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4d, 0x44, 0x5f, 0x53, 0x55, 0x42, 0x53, - 0x43, 0x52, 0x49, 0x42, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x44, 0x5f, 0x53, 0x45, - 0x54, 0x10, 0x04, 0x22, 0xc3, 0x03, 0x0a, 0x0e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x35, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x40, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, - 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x49, 0x0a, 0x0e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x0d, 0x74, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x63, 0x0a, 0x1a, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65, - 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x66, - 0x69, 0x6c, 0x65, 0x49, 0x44, 0x52, 0x18, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x50, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x43, 0x0a, 0x0c, 0x67, 0x6e, 0x6f, 0x69, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47, 0x4e, 0x4f, 0x49, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x0b, 0x67, 0x6e, 0x6f, 0x69, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x0c, 0x67, 0x6e, 0x6d, 0x69, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6f, 0x70, 0x65, - 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x2e, 0x47, 0x4e, 0x4d, 0x49, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x0b, 0x67, 0x6e, - 0x6d, 0x69, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, -} - -var ( - file_feature_proto_rawDescOnce sync.Once - file_feature_proto_rawDescData = file_feature_proto_rawDesc -) - -func file_feature_proto_rawDescGZIP() []byte { - file_feature_proto_rawDescOnce.Do(func() { - file_feature_proto_rawDescData = protoimpl.X.CompressGZIP(file_feature_proto_rawDescData) - }) - return file_feature_proto_rawDescData -} - -var file_feature_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_feature_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_feature_proto_goTypes = []interface{}{ - (GNMIService_Method)(0), // 0: openconfig.profiles.GNMIService.Method - (*FeatureProfileID)(nil), // 1: openconfig.profiles.FeatureProfileID - (*TelemetryPath)(nil), // 2: openconfig.profiles.TelemetryPath - (*ConfigPath)(nil), // 3: openconfig.profiles.ConfigPath - (*GNOIService)(nil), // 4: openconfig.profiles.GNOIService - (*GNMIService)(nil), // 5: openconfig.profiles.GNMIService - (*FeatureProfile)(nil), // 6: openconfig.profiles.FeatureProfile -} -var file_feature_proto_depIdxs = []int32{ - 0, // 0: openconfig.profiles.GNMIService.method_name:type_name -> openconfig.profiles.GNMIService.Method - 1, // 1: openconfig.profiles.FeatureProfile.id:type_name -> openconfig.profiles.FeatureProfileID - 3, // 2: openconfig.profiles.FeatureProfile.config_path:type_name -> openconfig.profiles.ConfigPath - 2, // 3: openconfig.profiles.FeatureProfile.telemetry_path:type_name -> openconfig.profiles.TelemetryPath - 1, // 4: openconfig.profiles.FeatureProfile.feature_profile_dependency:type_name -> openconfig.profiles.FeatureProfileID - 4, // 5: openconfig.profiles.FeatureProfile.gnoi_service:type_name -> openconfig.profiles.GNOIService - 5, // 6: openconfig.profiles.FeatureProfile.gnmi_service:type_name -> openconfig.profiles.GNMIService - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name -} - -func init() { file_feature_proto_init() } -func file_feature_proto_init() { - if File_feature_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_feature_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureProfileID); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feature_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TelemetryPath); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feature_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConfigPath); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feature_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GNOIService); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feature_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GNMIService); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_feature_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FeatureProfile); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_feature_proto_rawDesc, - NumEnums: 1, - NumMessages: 6, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_feature_proto_goTypes, - DependencyIndexes: file_feature_proto_depIdxs, - EnumInfos: file_feature_proto_enumTypes, - MessageInfos: file_feature_proto_msgTypes, - }.Build() - File_feature_proto = out.File - file_feature_proto_rawDesc = nil - file_feature_proto_goTypes = nil - file_feature_proto_depIdxs = nil -} diff --git a/tools/clone_oc_public.sh b/tools/clone_oc_public.sh deleted file mode 100755 index d0c7b22ac69..00000000000 --- a/tools/clone_oc_public.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# Usage: clone_oc_public.sh local_dir_name -set -e -git clone https://github.com/openconfig/public.git "$1" -cd "$1" -# Use latest commit of OpenConfig public repo. -echo "Using github.com/openconfig/public branch: $branch" diff --git a/tools/validate_paths.go b/tools/validate_paths.go deleted file mode 100644 index 84ab210886c..00000000000 --- a/tools/validate_paths.go +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright 2022 Google LLC - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// https://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// validate_paths inspects paths in the Feature Profiles and fails if any are not standard -// OpenConfig paths. -package main - -import ( - "errors" - "fmt" - "io/fs" - "os" - "path" - "path/filepath" - "reflect" - "sort" - "strings" - - "flag" - - log "github.com/golang/glog" - fppb "github.com/openconfig/featureprofiles/proto/feature_go_proto" - "github.com/openconfig/goyang/pkg/yang" - "github.com/openconfig/ygot/util" - "github.com/protocolbuffers/txtpbfmt/parser" - "google.golang.org/protobuf/encoding/prototext" -) - -var ( - featuresRootFlag = flag.String("feature_root", "", "root directory of the feature profiles") - yangRootsFlag = flag.String( - "yang_roots", "", "comma separated list of directories containing .yang files.", - ) - yangSkipsFlag = flag.String( - "yang_skip_roots", "", "sub-directories of the .yang roots which should be ignored.", - ) - featureFilesFlag = flag.String("feature_files", "", "optional file containing list of feature.textprotos to validate instead of checking all files. If not specified, then all files will be checked. Note that all files will still be checked and annotated, but only these files will cause failure.") -) - -var ( - featuresRoot string - yangPaths []string - skipYANGDirs = map[string]bool{} -) - -type pathType int - -const ( - unset pathType = iota - configuration - telemetry -) - -// addKnownPaths records information about all paths in and under a `yang.Entity`. -func addKnownPaths(ps map[string]pathType, e *yang.Entry) { - if e.IsLeaf() || e.IsLeafList() { - pt := unset - switch util.IsConfig(e) { - case true: - pt = configuration - case false: - pt = telemetry - } - ps[fmt.Sprintf("%q", util.SchemaTreePathNoModule(e))] = pt - return - } - for _, ce := range util.Children(e) { - addKnownPaths(ps, ce) - } -} - -func yangFiles(root string) ([]string, error) { - ps := map[string]bool{} - err := filepath.WalkDir(root, func(p string, info fs.DirEntry, err error) error { - if err != nil { - return err - } - if info == nil { - return nil - } - if info.IsDir() { - if skipYANGDirs[p] { - fmt.Println("Skipping definitions in", p) - return filepath.SkipDir - } - return nil - } - if strings.HasSuffix(p, ".yang") { - ps[p] = true - } - return nil - }) - if err != nil { - return nil, err - } - res := make([]string, 0, len(ps)) - for p := range ps { - res = append(res, p) - } - return res, nil -} - -func modules() (map[string]*yang.Module, error) { - var files, dirs []string - for _, p := range yangPaths { - ds, err := yang.PathsWithModules(p) - if err != nil { - return nil, err - } - dirs = append(dirs, ds...) - - fs, err := yangFiles(p) - if err != nil { - return nil, err - } - files = append(files, fs...) - } - - ms := yang.NewModules() - - ms.AddPath(dirs...) - - for _, p := range files { - p = path.Base(p) - if err := ms.Read(p); err != nil { - return nil, fmt.Errorf("ms.Read(%s): %v", p, err) - } - } - - if errs := ms.Process(); len(errs) != 0 { - log.Error("ms.Process errors:") - for _, e := range errs { - log.Error(" ", e) - } - return nil, errors.New("yang module process error") - } - return ms.Modules, nil -} - -type line struct { - line int32 - column int32 - oc string - detail string -} - -type file struct { - name string - lines []line - // Errors which are not correlated with a line. - errors []string -} - -func (f file) githubAnnotations() string { - var b strings.Builder - for _, errLine := range f.errors { - b.WriteString(fmt.Sprintf("::%s file=%s::%s\n", "error", f.name, errLine)) - } - - for _, line := range f.lines { - // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message - b.WriteString(fmt.Sprintf("::%s file=%s,line=%d,col=%d::%s %s\n", "error", f.name, line.line, line.column, line.detail, line.oc)) - } - - return b.String() -} - -func constructValidProfiles(files []string) (map[string]bool, map[string]*file) { - tmp := fppb.FeatureProfile{} - validProfiles := make(map[string]bool) - reports := make(map[string]*file) - - for _, f := range files { - report := reports[f] - if report == nil { - report = &file{name: f} - reports[f] = report - } - bs, err := os.ReadFile(f) - if err != nil { - // Just accumulate the file error since we can't do anything else. - report.errors = append(report.errors, err.Error()) - continue - } - - // Unmarshal will report syntax errors (although generally without line numbers). - if err := prototext.Unmarshal(bs, &tmp); err != nil { - report.errors = append(report.errors, err.Error()) - } - - // Validate feature profile ID name by checking path. - targetFeatureProfileName := getFeatureProfileNameFromPath(f) - featureProfileIDName := tmp.GetId().GetName() - if targetFeatureProfileName != featureProfileIDName { - report.errors = append(report.errors, featureProfileIDName+" is inconsistent with path, want "+targetFeatureProfileName) - } else { - validProfiles[featureProfileIDName] = true - } - } - return validProfiles, reports -} - -// checkFiles parses all `path:` lines in the input `files`, reporting any syntax errors and paths -// which are not in the `knownOC` set. -func checkFiles(knownOC map[string]pathType, files []string, validProfiles map[string]bool, reports map[string]*file) error { - tmp := fppb.FeatureProfile{} - - log.Infof("%d files to validate", len(files)) - - for _, f := range files { - log.Infof("Validating file: %v", f) - report := reports[f] - if report == nil { - report = &file{name: f} - reports[f] = report - } - - bs, err := os.ReadFile(f) - if err != nil { - // Just accumulate the file error since we can't do anything else. - report.errors = append(report.errors, err.Error()) - continue - } - - // Unmarshal will report syntax errors (although generally without line numbers). - if err := prototext.Unmarshal(bs, &tmp); err != nil { - report.errors = append(report.errors, err.Error()) - } - - // Use parser.Parse so I can get line numbers for OC paths we don't recognize. - ast, err := parser.Parse(bs) - if err != nil { - return err - } - for _, a := range ast { - switch a.Name { - case "config_path", "telemetry_path": - for _, c := range a.Children { - if c.Name == "path" { - for _, v := range c.Values { - var detail string - switch knownOC[v.Value] { - case configuration: - if a.Name != "config_path" { - detail = fmt.Sprintf("erroneously labeled %s", a.Name) - } - case telemetry: - if a.Name != "telemetry_path" { - detail = fmt.Sprintf("erroneously labeled %s", a.Name) - } - case unset: - detail = "missing from YANG" - } - if detail != "" { - report.lines = append(report.lines, line{ - line: c.Start.Line, - column: c.Start.Column, - oc: v.Value, - detail: detail, - }) - } - } - } - } - case "feature_profile_dependency": - for _, c := range a.Children { - if c.Name == "name" { - for _, v := range c.Values { - profileName := v.Value[1 : len(v.Value)-1] // Trim quotes - if !validProfiles[profileName] { - report.lines = append(report.lines, line{ - line: c.Start.Line, - column: c.Start.Column, - detail: "cannot find feature profile dependency " + profileName, - }) - } - } - } - } - } - } - } - return nil -} - -// cleanReports removes any empty reports. -func cleanReports(reports map[string]*file) { - for key, report := range reports { - if reflect.DeepEqual(report, &file{name: report.name}) { - delete(reports, key) - } - } -} - -// getFeatureProfileNameFromPath gets feature profile id.name from path. -func getFeatureProfileNameFromPath(file string) string { - featureProfileFilePath := strings.ReplaceAll(strings.TrimPrefix(file, featuresRoot), "/", " ") - featureProfileFilePathArray := strings.Fields(featureProfileFilePath) - featureProfileFilePathArray = featureProfileFilePathArray[0 : len(featureProfileFilePathArray)-1] - return strings.Join(featureProfileFilePathArray, "_") -} - -// featureFiles returns the feature files to check and all existing feature files. -func featureFiles() (map[string]struct{}, []string, error) { - var allFiles []string - filesToCheck := map[string]struct{}{} - err := filepath.WalkDir(featuresRoot, - func(path string, e fs.DirEntry, err error) error { - if err != nil { - return err - } - if e.IsDir() { - return nil - } - if e.Name() == "feature.textproto" { - allFiles = append(allFiles, path) - filesToCheck[path] = struct{}{} - } - return nil - }) - if err != nil { - return nil, nil, err - } - sort.Strings(allFiles) - - if *featureFilesFlag != "" { - filesToCheck = map[string]struct{}{} - readBytes, err := os.ReadFile(*featureFilesFlag) - if err != nil { - log.Fatalf("cannot read feature_files flag: %v", err) - } - for _, line := range strings.Split(string(readBytes), "\n") { - line = strings.TrimSpace(line) - if line == "" { - continue - } - path, err := filepath.Abs(line) - if err != nil { - return nil, nil, err - } - filesToCheck[path] = struct{}{} - } - } - - return filesToCheck, allFiles, nil -} - -// Check that every OC path used in the Feature Profiles is defined in the public OpenConfig yang. -func main() { - flag.Parse() - if *featuresRootFlag == "" { - log.Fatal("feature_root must be set.") - } - if *yangRootsFlag == "" { - log.Fatal("yang_roots must be set.") - } - featuresRoot = *featuresRootFlag - yangPaths = strings.Split(*yangRootsFlag, ",") - for _, s := range strings.Split(*yangSkipsFlag, ",") { - skipYANGDirs[s] = true - } - - ms, err := modules() - if err != nil { - log.Fatal(err) - } - knownPaths := map[string]pathType{} - for _, m := range ms { - addKnownPaths(knownPaths, yang.ToEntry(m)) - } - - filesToCheck, allFiles, err := featureFiles() - if err != nil { - log.Fatal(err) - } - - validProfiles, reports := constructValidProfiles(allFiles) - if err := checkFiles(knownPaths, allFiles, validProfiles, reports); err != nil { - log.Fatal(err) - } - - cleanReports(reports) - - log.Infof("%d files must pass: %v", len(filesToCheck), filesToCheck) - if len(reports) == 0 { - return - } - - msg := []string{"Feature paths inconsistent with YANG schema:"} - failed := false - for _, f := range reports { - fmt.Print(f.githubAnnotations()) - if _, ok := filesToCheck[f.name]; ok { - failed = true - } - msg = append(msg, " file: "+f.name) - if len(f.errors) != 0 { - msg = append(msg, " toplevel errors:") - for _, e := range f.errors { - msg = append(msg, " "+e) - } - } - for _, l := range f.lines { - msg = append(msg, fmt.Sprintf(" line %d: %s %s", l.line, l.detail, l.oc)) - } - } - log.Info(strings.Join(msg, "\n")) - if failed { - os.Exit(1) - } -}