From a2aad26e562866c313c43085d3ac0e41ea48eba8 Mon Sep 17 00:00:00 2001 From: wawlian Date: Mon, 14 Mar 2022 14:36:32 +0800 Subject: [PATCH] support edgex 2.1 --- Makefile | 1 - api/v1alpha1/device_types.go | 13 +- api/v1alpha1/deviceprofile_types.go | 119 ++--- api/v1alpha1/deviceservice_types.go | 31 +- api/v1alpha1/edgexobject.go | 4 - api/v1alpha1/valuedescriptor_types.go | 73 --- api/v1alpha1/zz_generated.deepcopy.go | 322 ++---------- clients/edgex-foundry/device_client.go | 185 +++---- clients/edgex-foundry/deviceprofile_client.go | 47 +- clients/edgex-foundry/deviceservice_client.go | 154 ++---- clients/edgex-foundry/util.go | 455 +++++------------ .../edgex-foundry/valuedescriptor_client.go | 108 ---- clients/interface.go | 19 - cmd/yurt-device-controller/app/core.go | 10 - cmd/yurt-device-controller/options/options.go | 12 +- .../device.openyurt.io_deviceprofiles.yaml | 210 ++------ .../crd/bases/device.openyurt.io_devices.yaml | 18 +- .../device.openyurt.io_deviceservices.yaml | 46 +- .../device.openyurt.io_valuedescriptors.yaml | 92 ---- config/crd/kustomization.yaml | 3 - config/rbac/role.yaml | 26 - config/setup/crd.yaml | 476 ++++++------------ controllers/device_controller.go | 16 +- controllers/deviceservice_controller.go | 51 +- controllers/deviceservice_syncer.go | 2 +- controllers/valuedescriptor_controller.go | 103 ---- go.mod | 2 +- go.sum | 128 ++++- 28 files changed, 700 insertions(+), 2026 deletions(-) delete mode 100644 api/v1alpha1/valuedescriptor_types.go delete mode 100644 clients/edgex-foundry/valuedescriptor_client.go delete mode 100644 config/crd/bases/device.openyurt.io_valuedescriptors.yaml delete mode 100644 controllers/valuedescriptor_controller.go diff --git a/Makefile b/Makefile index 5b1a26b..697d910 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,6 @@ generate: controller-gen paths="./api/v1alpha1/device_types.go" \ paths="./api/v1alpha1/deviceservice_types.go" \ paths="./api/v1alpha1/deviceprofile_types.go" \ - paths="./api/v1alpha1/valuedescriptor_types.go" \ paths="./api/v1alpha1/groupversion_info.go" # Download controller-gen locally if necessary diff --git a/api/v1alpha1/device_types.go b/api/v1alpha1/device_types.go index 24b3eae..18c47e0 100644 --- a/api/v1alpha1/device_types.go +++ b/api/v1alpha1/device_types.go @@ -39,8 +39,9 @@ const ( type OperatingState string const ( - Enabled OperatingState = "ENABLED" - Disabled OperatingState = "DISABLED" + Unknown OperatingState = "UNKNOWN" + Up OperatingState = "UP" + Down OperatingState = "DOWN" ) type ProtocolProperties map[string]string @@ -59,11 +60,13 @@ type DeviceSpec struct { Labels []string `json:"labels,omitempty"` // Device service specific location (interface{} is an empty interface so // it can be anything) + // TODO: location type in edgex is interface{} Location string `json:"location,omitempty"` // Associated Device Service - One per device - Service string `json:"service"` + Service string `json:"serviceName"` // Associated Device Profile - Describes the device - Profile string `json:"profile"` + Profile string `json:"profileName"` + Notify bool `json:"notify"` // True means device is managed by cloud, cloud can update the related fields // False means cloud can't update the fields Managed bool `json:"managed,omitempty"` @@ -103,7 +106,7 @@ type DeviceStatus struct { EdgeId string `json:"edgeId,omitempty"` // Admin state (locked/unlocked) AdminState AdminState `json:"adminState,omitempty"` - // Operating state (enabled/disabled) + // Operating state (up/down/unknown) OperatingState OperatingState `json:"operatingState,omitempty"` // current device state // +optional diff --git a/api/v1alpha1/deviceprofile_types.go b/api/v1alpha1/deviceprofile_types.go index 44ae1d9..47376dc 100644 --- a/api/v1alpha1/deviceprofile_types.go +++ b/api/v1alpha1/deviceprofile_types.go @@ -18,6 +18,7 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) const ( @@ -25,100 +26,61 @@ const ( ) type DeviceResource struct { - Description string `json:"description"` - Name string `json:"name"` - Tag string `json:"tag,omitempty"` - Properties ProfileProperty `json:"properties"` - Attributes map[string]string `json:"attributes,omitempty"` + Description string `json:"description"` + Name string `json:"name"` + Tag string `json:"tag,omitempty"` + IsHidden bool `json:"isHidden"` + Properties ResourceProperties `json:"properties"` + Attributes MapInterfaceValue `json:"attributes,omitempty"` } -type ProfileProperty struct { - Value PropertyValue `json:"value"` - Units Units `json:"units,omitempty"` +// +k8s:deepcopy-gen=false +type MapInterfaceValue map[string]interface{} + +func (in *MapInterfaceValue) DeepCopyInto(out *MapInterfaceValue) { + if in == nil { + *out = nil + } else { + *out = runtime.DeepCopyJSON(*in) + } +} + +func (in *MapInterfaceValue) DeepCopy() *MapInterfaceValue { + if in == nil { + return nil + } + out := new(MapInterfaceValue) + in.DeepCopyInto(out) + return out } -type PropertyValue struct { - Type string `json:"type,omitempty"` // ValueDescriptor Type of property after transformations +type ResourceProperties struct { ReadWrite string `json:"readWrite,omitempty"` // Read/Write Permissions set for this property Minimum string `json:"minimum,omitempty"` // Minimum value that can be get/set from this property Maximum string `json:"maximum,omitempty"` // Maximum value that can be get/set from this property DefaultValue string `json:"defaultValue,omitempty"` // Default value set to this property if no argument is passed - Size string `json:"size,omitempty"` // Size of this property in its type (i.e. bytes for numeric types, characters for string types) Mask string `json:"mask,omitempty"` // Mask to be applied prior to get/set of property Shift string `json:"shift,omitempty"` // Shift to be applied after masking, prior to get/set of property Scale string `json:"scale,omitempty"` // Multiplicative factor to be applied after shifting, prior to get/set of property Offset string `json:"offset,omitempty"` // Additive factor to be applied after multiplying, prior to get/set of property Base string `json:"base,omitempty"` // Base for property to be applied to, leave 0 for no power operation (i.e. base ^ property: 2 ^ 10) - // Required value of the property, set for checking error state. Failing an - // assertion condition wil l mark the device with an error state - Assertion string `json:"assertion,omitempty"` - Precision string `json:"precision,omitempty"` - FloatEncoding string `json:"floatEncoding,omitempty"` // FloatEncoding indicates the representation of floating value of reading. It should be 'Base64' or 'eNotation' - MediaType string `json:"mediaType,omitempty"` + Assertion string `json:"assertion,omitempty"` + MediaType string `json:"mediaType,omitempty"` + Units string `json:"units,omitempty"` + ValueType string `json:"valueType,omitempty"` } -type Units struct { - Type string `json:"type,omitempty"` - ReadWrite string `json:"readWrite,omitempty"` - DefaultValue string `json:"defaultValue,omitempty"` -} - -type Command struct { - // EdgeId is a unique identifier used by EdgeX Foundry, such as a UUID - EdgeId string `json:"id,omitempty"` - // Command name (unique on the profile) - Name string `json:"name,omitempty"` - // Get Command - Get Get `json:"get,omitempty"` - // Put Command - Put Put `json:"put,omitempty"` -} - -type Put struct { - Action `json:",inline"` - ParameterNames []string `json:"parameterNames,omitempty"` -} - -type Get struct { - Action `json:",omitempty"` -} - -type Action struct { - // Path used by service for action on a device or sensor - Path string `json:"path,omitempty"` - // Responses from get or put requests to service - Responses []Response `json:"responses,omitempty"` - // Url for requests from command service - URL string `json:"url,omitempty"` -} - -// Response for a Get or Put request to a service -type Response struct { - Code string `json:"code,omitempty"` - Description string `json:"description,omitempty"` - ExpectedValues []string `json:"expectedValues,omitempty"` -} - -type ProfileResource struct { - Name string `json:"name,omitempty"` - Get []ResourceOperation `json:"get,omitempty"` - Set []ResourceOperation `json:"set,omitempty"` +type DeviceCommand struct { + Name string `json:"name"` + IsHidden bool `json:"isHidden"` + ReadWrite string `json:"readWrite"` + ResourceOperations []ResourceOperation `json:"resourceOperations"` } type ResourceOperation struct { - Index string `json:"index,omitempty"` - Operation string `json:"operation,omitempty"` - // Deprecated - Object string `json:"object,omitempty"` - // The replacement of Object field - DeviceResource string `json:"deviceResource,omitempty"` - Parameter string `json:"parameter,omitempty"` - // Deprecated - Resource string `json:"resource,omitempty"` - // The replacement of Resource field - DeviceCommand string `json:"deviceCommand,omitempty"` - Secondary []string `json:"secondary,omitempty"` - Mappings map[string]string `json:"mappings,omitempty"` + DeviceResource string `json:"deviceResource,omitempty"` + Mappings map[string]string `json:"mappings,omitempty"` + DefaultValue string `json:"defaultValue"` } // DeviceProfileSpec defines the desired state of DeviceProfile @@ -133,10 +95,7 @@ type DeviceProfileSpec struct { // Labels used to search for groups of profiles on EdgeX Foundry Labels []string `json:"labels,omitempty"` DeviceResources []DeviceResource `json:"deviceResources,omitempty"` - - // TODO support the following field - DeviceCommands []ProfileResource `json:"deviceCommands,omitempty"` - CoreCommands []Command `json:"coreCommands,omitempty"` + DeviceCommands []DeviceCommand `json:"deviceCommands,omitempty"` } // DeviceProfileStatus defines the observed state of DeviceProfile diff --git a/api/v1alpha1/deviceservice_types.go b/api/v1alpha1/deviceservice_types.go index 5cda6e3..69c79ec 100644 --- a/api/v1alpha1/deviceservice_types.go +++ b/api/v1alpha1/deviceservice_types.go @@ -29,43 +29,14 @@ const ( DeviceServiceManagingCondition clusterv1.ConditionType = "DeviceServiceManaging" ) -type Addressable struct { - // ID is a unique identifier for the Addressable, such as a UUID - Id string `json:"id,omitempty"` - // Name is a unique name given to the Addressable - Name string `json:"name,omitempty"` - // Protocol for the address (HTTP/TCP) - Protocol string `json:"protocol,omitempty"` - // Method for connecting (i.e. POST) - HTTPMethod string `json:"method,omitempty"` - // Address of the addressable - Address string `json:"address,omitempty"` - // Port for the address - Port int `json:"port,omitempty"` - // Path for callbacks - Path string `json:"path,omitempty"` - // For message bus protocols - Publisher string `json:"publisher,omitempty"` - // User id for authentication - User string `json:"user,omitempty"` - // Password of the user for authentication for the addressable - Password string `json:"password,omitempty"` - // Topic for message bus addressables - Topic string `json:"topic,omitempty"` -} - // DeviceServiceSpec defines the desired state of DeviceService type DeviceServiceSpec struct { + BaseAddress string `json:"baseAddress"` // Information describing the device Description string `json:"description,omitempty"` - // operational state - either enabled or disabled - OperatingState OperatingState `json:"operatingState,omitempty"` // tags or other labels applied to the device service for search or other // identification needs on the EdgeX Foundry Labels []string `json:"labels,omitempty"` - // address (MQTT topic, HTTP address, serial bus, etc.) for reaching - // the service - Addressable Addressable `json:"addressable,omitempty"` // Device Service Admin State AdminState AdminState `json:"adminState,omitempty"` // True means deviceService is managed by cloud, cloud can update the related fields diff --git a/api/v1alpha1/edgexobject.go b/api/v1alpha1/edgexobject.go index fb5e90b..c49b0d8 100644 --- a/api/v1alpha1/edgexobject.go +++ b/api/v1alpha1/edgexobject.go @@ -20,10 +20,6 @@ type EdgeXObject interface { IsAddedToEdgeX() bool } -func (vd *ValueDescriptor) IsAddedToEdgeX() bool { - return vd.Status.AddedToEdgeX -} - func (dp *DeviceProfile) IsAddedToEdgeX() bool { return dp.Status.Synced } diff --git a/api/v1alpha1/valuedescriptor_types.go b/api/v1alpha1/valuedescriptor_types.go deleted file mode 100644 index e67d419..0000000 --- a/api/v1alpha1/valuedescriptor_types.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2021 The OpenYurt Authors. - -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 - - http://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. -*/ - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// ValueDescriptorSpec defines the desired state of ValueDescriptor -type ValueDescriptorSpec struct { - Id string `json:"id,omitempty"` - Created int64 `json:"created,omitempty"` - Description string `json:"description,omitempty"` - Modified int64 `json:"modified,omitempty"` - Origin int64 `json:"origin,omitempty"` - Min string `json:"min,omitempty"` - Max string `json:"max,omitempty"` - DefaultValue string `json:"defaultValue,omitempty"` - Type string `json:"type,omitempty"` - UomLabel string `json:"uomLabel,omitempty"` - Formatting string `json:"formatting,omitempty"` - Labels []string `json:"labels,omitempty"` - MediaType string `json:"mediaType,omitempty"` - FloatEncoding string `json:"floatEncoding,omitempty"` -} - -// ValueDescriptorStatus defines the observed state of ValueDescriptor -type ValueDescriptorStatus struct { - // AddedToEdgeX indicates whether the object has been successfully - // created on EdgeX Foundry - AddedToEdgeX bool `json:"addedToEdgeX,omitempty"` -} - -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status - -// ValueDescriptor is the Schema for the valuedescriptors API -// NOTE Thie struct is derived from -// edgex/go-mod-core-contracts/models/value-descriptor.go -type ValueDescriptor struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ValueDescriptorSpec `json:"spec,omitempty"` - Status ValueDescriptorStatus `json:"status,omitempty"` -} - -//+kubebuilder:object:root=true - -// ValueDescriptorList contains a list of ValueDescriptor -type ValueDescriptorList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ValueDescriptor `json:"items"` -} - -func init() { - SchemeBuilder.Register(&ValueDescriptor{}, &ValueDescriptorList{}) -} diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 460a587..55186e7 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -21,32 +22,10 @@ limitations under the License. package v1alpha1 import ( - runtime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/cluster-api/api/v1alpha4" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Action) DeepCopyInto(out *Action) { - *out = *in - if in.Responses != nil { - in, out := &in.Responses, &out.Responses - *out = make([]Response, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Action. -func (in *Action) DeepCopy() *Action { - if in == nil { - return nil - } - out := new(Action) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ActualPropertyState) DeepCopyInto(out *ActualPropertyState) { *out = *in @@ -62,38 +41,6 @@ func (in *ActualPropertyState) DeepCopy() *ActualPropertyState { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Addressable) DeepCopyInto(out *Addressable) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addressable. -func (in *Addressable) DeepCopy() *Addressable { - if in == nil { - return nil - } - out := new(Addressable) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Command) DeepCopyInto(out *Command) { - *out = *in - in.Get.DeepCopyInto(&out.Get) - in.Put.DeepCopyInto(&out.Put) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Command. -func (in *Command) DeepCopy() *Command { - if in == nil { - return nil - } - out := new(Command) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DesiredPropertyState) DeepCopyInto(out *DesiredPropertyState) { *out = *in @@ -136,6 +83,28 @@ func (in *Device) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeviceCommand) DeepCopyInto(out *DeviceCommand) { + *out = *in + if in.ResourceOperations != nil { + in, out := &in.ResourceOperations, &out.ResourceOperations + *out = make([]ResourceOperation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeviceCommand. +func (in *DeviceCommand) DeepCopy() *DeviceCommand { + if in == nil { + return nil + } + out := new(DeviceCommand) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeviceList) DeepCopyInto(out *DeviceList) { *out = *in @@ -244,14 +213,7 @@ func (in *DeviceProfileSpec) DeepCopyInto(out *DeviceProfileSpec) { } if in.DeviceCommands != nil { in, out := &in.DeviceCommands, &out.DeviceCommands - *out = make([]ProfileResource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.CoreCommands != nil { - in, out := &in.CoreCommands, &out.CoreCommands - *out = make([]Command, len(*in)) + *out = make([]DeviceCommand, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -287,13 +249,7 @@ func (in *DeviceProfileStatus) DeepCopy() *DeviceProfileStatus { func (in *DeviceResource) DeepCopyInto(out *DeviceResource) { *out = *in out.Properties = in.Properties - if in.Attributes != nil { - in, out := &in.Attributes, &out.Attributes - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } + in.Attributes.DeepCopyInto(&out.Attributes) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeviceResource. @@ -373,7 +329,6 @@ func (in *DeviceServiceSpec) DeepCopyInto(out *DeviceServiceSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - out.Addressable = in.Addressable } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeviceServiceSpec. @@ -481,83 +436,6 @@ func (in *DeviceStatus) DeepCopy() *DeviceStatus { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Get) DeepCopyInto(out *Get) { - *out = *in - in.Action.DeepCopyInto(&out.Action) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Get. -func (in *Get) DeepCopy() *Get { - if in == nil { - return nil - } - out := new(Get) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProfileProperty) DeepCopyInto(out *ProfileProperty) { - *out = *in - out.Value = in.Value - out.Units = in.Units -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileProperty. -func (in *ProfileProperty) DeepCopy() *ProfileProperty { - if in == nil { - return nil - } - out := new(ProfileProperty) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProfileResource) DeepCopyInto(out *ProfileResource) { - *out = *in - if in.Get != nil { - in, out := &in.Get, &out.Get - *out = make([]ResourceOperation, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Set != nil { - in, out := &in.Set, &out.Set - *out = make([]ResourceOperation, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProfileResource. -func (in *ProfileResource) DeepCopy() *ProfileResource { - if in == nil { - return nil - } - out := new(ProfileResource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PropertyValue) DeepCopyInto(out *PropertyValue) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PropertyValue. -func (in *PropertyValue) DeepCopy() *PropertyValue { - if in == nil { - return nil - } - out := new(PropertyValue) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in ProtocolProperties) DeepCopyInto(out *ProtocolProperties) { { @@ -579,35 +457,9 @@ func (in ProtocolProperties) DeepCopy() ProtocolProperties { return *out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Put) DeepCopyInto(out *Put) { - *out = *in - in.Action.DeepCopyInto(&out.Action) - if in.ParameterNames != nil { - in, out := &in.ParameterNames, &out.ParameterNames - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Put. -func (in *Put) DeepCopy() *Put { - if in == nil { - return nil - } - out := new(Put) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceOperation) DeepCopyInto(out *ResourceOperation) { *out = *in - if in.Secondary != nil { - in, out := &in.Secondary, &out.Secondary - *out = make([]string, len(*in)) - copy(*out, *in) - } if in.Mappings != nil { in, out := &in.Mappings, &out.Mappings *out = make(map[string]string, len(*in)) @@ -628,130 +480,16 @@ func (in *ResourceOperation) DeepCopy() *ResourceOperation { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Response) DeepCopyInto(out *Response) { - *out = *in - if in.ExpectedValues != nil { - in, out := &in.ExpectedValues, &out.ExpectedValues - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Response. -func (in *Response) DeepCopy() *Response { - if in == nil { - return nil - } - out := new(Response) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Units) DeepCopyInto(out *Units) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Units. -func (in *Units) DeepCopy() *Units { - if in == nil { - return nil - } - out := new(Units) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ValueDescriptor) DeepCopyInto(out *ValueDescriptor) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueDescriptor. -func (in *ValueDescriptor) DeepCopy() *ValueDescriptor { - if in == nil { - return nil - } - out := new(ValueDescriptor) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ValueDescriptor) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ValueDescriptorList) DeepCopyInto(out *ValueDescriptorList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ValueDescriptor, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueDescriptorList. -func (in *ValueDescriptorList) DeepCopy() *ValueDescriptorList { - if in == nil { - return nil - } - out := new(ValueDescriptorList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ValueDescriptorList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ValueDescriptorSpec) DeepCopyInto(out *ValueDescriptorSpec) { - *out = *in - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make([]string, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueDescriptorSpec. -func (in *ValueDescriptorSpec) DeepCopy() *ValueDescriptorSpec { - if in == nil { - return nil - } - out := new(ValueDescriptorSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ValueDescriptorStatus) DeepCopyInto(out *ValueDescriptorStatus) { +func (in *ResourceProperties) DeepCopyInto(out *ResourceProperties) { *out = *in } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueDescriptorStatus. -func (in *ValueDescriptorStatus) DeepCopy() *ValueDescriptorStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceProperties. +func (in *ResourceProperties) DeepCopy() *ResourceProperties { if in == nil { return nil } - out := new(ValueDescriptorStatus) + out := new(ResourceProperties) in.DeepCopyInto(out) return out } diff --git a/clients/edgex-foundry/device_client.go b/clients/edgex-foundry/device_client.go index 0277c3b..870bd81 100644 --- a/clients/edgex-foundry/device_client.go +++ b/clients/edgex-foundry/device_client.go @@ -26,11 +26,14 @@ import ( "strings" "time" - "github.com/edgexfoundry/go-mod-core-contracts/models" + "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos" + + edgex_resp "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/responses" "github.com/go-resty/resty/v2" "golang.org/x/net/publicsuffix" "k8s.io/klog/v2" + "github.com/openyurtio/device-controller/api/v1alpha1" devicev1alpha1 "github.com/openyurtio/device-controller/api/v1alpha1" edgeCli "github.com/openyurtio/device-controller/clients" ) @@ -120,40 +123,37 @@ func (efc *EdgexDeviceClient) Update(ctx context.Context, device *devicev1alpha1 // Get is used to query the device information corresponding to the device name func (efc *EdgexDeviceClient) Get(ctx context.Context, deviceName string, options edgeCli.GetOptions) (*devicev1alpha1.Device, error) { klog.V(5).Infof("will get Devices: %s", deviceName) - var device devicev1alpha1.Device + var dResp edgex_resp.DeviceResponse getURL := fmt.Sprintf("http://%s%s/name/%s", efc.CoreMetaAddr, DevicePath, deviceName) resp, err := efc.R().Get(getURL) if err != nil { - return &device, err + return nil, err + } + if resp.StatusCode() == http.StatusNotFound { + return nil, fmt.Errorf("Device %s not found", deviceName) } - if string(resp.Body()) == "Item not found\n" { - return &device, errors.New("Item not found") + err = json.Unmarshal(resp.Body(), &dResp) + if err != nil { + return nil, err } - var dp models.Device - err = json.Unmarshal(resp.Body(), &dp) - device = toKubeDevice(dp) + device := toKubeDevice(dResp.Device) return &device, err } // List is used to get all device objects on edge platform -// The Hanoi version currently supports only a single label and does not support other filters +// TODO:support label filtering according to options func (efc *EdgexDeviceClient) List(ctx context.Context, options edgeCli.ListOptions) ([]devicev1alpha1.Device, error) { - lp := fmt.Sprintf("http://%s%s", efc.CoreMetaAddr, DevicePath) - if options.LabelSelector != nil { - if _, ok := options.LabelSelector["label"]; ok { - lp = strings.Join([]string{lp, strings.Join([]string{"label", options.LabelSelector["label"]}, "/")}, "/") - } - } + lp := fmt.Sprintf("http://%s%s/all?limit=-1", efc.CoreMetaAddr, DevicePath) resp, err := efc.R().EnableTrace().Get(lp) if err != nil { return nil, err } - dps := []models.Device{} - if err := json.Unmarshal(resp.Body(), &dps); err != nil { + var mdResp edgex_resp.MultiDevicesResponse + if err := json.Unmarshal(resp.Body(), &mdResp); err != nil { return nil, err } var res []devicev1alpha1.Device - for _, dp := range dps { + for _, dp := range mdResp.Devices { res = append(res, toKubeDevice(dp)) } return res, nil @@ -164,20 +164,20 @@ func (efc *EdgexDeviceClient) GetPropertyState(ctx context.Context, propertyName // get the old property from status oldAps, exist := d.Status.DeviceProperties[propertyName] propertyGetURL := "" - // 1. query the Get URL of an property + // 1. query the Get URL of a property if !exist || (exist && oldAps.GetURL == "") { - commandRep, err := efc.GetCommandResponseByName(actualDeviceName) + coreCommands, err := efc.GetCommandResponseByName(actualDeviceName) if err != nil { return &devicev1alpha1.ActualPropertyState{}, err } - for _, c := range commandRep.Commands { - if c.Name == propertyName { - propertyGetURL = c.Get.URL + for _, c := range coreCommands { + if c.Name == propertyName && c.Get { + propertyGetURL = fmt.Sprintf("%s%s", c.Url, c.Path) break } } if propertyGetURL == "" { - return nil, fmt.Errorf("this property %s is not exist", propertyName) + return nil, &edgeCli.NotFoundError{} } } else { propertyGetURL = oldAps.GetURL @@ -190,11 +190,11 @@ func (efc *EdgexDeviceClient) GetPropertyState(ctx context.Context, propertyName if resp, err := getPropertyState(propertyGetURL); err != nil { return nil, err } else { - var event models.Event - if err := json.Unmarshal(resp.Body(), &event); err != nil { - return &devicev1alpha1.ActualPropertyState{}, err + var eResp edgex_resp.EventResponse + if err := json.Unmarshal(resp.Body(), &eResp); err != nil { + return nil, err } - actualPropertyState.ActualValue = getPropertyValueFromEvent(propertyName, event) + actualPropertyState.ActualValue = getPropertyValueFromEvent(propertyName, eResp.Event) } return &actualPropertyState, nil } @@ -229,21 +229,20 @@ func (efc *EdgexDeviceClient) UpdatePropertyState(ctx context.Context, propertyN dps := d.Spec.DeviceProperties[propertyName] parameterName := dps.Name if dps.PutURL == "" { - put, err := efc.getPropertyPut(acturalDeviceName, dps.Name) + putCmd, err := efc.getPropertyPut(acturalDeviceName, dps.Name) if err != nil { return err } - dps.PutURL = put.URL - if len(put.ParameterNames) == 1 { - parameterName = put.ParameterNames[0] + dps.PutURL = fmt.Sprintf("%s%s", putCmd.Url, putCmd.Path) + if len(putCmd.Parameters) == 1 { + parameterName = putCmd.Parameters[0].ResourceName } - } // set the device property to desired state bodyMap := make(map[string]string) bodyMap[parameterName] = dps.DesiredValue body, _ := json.Marshal(bodyMap) - klog.V(5).Infof("setting the property %s to desired value", "propertyName", parameterName, "desiredValue", string(body)) + klog.V(5).Infof("setting the property to desired value", "propertyName", parameterName, "desiredValue", string(body)) rep, err := resty.New().R(). SetHeader("Content-Type", "application/json"). SetBody(body). @@ -263,97 +262,103 @@ func (efc *EdgexDeviceClient) UpdatePropertyState(ctx context.Context, propertyN } // Gets the models.Put from edgex foundry which is used to set the device property's value -func (efc *EdgexDeviceClient) getPropertyPut(deviceName, cmdName string) (models.Put, error) { - cr, err := efc.GetCommandResponseByName(deviceName) +func (efc *EdgexDeviceClient) getPropertyPut(deviceName, cmdName string) (dtos.CoreCommand, error) { + coreCommands, err := efc.GetCommandResponseByName(deviceName) if err != nil { - return models.Put{}, err + return dtos.CoreCommand{}, err } - for _, c := range cr.Commands { - if cmdName == c.Name { - return c.Put, nil + for _, c := range coreCommands { + if cmdName == c.Name && c.Set { + return c, nil } } - return models.Put{}, errors.New("corresponding command is not found") + return dtos.CoreCommand{}, errors.New("corresponding command is not found") } // ListPropertiesState gets all the actual property information about a device -func (efc *EdgexDeviceClient) ListPropertiesState(ctx context.Context, device *devicev1alpha1.Device, options edgeCli.ListOptions) (map[string]devicev1alpha1.DesiredPropertyState, map[string]devicev1alpha1.ActualPropertyState, error) { +func (efc *EdgexDeviceClient) ListPropertiesState(ctx context.Context, device *devicev1alpha1.Device, options edgeCli.ListOptions) (map[string]v1alpha1.DesiredPropertyState, map[string]devicev1alpha1.ActualPropertyState, error) { actualDeviceName := getEdgeDeviceName(device) - dps := map[string]devicev1alpha1.DesiredPropertyState{} - aps := map[string]devicev1alpha1.ActualPropertyState{} - cr, err := efc.GetCommandResponseByName(actualDeviceName) + dpsm := map[string]devicev1alpha1.DesiredPropertyState{} + apsm := map[string]devicev1alpha1.ActualPropertyState{} + coreCommands, err := efc.GetCommandResponseByName(actualDeviceName) if err != nil { - return dps, aps, err + return dpsm, apsm, err } - for _, c := range cr.Commands { + for _, c := range coreCommands { // DesiredPropertyState only store the basic information and does not set DesiredValue - resp, err := getPropertyState(c.Get.URL) - dps[c.Name] = devicev1alpha1.DesiredPropertyState{Name: c.Name, PutURL: c.Put.URL} - if err != nil { - aps[c.Name] = devicev1alpha1.ActualPropertyState{Name: c.Name, GetURL: c.Get.URL} - klog.V(5).ErrorS(err, "getPropertyState failed", "propertyName", c.Name, "deviceName", actualDeviceName) - } else { - var event models.Event - if err := json.Unmarshal(resp.Body(), &event); err != nil { - klog.V(5).ErrorS(err, "failed to decode the response ", "response", resp) - continue + if c.Get { + getURL := fmt.Sprintf("%s%s", c.Url, c.Path) + aps, ok := apsm[c.Name] + if ok { + aps.GetURL = getURL + } else { + aps = devicev1alpha1.ActualPropertyState{Name: c.Name, GetURL: getURL} } - readingName := c.Name - getResp := c.Get.Responses - for _, it := range getResp { - if it.Code == "200" { - expectValues := it.ExpectedValues - if len(expectValues) == 1 { - readingName = expectValues[0] - } + apsm[c.Name] = aps + resp, err := getPropertyState(getURL) + if err != nil { + klog.V(5).ErrorS(err, "getPropertyState failed", "propertyName", c.Name, "deviceName", actualDeviceName) + } else { + var eResp edgex_resp.EventResponse + if err := json.Unmarshal(resp.Body(), &eResp); err != nil { + klog.V(5).ErrorS(err, "failed to decode the response ", "response", resp) + continue + } + event := eResp.Event + readingName := c.Name + expectParams := c.Parameters + if len(expectParams) == 1 { + readingName = expectParams[0].ResourceName } + klog.V(5).Infof("get reading name %s for command %s of device %s", readingName, c.Name, device.Name) + actualValue := getPropertyValueFromEvent(readingName, event) + aps.ActualValue = actualValue + apsm[c.Name] = aps } - klog.V(5).Infof("get reading name %s for command %s of device %s", readingName, c.Name, device.Name) - actualValue := getPropertyValueFromEvent(readingName, event) - - aps[c.Name] = devicev1alpha1.ActualPropertyState{Name: c.Name, GetURL: c.Get.URL, ActualValue: actualValue} } } - return dps, aps, nil + return dpsm, apsm, nil } // The actual property value is resolved from the returned event -func getPropertyValueFromEvent(propertyName string, modelEvent models.Event) string { +func getPropertyValueFromEvent(resName string, event dtos.Event) string { actualValue := "" - if len(modelEvent.Readings) == 1 { - if propertyName == modelEvent.Readings[0].Name { - actualValue = modelEvent.Readings[0].Value - } - } else { - for _, k := range modelEvent.Readings { - currentProperty := strings.Join([]string{k.Name, k.Value}, ":") - if actualValue == "" { - actualValue = currentProperty - } else { - actualValue = strings.Join([]string{actualValue, currentProperty}, ", ") + for _, r := range event.Readings { + if resName == r.ResourceName { + if r.SimpleReading.Value != "" { + actualValue = r.SimpleReading.Value + } else if len(r.BinaryReading.BinaryValue) != 0 { + // TODO: how to demonstrate binary data + actualValue = fmt.Sprintf("%s:%s", r.BinaryReading.MediaType, "blob value") + } else if r.ObjectReading.ObjectValue != nil { + serializedBytes, _ := json.Marshal(r.ObjectReading.ObjectValue) + actualValue = string(serializedBytes) } + break } } return actualValue } // GetCommandResponseByName gets all commands supported by the device -func (efc *EdgexDeviceClient) GetCommandResponseByName(deviceName string) ( - models.CommandResponse, error) { +func (efc *EdgexDeviceClient) GetCommandResponseByName(deviceName string) ([]dtos.CoreCommand, error) { klog.V(5).Infof("will get CommandResponses of device: %s", deviceName) - var vd models.CommandResponse + var dcr edgex_resp.DeviceCoreCommandResponse getURL := fmt.Sprintf("http://%s%s/name/%s", efc.CoreCommandAddr, CommandResponsePath, deviceName) resp, err := efc.R().Get(getURL) if err != nil { - return vd, err + return nil, err + } + if resp.StatusCode() == http.StatusNotFound { + return nil, errors.New("Item not found") } - if strings.Contains(string(resp.Body()), "Item not found") { - return vd, errors.New("Item not found") + err = json.Unmarshal(resp.Body(), &dcr) + if err != nil { + return nil, err } - err = json.Unmarshal(resp.Body(), &vd) - return vd, err + return dcr.DeviceCoreCommand.CoreCommands, nil } diff --git a/clients/edgex-foundry/deviceprofile_client.go b/clients/edgex-foundry/deviceprofile_client.go index 74027dc..df5f2d0 100644 --- a/clients/edgex-foundry/deviceprofile_client.go +++ b/clients/edgex-foundry/deviceprofile_client.go @@ -19,17 +19,16 @@ package edgex_foundry import ( "context" "encoding/json" - "errors" "fmt" "net/http" - "github.com/edgexfoundry/go-mod-core-contracts/models" + "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/responses" + "github.com/go-resty/resty/v2" "k8s.io/klog/v2" "github.com/openyurtio/device-controller/api/v1alpha1" devcli "github.com/openyurtio/device-controller/clients" - strutil "github.com/openyurtio/device-controller/controllers/util" ) type EdgexDeviceProfile struct { @@ -44,25 +43,9 @@ func NewEdgexDeviceProfile(coreMetaAddr string) *EdgexDeviceProfile { } } +//TODO: support label filtering func getListDeviceProfileURL(address string, opts devcli.ListOptions) (string, error) { - url := fmt.Sprintf("http://%s%s", address, DeviceProfilePath) - if len(opts.LabelSelector) > 1 { - return url, fmt.Errorf("Multiple labels: list only support one label") - } - if len(opts.LabelSelector) > 0 && len(opts.LabelSelector) > 0 { - return url, fmt.Errorf("Multi list options: list action can't use 'label' with 'manufacturer' or 'model'") - } - for _, v := range opts.LabelSelector { - url = fmt.Sprintf("%s/label/%s", url, v) - } - - listParameters := []string{"manufacturer", "model"} - for k, v := range opts.FieldSelector { - if !strutil.IsInStringLst(listParameters, k) { - return url, fmt.Errorf("Invaild list options: %s", k) - } - url = fmt.Sprintf("%s/%s/%s", url, k, v) - } + url := fmt.Sprintf("http://%s%s/all?limit=-1", address, DeviceProfilePath) return url, nil } @@ -76,32 +59,32 @@ func (cdc *EdgexDeviceProfile) List(ctx context.Context, opts devcli.ListOptions if err != nil { return nil, err } - dps := []models.DeviceProfile{} - if err := json.Unmarshal(resp.Body(), &dps); err != nil { + var mdpResp responses.MultiDeviceProfilesResponse + if err := json.Unmarshal(resp.Body(), &mdpResp); err != nil { return nil, err } - deviceProfiles := make([]v1alpha1.DeviceProfile, len(dps)) - for i, dp := range dps { - deviceProfiles[i] = toKubeDeviceProfile(&dp) + var deviceProfiles []v1alpha1.DeviceProfile + for _, dp := range mdpResp.Profiles { + deviceProfiles = append(deviceProfiles, toKubeDeviceProfile(&dp)) } return deviceProfiles, nil } func (cdc *EdgexDeviceProfile) Get(ctx context.Context, name string, opts devcli.GetOptions) (*v1alpha1.DeviceProfile, error) { klog.V(5).Infof("will get DeviceProfiles: %s", name) - var dp models.DeviceProfile + var dpResp responses.DeviceProfileResponse getURL := fmt.Sprintf("http://%s%s/name/%s", cdc.CoreMetaAddr, DeviceProfilePath, name) resp, err := cdc.R().Get(getURL) if err != nil { return nil, err } - if string(resp.Body()) == "Item not found\n" { - return nil, errors.New("Item not found") + if resp.StatusCode() == http.StatusNotFound { + return nil, fmt.Errorf("DeviceProfile %s not found", name) } - if err = json.Unmarshal(resp.Body(), &dp); err != nil { + if err = json.Unmarshal(resp.Body(), &dpResp); err != nil { return nil, err } - kubedp := toKubeDeviceProfile(&dp) + kubedp := toKubeDeviceProfile(&dpResp.Profile) return &kubedp, nil } @@ -124,7 +107,7 @@ func (cdc *EdgexDeviceProfile) Create(ctx context.Context, deviceProfile *v1alph return deviceProfile, err } -// TODO +// TODO: edgex does not support update DeviceProfile func (cdc *EdgexDeviceProfile) Update(ctx context.Context, deviceProfile *v1alpha1.DeviceProfile, opts devcli.UpdateOptions) (*v1alpha1.DeviceProfile, error) { return nil, nil } diff --git a/clients/edgex-foundry/deviceservice_client.go b/clients/edgex-foundry/deviceservice_client.go index 4644e70..4b101b5 100644 --- a/clients/edgex-foundry/deviceservice_client.go +++ b/clients/edgex-foundry/deviceservice_client.go @@ -22,9 +22,9 @@ import ( "errors" "fmt" "net/http" - "strings" - "github.com/edgexfoundry/go-mod-core-contracts/models" + "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/responses" + "github.com/go-resty/resty/v2" "k8s.io/klog/v2" @@ -82,151 +82,71 @@ func (eds *EdgexDeviceServiceClient) Delete(ctx context.Context, name string, op // Update is used to set the admin or operating state of the deviceService by unique name of the deviceService. // TODO support to update other fields func (eds *EdgexDeviceServiceClient) Update(ctx context.Context, ds *v1alpha1.DeviceService, options edgeCli.UpdateOptions) (*v1alpha1.DeviceService, error) { - actualDSName := getEdgeDeviceServiceName(ds) - putBaseURL := fmt.Sprintf("http://%s%s/name/%s", eds.CoreMetaAddr, DeviceServicePath, actualDSName) + patchURL := fmt.Sprintf("http://%s%s", eds.CoreMetaAddr, DeviceServicePath) if ds == nil { return nil, nil } - if ds.Spec.AdminState != "" { - amURL := fmt.Sprintf("%s/adminstate/%s", putBaseURL, ds.Spec.AdminState) - if rep, err := resty.New().R().SetHeader("Content-Type", "application/json").Put(amURL); err != nil { - return nil, err - } else if rep.StatusCode() != http.StatusOK { - return nil, fmt.Errorf("failed to update deviceService: %s, get response: %s", actualDSName, string(rep.Body())) - } - } - if ds.Spec.OperatingState != "" { - opURL := fmt.Sprintf("%s/opstate/%s", putBaseURL, ds.Spec.OperatingState) - if rep, err := resty.New().R(). - SetHeader("Content-Type", "application/json").Put(opURL); err != nil { - return nil, err - } else if rep.StatusCode() != http.StatusOK { - return nil, fmt.Errorf("failed to update deviceService: %s, get response: %s", actualDSName, string(rep.Body())) - } - } - - return ds, nil -} - -// Get is used to query the deviceService information corresponding to the deviceService name -func (eds *EdgexDeviceServiceClient) Get(ctx context.Context, name string, options edgeCli.GetOptions) (*v1alpha1.DeviceService, error) { - klog.V(5).InfoS("will get DeviceServices", "DeviceService", name) - var ds v1alpha1.DeviceService - getURL := fmt.Sprintf("http://%s%s/name/%s", eds.CoreMetaAddr, DeviceServicePath, name) - resp, err := eds.R().Get(getURL) - if err != nil { - return &ds, err - } - if string(resp.Body()) == "Item not found\n" || - strings.HasPrefix(string(resp.Body()), "no item found") { - return &ds, errors.New("Item not found") - } - var dp models.DeviceService - err = json.Unmarshal(resp.Body(), &dp) - ds = toKubeDeviceService(dp) - return &ds, err -} -// List is used to get all deviceService objects on edge platform -// The Hanoi version currently supports only a single label and does not support other filters -func (eds *EdgexDeviceServiceClient) List(ctx context.Context, options edgeCli.ListOptions) ([]v1alpha1.DeviceService, error) { - klog.V(5).Info("will list DeviceServices") - lp := fmt.Sprintf("http://%s%s", eds.CoreMetaAddr, DeviceServicePath) - if options.LabelSelector != nil { - if _, ok := options.LabelSelector["label"]; ok { - lp = strings.Join([]string{lp, strings.Join([]string{"label", options.LabelSelector["label"]}, "/")}, "/") - } + if ds.Status.EdgeId == "" { + return nil, fmt.Errorf("failed to update deviceservice %s with empty edgex id", ds.Name) } - resp, err := eds.R(). - EnableTrace(). - Get(lp) + edgeDs := toEdgexDeviceService(ds) + edgeDs.Id = ds.Status.EdgeId + dsJson, err := json.Marshal(&edgeDs) if err != nil { return nil, err } - dss := []models.DeviceService{} - if err := json.Unmarshal(resp.Body(), &dss); err != nil { - return nil, err - } - var res []v1alpha1.DeviceService - for _, ds := range dss { - res = append(res, toKubeDeviceService(ds)) - } - return res, nil -} - -// CreateAddressable function sends a POST request to EdgeX to add a new addressable -func (eds *EdgexDeviceServiceClient) CreateAddressable(ctx context.Context, addressable *v1alpha1.Addressable, options edgeCli.CreateOptions) (*v1alpha1.Addressable, error) { - as := toEdgeXAddressable(addressable) - klog.V(5).InfoS("will add the Addressable", "Addressable", as.Name) - dpJson, err := json.Marshal(&as) - if err != nil { - return nil, err - } - postPath := fmt.Sprintf("http://%s%s", eds.CoreMetaAddr, AddressablePath) resp, err := eds.R(). - SetBody(dpJson).Post(postPath) + SetBody(dsJson).Patch(patchURL) if err != nil { return nil, err } - createdAddr := addressable.DeepCopy() - createdAddr.Id = string(resp.Body()) - return createdAddr, err -} -// DeleteAddressable function sends a request to EdgeX to delete a addressable -func (eds *EdgexDeviceServiceClient) DeleteAddressable(ctx context.Context, name string, options edgeCli.DeleteOptions) error { - klog.V(5).InfoS("will delete the Addressable", "Addressable", name) - delURL := fmt.Sprintf("http://%s%s/name/%s", eds.CoreMetaAddr, AddressablePath, name) - resp, err := eds.R().Delete(delURL) - if err != nil { - return err + if resp.StatusCode() == http.StatusOK || resp.StatusCode() == http.StatusMultiStatus { + return ds, nil + } else { + return nil, fmt.Errorf("request to patch deviceservice failed, errcode:%d", resp.StatusCode()) } - if string(resp.Body()) != "true" { - return errors.New(string(resp.Body())) - } - return nil } -// UpdateAddressable is used to update the addressable on edgex foundry -func (eds *EdgexDeviceServiceClient) UpdateAddressable(ctx context.Context, device *v1alpha1.Addressable, options edgeCli.UpdateOptions) (*v1alpha1.Addressable, error) { - return nil, nil -} - -// GetAddressable is used to query the addressable information corresponding to the addressable name -func (eds *EdgexDeviceServiceClient) GetAddressable(ctx context.Context, name string, options edgeCli.GetOptions) (*v1alpha1.Addressable, error) { - klog.V(5).InfoS("will get Addressable", "Addressable", name) - var addressable v1alpha1.Addressable - getURL := fmt.Sprintf("http://%s%s/name/%s", eds.CoreMetaAddr, AddressablePath, name) +// Get is used to query the deviceService information corresponding to the deviceService name +func (eds *EdgexDeviceServiceClient) Get(ctx context.Context, name string, options edgeCli.GetOptions) (*v1alpha1.DeviceService, error) { + klog.V(5).InfoS("will get DeviceServices", "DeviceService", name) + var dsResp responses.DeviceServiceResponse + getURL := fmt.Sprintf("http://%s%s/name/%s", eds.CoreMetaAddr, DeviceServicePath, name) resp, err := eds.R().Get(getURL) if err != nil { - return &addressable, err + return nil, err } - if string(resp.Body()) == "Item not found\n" { - return &addressable, errors.New("Item not found") + if resp.StatusCode() == http.StatusNotFound { + return nil, fmt.Errorf("deviceservice %s not found", name) + } + err = json.Unmarshal(resp.Body(), &dsResp) + if err != nil { + return nil, err } - var maddr models.Addressable - err = json.Unmarshal(resp.Body(), &maddr) - addressable = toKubeAddressable(maddr) - return &addressable, err + ds := toKubeDeviceService(dsResp.Service) + return &ds, nil } -// ListAddressables is used to get all addressable objects on edge platform -func (eds *EdgexDeviceServiceClient) ListAddressables(ctx context.Context, options edgeCli.ListOptions) ([]v1alpha1.Addressable, error) { - klog.V(5).Info("will list Addressables") - lp := fmt.Sprintf("http://%s%s", eds.CoreMetaAddr, AddressablePath) +// List is used to get all deviceService objects on edge platform +// The Hanoi version currently supports only a single label and does not support other filters +func (eds *EdgexDeviceServiceClient) List(ctx context.Context, options edgeCli.ListOptions) ([]v1alpha1.DeviceService, error) { + klog.V(5).Info("will list DeviceServices") + lp := fmt.Sprintf("http://%s%s/all?limit=-1", eds.CoreMetaAddr, DeviceServicePath) resp, err := eds.R(). EnableTrace(). Get(lp) if err != nil { return nil, err } - ass := []models.Addressable{} - if err := json.Unmarshal(resp.Body(), &ass); err != nil { + var mdsResponse responses.MultiDeviceServicesResponse + if err := json.Unmarshal(resp.Body(), &mdsResponse); err != nil { return nil, err } - var res []v1alpha1.Addressable - for i := range ass { - res = append(res, toKubeAddressable(ass[i])) + var res []v1alpha1.DeviceService + for _, ds := range mdsResponse.Services { + res = append(res, toKubeDeviceService(ds)) } return res, nil } diff --git a/clients/edgex-foundry/util.go b/clients/edgex-foundry/util.go index 0f52c09..a7fc3b3 100644 --- a/clients/edgex-foundry/util.go +++ b/clients/edgex-foundry/util.go @@ -19,7 +19,9 @@ package edgex_foundry import ( "strings" - "github.com/edgexfoundry/go-mod-core-contracts/models" + "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos" + + "github.com/edgexfoundry/go-mod-core-contracts/v2/models" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" devicev1alpha1 "github.com/openyurtio/device-controller/api/v1alpha1" @@ -27,11 +29,10 @@ import ( const ( EdgeXObjectName = "device-controller/edgex-object.name" - DeviceServicePath = "/api/v1/deviceservice" - DeviceProfilePath = "/api/v1/deviceprofile" - AddressablePath = "/api/v1/addressable" - DevicePath = "/api/v1/device" - CommandResponsePath = "/api/v1/device" + DeviceServicePath = "/api/v2/deviceservice" + DeviceProfilePath = "/api/v2/deviceprofile" + DevicePath = "/api/v2/device" + CommandResponsePath = "/api/v2/device" ) type ClientURL struct { @@ -39,16 +40,6 @@ type ClientURL struct { Port int } -func getEdgeDeviceServiceName(ds *devicev1alpha1.DeviceService) string { - var actualDSName string - if _, ok := ds.ObjectMeta.Labels[EdgeXObjectName]; ok { - actualDSName = ds.ObjectMeta.Labels[EdgeXObjectName] - } else { - actualDSName = ds.GetName() - } - return actualDSName -} - func getEdgeDeviceName(d *devicev1alpha1.Device) string { var actualDeviceName string if _, ok := d.ObjectMeta.Labels[EdgeXObjectName]; ok { @@ -61,17 +52,14 @@ func getEdgeDeviceName(d *devicev1alpha1.Device) string { func toEdgexDeviceService(ds *devicev1alpha1.DeviceService) models.DeviceService { return models.DeviceService{ - DescribedObject: models.DescribedObject{ - Description: ds.Spec.Description, - }, - Name: ds.GetName(), + Description: ds.Spec.Description, + Name: ds.GetName(), //Id: ds.Spec.Id, - LastConnected: ds.Status.LastConnected, - LastReported: ds.Status.LastReported, - OperatingState: models.OperatingState(ds.Spec.OperatingState), - Labels: ds.Spec.Labels, - AdminState: models.AdminState(ds.Spec.AdminState), - Addressable: toEdgeXAddressable(&ds.Spec.Addressable), + LastConnected: ds.Status.LastConnected, + LastReported: ds.Status.LastReported, + Labels: ds.Spec.Labels, + AdminState: models.AdminState(ds.Spec.AdminState), + BaseAddress: ds.Spec.BaseAddress, } } @@ -93,30 +81,25 @@ func toEdgeXDeviceResource(dr devicev1alpha1.DeviceResource) models.DeviceResour } } -func toEdgeXProfileProperty(pp devicev1alpha1.ProfileProperty) models.ProfileProperty { - return models.ProfileProperty{ - Value: toEdgeXPropertyValue(pp.Value), - Units: toEdgeXUnits(pp.Units), +func toEdgeXProfileProperty(pp devicev1alpha1.ResourceProperties) models.ResourceProperties { + return models.ResourceProperties{ + ReadWrite: pp.ReadWrite, + Minimum: pp.Minimum, + Maximum: pp.Maximum, + DefaultValue: pp.DefaultValue, + Mask: pp.Mask, + Shift: pp.Shift, + Scale: pp.Scale, + Offset: pp.Offset, + Base: pp.Base, + Assertion: pp.Assertion, + MediaType: pp.MediaType, + Units: pp.Units, + ValueType: pp.ValueType, } } -func toEdgeXAddressable(a *devicev1alpha1.Addressable) models.Addressable { - return models.Addressable{ - Id: a.Id, - Name: a.Name, - Protocol: a.Protocol, - HTTPMethod: a.HTTPMethod, - Address: a.Address, - Port: a.Port, - Path: a.Path, - Publisher: a.Publisher, - User: a.User, - Password: a.Password, - Topic: a.Topic, - } -} - -func toKubeDeviceService(ds models.DeviceService) devicev1alpha1.DeviceService { +func toKubeDeviceService(ds dtos.DeviceService) devicev1alpha1.DeviceService { return devicev1alpha1.DeviceService{ ObjectMeta: metav1.ObjectMeta{ Name: strings.ToLower(ds.Name), @@ -126,85 +109,23 @@ func toKubeDeviceService(ds models.DeviceService) devicev1alpha1.DeviceService { }, }, Spec: devicev1alpha1.DeviceServiceSpec{ - Description: ds.Description, - OperatingState: toKubeOperatingState(ds.OperatingState), - Labels: ds.Labels, - Addressable: toKubeAddressable(ds.Addressable), - AdminState: toKubeAdminState(ds.AdminState), + Description: ds.Description, + Labels: ds.Labels, + AdminState: devicev1alpha1.AdminState(ds.AdminState), + BaseAddress: ds.BaseAddress, }, Status: devicev1alpha1.DeviceServiceStatus{ EdgeId: ds.Id, LastConnected: ds.LastConnected, LastReported: ds.LastReported, - AdminState: toKubeAdminState(ds.AdminState), + AdminState: devicev1alpha1.AdminState(ds.AdminState), }, } } -func toEdgeXPropertyValue(pv devicev1alpha1.PropertyValue) models.PropertyValue { - return models.PropertyValue{ - Type: pv.Type, - ReadWrite: pv.ReadWrite, - Minimum: pv.Minimum, - Maximum: pv.Maximum, - DefaultValue: pv.DefaultValue, - Size: pv.Size, - Mask: pv.Mask, - Shift: pv.Shift, - Scale: pv.Scale, - Offset: pv.Offset, - Base: pv.Base, - Assertion: pv.Assertion, - Precision: pv.Precision, - FloatEncoding: pv.FloatEncoding, - MediaType: pv.MediaType, - } -} - -func toEdgeXUnits(u devicev1alpha1.Units) models.Units { - return models.Units{ - Type: u.Type, - ReadWrite: u.ReadWrite, - DefaultValue: u.DefaultValue, - } -} - -func toEdgeXProfileResource(pr devicev1alpha1.ProfileResource) models.ProfileResource { - gros := []models.ResourceOperation{} - for _, gro := range pr.Get { - gros = append(gros, toEdgeXResourceOperation(gro)) - } - sros := []models.ResourceOperation{} - for _, sro := range pr.Set { - sros = append(sros, toEdgeXResourceOperation(sro)) - } - return models.ProfileResource{ - Name: pr.Name, - Get: gros, - Set: sros, - } -} - -func toEdgeXResourceOperation(ro devicev1alpha1.ResourceOperation) models.ResourceOperation { - return models.ResourceOperation{ - Index: ro.Index, - Operation: ro.Operation, - Object: ro.Object, - DeviceResource: ro.DeviceResource, - Parameter: ro.Parameter, - Resource: ro.Resource, - DeviceCommand: ro.DeviceCommand, - Secondary: ro.Secondary, - Mappings: ro.Mappings, - } -} - func toEdgeXDevice(d *devicev1alpha1.Device) models.Device { md := models.Device{ - DescribedObject: models.DescribedObject{ - Description: d.Spec.Description, - }, - Id: d.Status.EdgeId, + Description: d.Spec.Description, Name: d.GetName(), AdminState: toEdgeXAdminState(d.Spec.AdminState), OperatingState: toEdgeXOperatingState(d.Spec.OperatingState), @@ -213,14 +134,9 @@ func toEdgeXDevice(d *devicev1alpha1.Device) models.Device { LastReported: d.Status.LastReported, Labels: d.Spec.Labels, Location: d.Spec.Location, - Service: models.DeviceService{Name: d.Spec.Service}, - Profile: toEdgeXDeviceProfile( - devicev1alpha1.DeviceProfile{ - ObjectMeta: metav1.ObjectMeta{ - Name: d.Spec.Profile, - }, - }, - ), + ServiceName: d.Spec.Service, + ProfileName: d.Spec.Profile, + Notify: d.Spec.Notify, } if d.Status.EdgeId != "" { md.Id = d.Status.EdgeId @@ -245,81 +161,16 @@ func toEdgeXAdminState(as devicev1alpha1.AdminState) models.AdminState { } func toEdgeXOperatingState(os devicev1alpha1.OperatingState) models.OperatingState { - if os == devicev1alpha1.Enabled { - return models.Enabled - } - return models.Disabled -} - -func toEdgeXDeviceProfile( - dp devicev1alpha1.DeviceProfile) models.DeviceProfile { - cs := []models.Command{} - for _, c := range dp.Spec.CoreCommands { - cs = append(cs, toEdgeXCommand(c)) - } - dcs := []models.ProfileResource{} - for _, pr := range dp.Spec.DeviceCommands { - dcs = append(dcs, toEdgeXProfileResource(pr)) - } - - return models.DeviceProfile{ - DescribedObject: models.DescribedObject{ - Description: dp.Spec.Description, - }, - //Id: dp.Spec.Id, - Name: dp.GetName(), - Manufacturer: dp.Spec.Manufacturer, - Model: dp.Spec.Model, - //Labels: dp.Spec.Labels, - DeviceResources: toEdgeXDeviceResourceSlice(dp.Spec.DeviceResources), - DeviceCommands: dcs, - CoreCommands: cs, - } -} - -func toEdgeXCommand(c devicev1alpha1.Command) models.Command { - return models.Command{ - Id: c.EdgeId, - Name: c.Name, - Get: toEdgeXGet(c.Get), - Put: toEdgeXPut(c.Put), - } -} -func toEdgeXPut(p devicev1alpha1.Put) models.Put { - return models.Put{ - Action: toEdgeXAction(p.Action), - ParameterNames: p.ParameterNames, - } -} - -func toEdgeXGet(g devicev1alpha1.Get) models.Get { - return models.Get{ - Action: toEdgeXAction(g.Action), - } -} - -func toEdgeXAction(a devicev1alpha1.Action) models.Action { - responses := []models.Response{} - for _, r := range a.Responses { - responses = append(responses, toEdgeXResponse(r)) - } - return models.Action{ - Path: a.Path, - Responses: responses, - URL: a.URL, - } -} - -func toEdgeXResponse(r devicev1alpha1.Response) models.Response { - return models.Response{ - Code: r.Code, - Description: r.Description, - ExpectedValues: r.ExpectedValues, + if os == devicev1alpha1.Up { + return models.Up + } else if os == devicev1alpha1.Down { + return models.Down } + return models.Unknown } // toKubeDevice serialize the EdgeX Device to the corresponding Kubernetes Device -func toKubeDevice(ed models.Device) devicev1alpha1.Device { +func toKubeDevice(ed dtos.Device) devicev1alpha1.Device { var loc string if ed.Location != nil { loc = ed.Location.(string) @@ -334,62 +185,30 @@ func toKubeDevice(ed models.Device) devicev1alpha1.Device { }, Spec: devicev1alpha1.DeviceSpec{ Description: ed.Description, - AdminState: toKubeAdminState(ed.AdminState), - OperatingState: toKubeOperatingState(ed.OperatingState), + AdminState: devicev1alpha1.AdminState(ed.AdminState), + OperatingState: devicev1alpha1.OperatingState(ed.OperatingState), Protocols: toKubeProtocols(ed.Protocols), Labels: ed.Labels, Location: loc, - Service: ed.Service.Name, - Profile: ed.Profile.Name, + Service: ed.ServiceName, + Profile: ed.ProfileName, + // TODO: Notify }, Status: devicev1alpha1.DeviceStatus{ LastConnected: ed.LastConnected, LastReported: ed.LastReported, Synced: true, EdgeId: ed.Id, - AdminState: toKubeAdminState(ed.AdminState), - OperatingState: toKubeOperatingState(ed.OperatingState), + AdminState: devicev1alpha1.AdminState(ed.AdminState), + OperatingState: devicev1alpha1.OperatingState(ed.OperatingState), }, } } -func toKubeAddressable(ad models.Addressable) devicev1alpha1.Addressable { - return devicev1alpha1.Addressable{ - Id: ad.Id, - Name: ad.Name, - Protocol: ad.Protocol, - HTTPMethod: ad.HTTPMethod, - Address: ad.Address, - Port: ad.Port, - Path: ad.Path, - Publisher: ad.Publisher, - User: ad.User, - Password: ad.Password, - Topic: ad.Topic, - } -} - -// toKubeDevice serialize the EdgeX AdminState to the corresponding Kubernetes AdminState -func toKubeAdminState(ea models.AdminState) devicev1alpha1.AdminState { - if ea == models.Locked { - return devicev1alpha1.Locked - } - return devicev1alpha1.UnLocked -} - -// toKubeDevice serialize the EdgeX OperatingState to the corresponding -// Kubernetes OperatingState -func toKubeOperatingState(ea models.OperatingState) devicev1alpha1.OperatingState { - if ea == models.Enabled { - return devicev1alpha1.Enabled - } - return devicev1alpha1.Disabled -} - // toKubeProtocols serialize the EdgeX ProtocolProperties to the corresponding // Kubernetes OperatingState func toKubeProtocols( - eps map[string]models.ProtocolProperties) map[string]devicev1alpha1.ProtocolProperties { + eps map[string]dtos.ProtocolProperties) map[string]devicev1alpha1.ProtocolProperties { ret := map[string]devicev1alpha1.ProtocolProperties{} for k, v := range eps { ret[k] = devicev1alpha1.ProtocolProperties(v) @@ -398,7 +217,7 @@ func toKubeProtocols( } // toKubeDeviceProfile create DeviceProfile in cloud according to devicProfile in edge -func toKubeDeviceProfile(dp *models.DeviceProfile) devicev1alpha1.DeviceProfile { +func toKubeDeviceProfile(dp *dtos.DeviceProfile) devicev1alpha1.DeviceProfile { return devicev1alpha1.DeviceProfile{ ObjectMeta: metav1.ObjectMeta{ Name: strings.ToLower(dp.Name), @@ -413,7 +232,7 @@ func toKubeDeviceProfile(dp *models.DeviceProfile) devicev1alpha1.DeviceProfile Model: dp.Model, Labels: dp.Labels, DeviceResources: toKubeDeviceResources(dp.DeviceResources), - CoreCommands: toKubeCoreCommands(dp.CoreCommands), + DeviceCommands: toKubeDeviceCommand(dp.DeviceCommands), }, Status: devicev1alpha1.DeviceProfileStatus{ EdgeId: dp.Id, @@ -422,134 +241,102 @@ func toKubeDeviceProfile(dp *models.DeviceProfile) devicev1alpha1.DeviceProfile } } -func toKubeDeviceResources(drs []models.DeviceResource) []devicev1alpha1.DeviceResource { - var ret []devicev1alpha1.DeviceResource - for _, dr := range drs { - ret = append(ret, toKubeDeviceResource(dr)) +func toKubeDeviceCommand(dcs []dtos.DeviceCommand) []devicev1alpha1.DeviceCommand { + var ret []devicev1alpha1.DeviceCommand + for _, dc := range dcs { + ret = append(ret, devicev1alpha1.DeviceCommand{ + Name: dc.Name, + ReadWrite: dc.ReadWrite, + IsHidden: dc.IsHidden, + ResourceOperations: toKubeResourceOperations(dc.ResourceOperations), + }) } return ret } -func toKubeDeviceResource(dr models.DeviceResource) devicev1alpha1.DeviceResource { - return devicev1alpha1.DeviceResource{ - Description: dr.Description, - Name: dr.Name, - Tag: dr.Tag, - Properties: toKubeProfileProperty(dr.Properties), - Attributes: dr.Attributes, - } -} - -func toKubeProfileProperty(pp models.ProfileProperty) devicev1alpha1.ProfileProperty { - return devicev1alpha1.ProfileProperty{ - Value: toKubePropertyValue(pp.Value), - Units: toKubeUnits(pp.Units), - } -} - -func toKubePropertyValue(pv models.PropertyValue) devicev1alpha1.PropertyValue { - return devicev1alpha1.PropertyValue{ - Type: pv.Type, - ReadWrite: pv.ReadWrite, - Minimum: pv.Minimum, - Maximum: pv.Maximum, - DefaultValue: pv.DefaultValue, - Size: pv.Size, - Mask: pv.Mask, - Shift: pv.Shift, - Scale: pv.Scale, - Offset: pv.Offset, - Base: pv.Base, - Assertion: pv.Assertion, - Precision: pv.Precision, - FloatEncoding: pv.FloatEncoding, - MediaType: pv.MediaType, - } -} - -func toKubeUnits(u models.Units) devicev1alpha1.Units { - return devicev1alpha1.Units{ - Type: u.Type, - ReadWrite: u.ReadWrite, - DefaultValue: u.DefaultValue, - } -} - -func toKubeCoreCommands(ccs []models.Command) []devicev1alpha1.Command { - var ret []devicev1alpha1.Command - for _, cc := range ccs { - ret = append(ret, toKubeCoreCommand(cc)) +func toEdgeXDeviceCommand(dcs []devicev1alpha1.DeviceCommand) []models.DeviceCommand { + var ret []models.DeviceCommand + for _, dc := range dcs { + ret = append(ret, models.DeviceCommand{ + Name: dc.Name, + ReadWrite: dc.ReadWrite, + IsHidden: dc.IsHidden, + ResourceOperations: toEdgeXResourceOperations(dc.ResourceOperations), + }) } return ret } -func toKubeCoreCommand(cc models.Command) devicev1alpha1.Command { - return devicev1alpha1.Command{ - Name: cc.Name, - EdgeId: cc.Id, - Get: toKubeGet(cc.Get), - Put: toKubePut(cc.Put), - } -} - -func toKubeGet(get models.Get) devicev1alpha1.Get { - return devicev1alpha1.Get{ - Action: toKubeAction(get.Action), +func toKubeResourceOperations(ros []dtos.ResourceOperation) []devicev1alpha1.ResourceOperation { + var ret []devicev1alpha1.ResourceOperation + for _, ro := range ros { + ret = append(ret, devicev1alpha1.ResourceOperation{ + DeviceResource: ro.DeviceResource, + Mappings: ro.Mappings, + DefaultValue: ro.DefaultValue, + }) } + return ret } -func toKubePut(put models.Put) devicev1alpha1.Put { - return devicev1alpha1.Put{ - Action: toKubeAction(put.Action), - ParameterNames: put.ParameterNames, +func toEdgeXResourceOperations(ros []devicev1alpha1.ResourceOperation) []models.ResourceOperation { + var ret []models.ResourceOperation + for _, ro := range ros { + ret = append(ret, models.ResourceOperation{ + DeviceResource: ro.DeviceResource, + Mappings: ro.Mappings, + DefaultValue: ro.DefaultValue, + }) } + return ret } -func toKubeAction(act models.Action) devicev1alpha1.Action { - return devicev1alpha1.Action{ - Path: act.Path, - Responses: toKubeResponses(act.Responses), - URL: act.URL, +func toKubeDeviceResources(drs []dtos.DeviceResource) []devicev1alpha1.DeviceResource { + var ret []devicev1alpha1.DeviceResource + for _, dr := range drs { + ret = append(ret, toKubeDeviceResource(dr)) } + return ret } -func toKubeResponses(reps []models.Response) []devicev1alpha1.Response { - var ret []devicev1alpha1.Response - for _, rep := range reps { - ret = append(ret, toKubeResponse(rep)) +func toKubeDeviceResource(dr dtos.DeviceResource) devicev1alpha1.DeviceResource { + return devicev1alpha1.DeviceResource{ + Description: dr.Description, + Name: dr.Name, + Tag: dr.Tag, + IsHidden: dr.IsHidden, + Properties: toKubeProfileProperty(dr.Properties), + Attributes: dr.Attributes, } - return ret } -func toKubeResponse(rep models.Response) devicev1alpha1.Response { - return devicev1alpha1.Response{ - Code: rep.Code, - Description: rep.Description, - ExpectedValues: rep.ExpectedValues, +func toKubeProfileProperty(rp dtos.ResourceProperties) devicev1alpha1.ResourceProperties { + return devicev1alpha1.ResourceProperties{ + ValueType: rp.ValueType, + ReadWrite: rp.ReadWrite, + Minimum: rp.Minimum, + Maximum: rp.Maximum, + DefaultValue: rp.DefaultValue, + Mask: rp.Mask, + Shift: rp.Shift, + Scale: rp.Scale, + Offset: rp.Offset, + Base: rp.Base, + Assertion: rp.Assertion, + MediaType: rp.MediaType, + Units: rp.Units, } } // ToEdgeXDeviceProfile create DeviceProfile in edge according to devicProfile in cloud func ToEdgeXDeviceProfile(dp *devicev1alpha1.DeviceProfile) *models.DeviceProfile { - cs := []models.Command{} - for _, c := range dp.Spec.CoreCommands { - cs = append(cs, toEdgeXCommand(c)) - } - dcs := []models.ProfileResource{} - for _, pr := range dp.Spec.DeviceCommands { - dcs = append(dcs, toEdgeXProfileResource(pr)) - } - return &models.DeviceProfile{ - DescribedObject: models.DescribedObject{ - Description: dp.Spec.Description, - }, + Description: dp.Spec.Description, Name: dp.GetName(), Manufacturer: dp.Spec.Manufacturer, Model: dp.Spec.Model, Labels: dp.Spec.Labels, DeviceResources: toEdgeXDeviceResourceSlice(dp.Spec.DeviceResources), - DeviceCommands: dcs, - CoreCommands: cs, + DeviceCommands: toEdgeXDeviceCommand(dp.Spec.DeviceCommands), } } diff --git a/clients/edgex-foundry/valuedescriptor_client.go b/clients/edgex-foundry/valuedescriptor_client.go deleted file mode 100644 index 5ff2d15..0000000 --- a/clients/edgex-foundry/valuedescriptor_client.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2021 The OpenYurt Authors. - -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 - - http://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. -*/ - -package edgex_foundry - -import ( - "encoding/json" - "errors" - "fmt" - - "github.com/edgexfoundry/go-mod-core-contracts/models" - "github.com/go-resty/resty/v2" - "k8s.io/klog/v2" -) - -type EdgexValueDescriptorClient struct { - *resty.Client - CoreDataAddr string -} - -const ( - ValueDescriptorPath = "/api/v1/valuedescriptor" -) - -func NewValueDescriptorClient(address string) *EdgexValueDescriptorClient { - return &EdgexValueDescriptorClient{ - Client: resty.New(), - CoreDataAddr: address, - } -} - -func (cdc *EdgexValueDescriptorClient) ListValueDescriptor() ([]models.ValueDescriptor, error) { - klog.V(5).Info("will list ValueDescriptors") - lp := fmt.Sprintf("http://%s%s", cdc.CoreDataAddr, ValueDescriptorPath) - resp, err := cdc.R(). - EnableTrace(). - Get(lp) - if err != nil { - return nil, err - } - vds := []models.ValueDescriptor{} - if err := json.Unmarshal(resp.Body(), &vds); err != nil { - return nil, err - } - return vds, nil -} - -func (cdc *EdgexValueDescriptorClient) GetValueDescriptorByName(name string) ( - models.ValueDescriptor, error) { - klog.V(5).InfoS("will get ValueDescriptors", "valuedescriptor", name) - var vd models.ValueDescriptor - getURL := fmt.Sprintf("http://%s%s/name/%s", cdc.CoreDataAddr, ValueDescriptorPath, name) - resp, err := cdc.R().Get(getURL) - if err != nil { - return vd, err - } - if string(resp.Body()) == "Item not found\n" { - return vd, errors.New("Item not found") - } - err = json.Unmarshal(resp.Body(), &vd) - return vd, err -} - -func (cdc *EdgexValueDescriptorClient) GetValueDescriptsByLabel(label string) ([]models.ValueDescriptor, error) { - panic("NOT IMPLEMENT YET") -} - -func (cdc *EdgexValueDescriptorClient) AddValueDescript(vd models.ValueDescriptor) ( - string, error) { - klog.V(5).InfoS("will add the ValueDescriptors", "valuedescriptor", vd.Name) - vdJson, err := json.Marshal(&vd) - if err != nil { - return "", err - } - postPath := fmt.Sprintf("http://%s%s", cdc.CoreDataAddr, ValueDescriptorPath) - resp, err := cdc.R(). - SetBody(vdJson).Post(postPath) - if err != nil { - return "", err - } - return string(resp.Body()), err -} - -func (cdc *EdgexValueDescriptorClient) DeleteValueDescriptorByName(name string) error { - klog.V(5).InfoS("will delete the ValueDescriptor", "valuedescriptor", name) - delURL := fmt.Sprintf("http://%s%s/name/%s", cdc.CoreDataAddr, ValueDescriptorPath, name) - resp, err := cdc.R().Delete(delURL) - if err != nil { - return err - } - if string(resp.Body()) != "true" { - return errors.New(string(resp.Body())) - } - return nil -} diff --git a/clients/interface.go b/clients/interface.go index ada1dd0..6db7dbb 100644 --- a/clients/interface.go +++ b/clients/interface.go @@ -69,7 +69,6 @@ type DevicePropertyInterface interface { // DeviceServiceInterface defines the interfaces which used to create, delete, update, get and list DeviceService objects on edge-side platform type DeviceServiceInterface interface { - AddressableInterface Create(ctx context.Context, deviceService *v1alpha1.DeviceService, options CreateOptions) (*v1alpha1.DeviceService, error) Delete(ctx context.Context, name string, options DeleteOptions) error Update(ctx context.Context, deviceService *v1alpha1.DeviceService, options UpdateOptions) (*v1alpha1.DeviceService, error) @@ -77,15 +76,6 @@ type DeviceServiceInterface interface { List(ctx context.Context, options ListOptions) ([]v1alpha1.DeviceService, error) } -// AddressableInterface defines the interfaces which used to create, delete, update, get and list Addressable objects on edge-side platform -type AddressableInterface interface { - CreateAddressable(ctx context.Context, addressable *v1alpha1.Addressable, options CreateOptions) (*v1alpha1.Addressable, error) - DeleteAddressable(ctx context.Context, name string, options DeleteOptions) error - UpdateAddressable(ctx context.Context, device *v1alpha1.Addressable, options UpdateOptions) (*v1alpha1.Addressable, error) - GetAddressable(ctx context.Context, name string, options GetOptions) (*v1alpha1.Addressable, error) - ListAddressables(ctx context.Context, options ListOptions) ([]v1alpha1.Addressable, error) -} - // DeviceProfileInterface defines the interfaces which used to create, delete, update, get and list DeviceProfile objects on edge-side platform type DeviceProfileInterface interface { Create(ctx context.Context, deviceProfile *v1alpha1.DeviceProfile, options CreateOptions) (*v1alpha1.DeviceProfile, error) @@ -94,12 +84,3 @@ type DeviceProfileInterface interface { Get(ctx context.Context, name string, options GetOptions) (*v1alpha1.DeviceProfile, error) List(ctx context.Context, options ListOptions) ([]v1alpha1.DeviceProfile, error) } - -// ValueDescriptorInterface defines the interfaces which used to create, delete, update, get and list valueDescriptor objects on edge-side platform -type ValueDescriptorInterface interface { - Create(ctx context.Context, valueDescriptor *v1alpha1.ValueDescriptor, options CreateOptions) (*v1alpha1.ValueDescriptor, error) - Delete(ctx context.Context, name string, options DeleteOptions) error - Update(ctx context.Context, valueDescriptor *v1alpha1.ValueDescriptor, options UpdateOptions) (*v1alpha1.ValueDescriptor, error) - Get(ctx context.Context, name string, options GetOptions) (*v1alpha1.ValueDescriptor, error) - List(ctx context.Context, options ListOptions) ([]v1alpha1.ValueDescriptor, error) -} diff --git a/cmd/yurt-device-controller/app/core.go b/cmd/yurt-device-controller/app/core.go index c3f068b..ae68df4 100644 --- a/cmd/yurt-device-controller/app/core.go +++ b/cmd/yurt-device-controller/app/core.go @@ -111,16 +111,6 @@ func Run(opts *options.YurtDeviceControllerOptions, stopCh <-chan struct{}) { } } - setupLog.Info("[add controllers] Adding controllers and syncers for valueDescriptor, device, deviceProfile and deviceService") - // setup the ValueDescriptor Reconciler - if err = (&controllers.ValueDescriptorReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr, opts); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "ValueDescriptor") - os.Exit(1) - } - // setup the DeviceProfile Reconciler and Syncer if err = (&controllers.DeviceProfileReconciler{ Client: mgr.GetClient(), diff --git a/cmd/yurt-device-controller/options/options.go b/cmd/yurt-device-controller/options/options.go index 9a47377..3d40df1 100644 --- a/cmd/yurt-device-controller/options/options.go +++ b/cmd/yurt-device-controller/options/options.go @@ -43,9 +43,9 @@ func NewYurtDeviceControllerOptions() *YurtDeviceControllerOptions { EnableLeaderElection: false, Nodepool: "", Namespace: "default", - CoreDataAddr: "edgex-core-data:48080", - CoreMetadataAddr: "edgex-core-metadata:48081", - CoreCommandAddr: "edgex-core-command:48082", + CoreDataAddr: "edgex-core-data:59880", + CoreMetadataAddr: "edgex-core-metadata:59881", + CoreCommandAddr: "edgex-core-command:59882", EdgeSyncPeriod: 5, } } @@ -63,9 +63,9 @@ func (o *YurtDeviceControllerOptions) AddFlags(fs *pflag.FlagSet) { fs.BoolVar(&o.EnableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+"Enabling this will ensure there is only one active controller manager.") fs.StringVar(&o.Nodepool, "nodepool", "", "The nodePool deviceController is deployed in.(just for debugging)") fs.StringVar(&o.Namespace, "namespace", "default", "The cluster namespace for edge resources synchronization.") - fs.StringVar(&o.CoreDataAddr, "core-data-address", "edgex-core-data:48080", "The address of edge core-data service.") - fs.StringVar(&o.CoreMetadataAddr, "core-metadata-address", "edgex-core-metadata:48081", "The address of edge core-metadata service.") - fs.StringVar(&o.CoreCommandAddr, "core-command-address", "edgex-core-command:48082", "The address of edge core-command service.") + fs.StringVar(&o.CoreDataAddr, "core-data-address", "edgex-core-data:59880", "The address of edge core-data service.") + fs.StringVar(&o.CoreMetadataAddr, "core-metadata-address", "edgex-core-metadata:59881", "The address of edge core-metadata service.") + fs.StringVar(&o.CoreCommandAddr, "core-command-address", "edgex-core-command:59882", "The address of edge core-command service.") fs.UintVar(&o.EdgeSyncPeriod, "edge-sync-period", 5, "The period of the device management platform synchronizing the device status to the cloud.(in seconds,not less than 5 seconds)") } diff --git a/config/crd/bases/device.openyurt.io_deviceprofiles.yaml b/config/crd/bases/device.openyurt.io_deviceprofiles.yaml index 3667bc6..3643849 100644 --- a/config/crd/bases/device.openyurt.io_deviceprofiles.yaml +++ b/config/crd/bases/device.openyurt.io_deviceprofiles.yaml @@ -52,211 +52,87 @@ spec: spec: description: DeviceProfileSpec defines the desired state of DeviceProfile properties: - coreCommands: - items: - properties: - get: - description: Get Command - properties: - path: - description: Path used by service for action on a device - or sensor - type: string - responses: - description: Responses from get or put requests to service - items: - description: Response for a Get or Put request to a service - properties: - code: - type: string - description: - type: string - expectedValues: - items: - type: string - type: array - type: object - type: array - url: - description: Url for requests from command service - type: string - type: object - id: - description: EdgeId is a unique identifier used by EdgeX Foundry, - such as a UUID - type: string - name: - description: Command name (unique on the profile) - type: string - put: - description: Put Command - properties: - parameterNames: - items: - type: string - type: array - path: - description: Path used by service for action on a device - or sensor - type: string - responses: - description: Responses from get or put requests to service - items: - description: Response for a Get or Put request to a service - properties: - code: - type: string - description: - type: string - expectedValues: - items: - type: string - type: array - type: object - type: array - url: - description: Url for requests from command service - type: string - type: object - type: object - type: array description: type: string deviceCommands: - description: TODO support the following field items: properties: - get: - items: - properties: - deviceCommand: - description: The replacement of Resource field - type: string - deviceResource: - description: The replacement of Object field - type: string - index: - type: string - mappings: - additionalProperties: - type: string - type: object - object: - description: Deprecated - type: string - operation: - type: string - parameter: - type: string - resource: - description: Deprecated - type: string - secondary: - items: - type: string - type: array - type: object - type: array + isHidden: + type: boolean name: type: string - set: + readWrite: + type: string + resourceOperations: items: properties: - deviceCommand: - description: The replacement of Resource field + defaultValue: type: string deviceResource: - description: The replacement of Object field - type: string - index: type: string mappings: additionalProperties: type: string type: object - object: - description: Deprecated - type: string - operation: - type: string - parameter: - type: string - resource: - description: Deprecated - type: string - secondary: - items: - type: string - type: array + required: + - defaultValue type: object type: array + required: + - isHidden + - name + - readWrite + - resourceOperations type: object type: array deviceResources: items: properties: attributes: - additionalProperties: - type: string type: object + x-kubernetes-preserve-unknown-fields: true description: type: string + isHidden: + type: boolean name: type: string properties: properties: + assertion: + type: string + base: + type: string + defaultValue: + type: string + mask: + type: string + maximum: + type: string + mediaType: + type: string + minimum: + type: string + offset: + type: string + readWrite: + type: string + scale: + type: string + shift: + type: string units: - properties: - defaultValue: - type: string - readWrite: - type: string - type: - type: string - type: object - value: - properties: - assertion: - description: Required value of the property, set for - checking error state. Failing an assertion condition - wil l mark the device with an error state - type: string - base: - type: string - defaultValue: - type: string - floatEncoding: - type: string - mask: - type: string - maximum: - type: string - mediaType: - type: string - minimum: - type: string - offset: - type: string - precision: - type: string - readWrite: - type: string - scale: - type: string - shift: - type: string - size: - type: string - type: - type: string - type: object + type: string + valueType: + type: string required: - - value + - valueType type: object tag: type: string required: - description + - isHidden - name - properties type: object diff --git a/config/crd/bases/device.openyurt.io_devices.yaml b/config/crd/bases/device.openyurt.io_devices.yaml index 2e158dc..55e898d 100644 --- a/config/crd/bases/device.openyurt.io_devices.yaml +++ b/config/crd/bases/device.openyurt.io_devices.yaml @@ -84,8 +84,9 @@ spec: type: string type: array location: - description: Device service specific location (interface{} is an empty - interface so it can be anything) + description: 'Device service specific location (interface{} is an + empty interface so it can be anything) TODO: location type in edgex + is interface{}' type: string managed: description: True means device is managed by cloud, cloud can update @@ -94,10 +95,12 @@ spec: nodePool: description: NodePool indicates which nodePool the device comes from type: string + notify: + type: boolean operatingState: description: Operating state (enabled/disabled) type: string - profile: + profileName: description: Associated Device Profile - Describes the device type: string protocols: @@ -107,12 +110,13 @@ spec: type: object description: A map of supported protocols for the given device type: object - service: + serviceName: description: Associated Device Service - One per device type: string required: - - profile - - service + - notify + - profileName + - serviceName type: object status: description: DeviceStatus defines the observed state of Device @@ -192,7 +196,7 @@ spec: format: int64 type: integer operatingState: - description: Operating state (enabled/disabled) + description: Operating state (up/down/unknown) type: string synced: description: Synced indicates whether the device already exists on diff --git a/config/crd/bases/device.openyurt.io_deviceservices.yaml b/config/crd/bases/device.openyurt.io_deviceservices.yaml index 9eab2db..dea78cb 100644 --- a/config/crd/bases/device.openyurt.io_deviceservices.yaml +++ b/config/crd/bases/device.openyurt.io_deviceservices.yaml @@ -55,48 +55,11 @@ spec: spec: description: DeviceServiceSpec defines the desired state of DeviceService properties: - addressable: - description: address (MQTT topic, HTTP address, serial bus, etc.) - for reaching the service - properties: - address: - description: Address of the addressable - type: string - id: - description: ID is a unique identifier for the Addressable, such - as a UUID - type: string - method: - description: Method for connecting (i.e. POST) - type: string - name: - description: Name is a unique name given to the Addressable - type: string - password: - description: Password of the user for authentication for the addressable - type: string - path: - description: Path for callbacks - type: string - port: - description: Port for the address - type: integer - protocol: - description: Protocol for the address (HTTP/TCP) - type: string - publisher: - description: For message bus protocols - type: string - topic: - description: Topic for message bus addressables - type: string - user: - description: User id for authentication - type: string - type: object adminState: description: Device Service Admin State type: string + baseAddress: + type: string description: description: Information describing the device type: string @@ -114,9 +77,8 @@ spec: description: NodePool indicates which nodePool the deviceService comes from type: string - operatingState: - description: operational state - either enabled or disabled - type: string + required: + - baseAddress type: object status: description: DeviceServiceStatus defines the observed state of DeviceService diff --git a/config/crd/bases/device.openyurt.io_valuedescriptors.yaml b/config/crd/bases/device.openyurt.io_valuedescriptors.yaml deleted file mode 100644 index 0a5a158..0000000 --- a/config/crd/bases/device.openyurt.io_valuedescriptors.yaml +++ /dev/null @@ -1,92 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: valuedescriptors.device.openyurt.io -spec: - group: device.openyurt.io - names: - kind: ValueDescriptor - listKind: ValueDescriptorList - plural: valuedescriptors - singular: valuedescriptor - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ValueDescriptor is the Schema for the valuedescriptors API NOTE - Thie struct is derived from edgex/go-mod-core-contracts/models/value-descriptor.go - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ValueDescriptorSpec defines the desired state of ValueDescriptor - properties: - created: - format: int64 - type: integer - defaultValue: - type: string - description: - type: string - floatEncoding: - type: string - formatting: - type: string - id: - type: string - labels: - items: - type: string - type: array - max: - type: string - mediaType: - type: string - min: - type: string - modified: - format: int64 - type: integer - origin: - format: int64 - type: integer - type: - type: string - uomLabel: - type: string - type: object - status: - description: ValueDescriptorStatus defines the observed state of ValueDescriptor - properties: - addedToEdgeX: - description: AddedToEdgeX indicates whether the object has been successfully - created on EdgeX Foundry - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 9d5764a..039a826 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -2,7 +2,6 @@ # since it depends on service name and namespace that are out of this kustomize package. # It should be run by config/default resources: -- bases/device.openyurt.io_valuedescriptors.yaml - bases/device.openyurt.io_deviceprofiles.yaml - bases/device.openyurt.io_devices.yaml - bases/device.openyurt.io_deviceservices.yaml @@ -11,7 +10,6 @@ resources: patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_valuedescriptors.yaml #- patches/webhook_in_deviceprofiles.yaml #- patches/webhook_in_devices.yaml #- patches/webhook_in_deviceservices.yaml @@ -19,7 +17,6 @@ patchesStrategicMerge: # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_valuedescriptors.yaml #- patches/cainjection_in_deviceprofiles.yaml #- patches/cainjection_in_devices.yaml #- patches/cainjection_in_deviceservices.yaml diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 999b718..d862ad4 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -84,29 +84,3 @@ rules: - get - patch - update -- apiGroups: - - device.openyurt.io - resources: - - valuedescriptors - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - device.openyurt.io - resources: - - valuedescriptors/finalizers - verbs: - - update -- apiGroups: - - device.openyurt.io - resources: - - valuedescriptors/status - verbs: - - get - - patch - - update diff --git a/config/setup/crd.yaml b/config/setup/crd.yaml index c3dc504..d50763d 100644 --- a/config/setup/crd.yaml +++ b/config/setup/crd.yaml @@ -1,3 +1,4 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: @@ -31,225 +32,113 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: DeviceProfile represents the attributes and operational capabilities of a device. It is a template for which there can be multiple matching devices within a given system. NOTE This struct is derived from edgex/go-mod-core-contracts/models/deviceprofile.go + description: DeviceProfile represents the attributes and operational capabilities + of a device. It is a template for which there can be multiple matching devices + within a given system. NOTE This struct is derived from edgex/go-mod-core-contracts/models/deviceprofile.go properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: DeviceProfileSpec defines the desired state of DeviceProfile properties: - coreCommands: - items: - properties: - get: - description: Get Command - properties: - path: - description: Path used by service for action on a device or sensor - type: string - responses: - description: Responses from get or put requests to service - items: - description: Response for a Get or Put request to a service - properties: - code: - type: string - description: - type: string - expectedValues: - items: - type: string - type: array - type: object - type: array - url: - description: Url for requests from command service - type: string - type: object - id: - description: EdgeId is a unique identifier used by EdgeX Foundry, such as a UUID - type: string - name: - description: Command name (unique on the profile) - type: string - put: - description: Put Command - properties: - parameterNames: - items: - type: string - type: array - path: - description: Path used by service for action on a device or sensor - type: string - responses: - description: Responses from get or put requests to service - items: - description: Response for a Get or Put request to a service - properties: - code: - type: string - description: - type: string - expectedValues: - items: - type: string - type: array - type: object - type: array - url: - description: Url for requests from command service - type: string - type: object - type: object - type: array description: type: string deviceCommands: - description: TODO support the following field items: properties: - get: - items: - properties: - deviceCommand: - description: The replacement of Resource field - type: string - deviceResource: - description: The replacement of Object field - type: string - index: - type: string - mappings: - additionalProperties: - type: string - type: object - object: - description: Deprecated - type: string - operation: - type: string - parameter: - type: string - resource: - description: Deprecated - type: string - secondary: - items: - type: string - type: array - type: object - type: array + isHidden: + type: boolean name: type: string - set: + readWrite: + type: string + resourceOperations: items: properties: - deviceCommand: - description: The replacement of Resource field + defaultValue: type: string deviceResource: - description: The replacement of Object field - type: string - index: type: string mappings: additionalProperties: type: string type: object - object: - description: Deprecated - type: string - operation: - type: string - parameter: - type: string - resource: - description: Deprecated - type: string - secondary: - items: - type: string - type: array + required: + - defaultValue type: object type: array + required: + - isHidden + - name + - readWrite + - resourceOperations type: object type: array deviceResources: items: properties: attributes: - additionalProperties: - type: string type: object + x-kubernetes-preserve-unknown-fields: true description: type: string + isHidden: + type: boolean name: type: string properties: properties: + assertion: + type: string + base: + type: string + defaultValue: + type: string + mask: + type: string + maximum: + type: string + mediaType: + type: string + minimum: + type: string + offset: + type: string + readWrite: + type: string + scale: + type: string + shift: + type: string units: - properties: - defaultValue: - type: string - readWrite: - type: string - type: - type: string - type: object - value: - properties: - assertion: - description: Required value of the property, set for checking error state. Failing an assertion condition wil l mark the device with an error state - type: string - base: - type: string - defaultValue: - type: string - floatEncoding: - type: string - mask: - type: string - maximum: - type: string - mediaType: - type: string - minimum: - type: string - offset: - type: string - precision: - type: string - readWrite: - type: string - scale: - type: string - shift: - type: string - size: - type: string - type: - type: string - type: object + type: string + valueType: + type: string required: - - value + - valueType type: object tag: type: string required: - description + - isHidden - name - properties type: object type: array labels: - description: Labels used to search for groups of profiles on EdgeX Foundry + description: Labels used to search for groups of profiles on EdgeX + Foundry items: type: string type: array @@ -260,7 +149,8 @@ spec: description: Model of the device type: string nodePool: - description: NodePool specifies which nodePool the deviceProfile belongs to + description: NodePool specifies which nodePool the deviceProfile belongs + to type: string type: object status: @@ -282,6 +172,7 @@ status: plural: "" conditions: [] storedVersions: [] + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -324,10 +215,14 @@ spec: description: Device is the Schema for the devices API properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object @@ -353,7 +248,9 @@ spec: - desiredValue - name type: object - description: TODO support the following field A list of auto-generated events coming from the device AutoEvents []AutoEvent `json:"autoEvents"` DeviceProperties represents the expected state of the device's properties + description: TODO support the following field A list of auto-generated + events coming from the device AutoEvents []AutoEvent `json:"autoEvents"` + DeviceProperties represents the expected state of the device's properties type: object labels: description: Other labels applied to the device to help with searching @@ -361,18 +258,23 @@ spec: type: string type: array location: - description: Device service specific location (interface{} is an empty interface so it can be anything) + description: 'Device service specific location (interface{} is an + empty interface so it can be anything) TODO: location type in edgex + is interface{}' type: string managed: - description: True means device is managed by cloud, cloud can update the related fields False means cloud can't update the fields + description: True means device is managed by cloud, cloud can update + the related fields False means cloud can't update the fields type: boolean nodePool: description: NodePool indicates which nodePool the device comes from type: string + notify: + type: boolean operatingState: description: Operating state (enabled/disabled) type: string - profile: + profileName: description: Associated Device Profile - Describes the device type: string protocols: @@ -382,12 +284,13 @@ spec: type: object description: A map of supported protocols for the given device type: object - service: + serviceName: description: Associated Device Service - One per device type: string required: - - profile - - service + - notify + - profileName + - serviceName type: object status: description: DeviceStatus defines the observed state of Device @@ -398,26 +301,41 @@ spec: conditions: description: current device state items: - description: Condition defines an observation of a Cluster API resource operational state. + description: Condition defines an observation of a Cluster API resource + operational state. properties: lastTransitionTime: - description: Last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. format: date-time type: string message: - description: A human readable message indicating details about the transition. This field may be empty. + description: A human readable message indicating details about + the transition. This field may be empty. type: string reason: - description: The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may not be empty. + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. type: string severity: - description: Severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. type: string required: - status @@ -442,18 +360,21 @@ spec: edgeId: type: string lastConnected: - description: Time (milliseconds) that the device last provided any feedback or responded to any request + description: Time (milliseconds) that the device last provided any + feedback or responded to any request format: int64 type: integer lastReported: - description: Time (milliseconds) that the device reported data to the core microservice + description: Time (milliseconds) that the device reported data to + the core microservice format: int64 type: integer operatingState: - description: Operating state (enabled/disabled) + description: Operating state (up/down/unknown) type: string synced: - description: Synced indicates whether the device already exists on both OpenYurt and edge platform + description: Synced indicates whether the device already exists on + both OpenYurt and edge platform type: boolean type: object type: object @@ -467,6 +388,7 @@ status: plural: "" conditions: [] storedVersions: [] + --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -509,73 +431,44 @@ spec: description: DeviceService is the Schema for the deviceservices API properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' type: string kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string metadata: type: object spec: description: DeviceServiceSpec defines the desired state of DeviceService properties: - addressable: - description: address (MQTT topic, HTTP address, serial bus, etc.) for reaching the service - properties: - address: - description: Address of the addressable - type: string - id: - description: ID is a unique identifier for the Addressable, such as a UUID - type: string - method: - description: Method for connecting (i.e. POST) - type: string - name: - description: Name is a unique name given to the Addressable - type: string - password: - description: Password of the user for authentication for the addressable - type: string - path: - description: Path for callbacks - type: string - port: - description: Port for the address - type: integer - protocol: - description: Protocol for the address (HTTP/TCP) - type: string - publisher: - description: For message bus protocols - type: string - topic: - description: Topic for message bus addressables - type: string - user: - description: User id for authentication - type: string - type: object adminState: description: Device Service Admin State type: string + baseAddress: + type: string description: description: Information describing the device type: string labels: - description: tags or other labels applied to the device service for search or other identification needs on the EdgeX Foundry + description: tags or other labels applied to the device service for + search or other identification needs on the EdgeX Foundry items: type: string type: array managed: - description: True means deviceService is managed by cloud, cloud can update the related fields False means cloud can't update the fields + description: True means deviceService is managed by cloud, cloud can + update the related fields False means cloud can't update the fields type: boolean nodePool: - description: NodePool indicates which nodePool the deviceService comes from - type: string - operatingState: - description: operational state - either enabled or disabled + description: NodePool indicates which nodePool the deviceService comes + from type: string + required: + - baseAddress type: object status: description: DeviceServiceStatus defines the observed state of DeviceService @@ -586,26 +479,41 @@ spec: conditions: description: current deviceService state items: - description: Condition defines an observation of a Cluster API resource operational state. + description: Condition defines an observation of a Cluster API resource + operational state. properties: lastTransitionTime: - description: Last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. format: date-time type: string message: - description: A human readable message indicating details about the transition. This field may be empty. + description: A human readable message indicating details about + the transition. This field may be empty. type: string reason: - description: The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may not be empty. + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. type: string severity: - description: Severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False. + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. type: string status: description: Status of the condition, one of True, False, Unknown. type: string type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. type: string required: - status @@ -616,100 +524,18 @@ spec: description: the Id assigned by the edge platform type: string lastConnected: - description: time in milliseconds that the device last reported data to the core + description: time in milliseconds that the device last reported data + to the core format: int64 type: integer lastReported: - description: time in milliseconds that the device last reported data to the core + description: time in milliseconds that the device last reported data + to the core format: int64 type: integer synced: - description: Synced indicates whether the device already exists on both OpenYurt and edge platform - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: valuedescriptors.device.openyurt.io -spec: - group: device.openyurt.io - names: - kind: ValueDescriptor - listKind: ValueDescriptorList - plural: valuedescriptors - singular: valuedescriptor - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: ValueDescriptor is the Schema for the valuedescriptors API NOTE Thie struct is derived from edgex/go-mod-core-contracts/models/value-descriptor.go - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ValueDescriptorSpec defines the desired state of ValueDescriptor - properties: - created: - format: int64 - type: integer - defaultValue: - type: string - description: - type: string - floatEncoding: - type: string - formatting: - type: string - id: - type: string - labels: - items: - type: string - type: array - max: - type: string - mediaType: - type: string - min: - type: string - modified: - format: int64 - type: integer - origin: - format: int64 - type: integer - type: - type: string - uomLabel: - type: string - type: object - status: - description: ValueDescriptorStatus defines the observed state of ValueDescriptor - properties: - addedToEdgeX: - description: AddedToEdgeX indicates whether the object has been successfully created on EdgeX Foundry + description: Synced indicates whether the device already exists on + both OpenYurt and edge platform type: boolean type: object type: object diff --git a/controllers/device_controller.go b/controllers/device_controller.go index bf4554e..b504850 100644 --- a/controllers/device_controller.go +++ b/controllers/device_controller.go @@ -216,8 +216,8 @@ func (r *DeviceReconciler) reconcileUpdateDevice(ctx context.Context, d *devicev // 2. reconciling the device properties' value klog.V(3).Infof("DeviceName: %s, reconciling the device properties", d.GetName()) - // property updates are made only when the device is operational and unlocked - if newDeviceStatus.OperatingState == devicev1alpha1.Enabled && newDeviceStatus.AdminState == devicev1alpha1.UnLocked { + // property updates are made only when the device is up and unlocked + if newDeviceStatus.OperatingState == devicev1alpha1.Up && newDeviceStatus.AdminState == devicev1alpha1.UnLocked { newDeviceStatus, failedPropertyNames = r.reconcileDeviceProperties(d, newDeviceStatus) } @@ -254,8 +254,12 @@ func (r *DeviceReconciler) reconcileDeviceProperties(d *devicev1alpha1.Device, d klog.V(4).Infof("DeviceName: %s, getting the actual value of property: %s", d.GetName(), propertyName) actualProperty, err := r.deviceCli.GetPropertyState(nil, propertyName, d, iotcli.GetOptions{}) if err != nil { - failedPropertyNames = append(failedPropertyNames, propertyName) - continue + if !iotcli.IsNotFoundErr(err) { + klog.Errorf("DeviceName: %s, failed to get actual property value of %s, err:%v", d.GetName(), propertyName, err) + failedPropertyNames = append(failedPropertyNames, propertyName) + continue + } + klog.Errorf("DeviceName: %s, property read command not found", d.GetName()) } klog.V(4).Infof("DeviceName: %s, got the actual property state, {Name: %s, GetURL: %s, ActualValue: %s}", d.GetName(), propertyName, actualProperty.GetURL, actualProperty.ActualValue) @@ -266,11 +270,11 @@ func (r *DeviceReconciler) reconcileDeviceProperties(d *devicev1alpha1.Device, d newDeviceStatus.DeviceProperties[propertyName] = *actualProperty // 1.2. set the device attribute in the edge platform to the expected value - if desiredProperty.DesiredValue != actualProperty.ActualValue { + if actualProperty == nil || desiredProperty.DesiredValue != actualProperty.ActualValue { klog.V(4).Infof("DeviceName: %s, the desired value and the actual value are different, desired: %s, actual: %s", d.GetName(), desiredProperty.DesiredValue, actualProperty.ActualValue) if err := r.deviceCli.UpdatePropertyState(nil, propertyName, d, iotcli.UpdateOptions{}); err != nil { - klog.V(4).ErrorS(err, "failed to update property", "DeviceName", d.GetName(), "propertyName", propertyName) + klog.ErrorS(err, "failed to update property", "DeviceName", d.GetName(), "propertyName", propertyName) failedPropertyNames = append(failedPropertyNames, propertyName) continue } diff --git a/controllers/deviceservice_controller.go b/controllers/deviceservice_controller.go index e81250b..7901d99 100644 --- a/controllers/deviceservice_controller.go +++ b/controllers/deviceservice_controller.go @@ -168,6 +168,19 @@ func (r *DeviceServiceReconciler) reconcileCreateDeviceService(ctx context.Conte if !clis.IsNotFoundErr(err) { klog.V(4).ErrorS(err, "fail to visit the edge platform") return nil + } else { + createdDs, err := r.deviceServiceCli.Create(nil, ds, edgeInterface.CreateOptions{}) + if err != nil { + klog.V(4).ErrorS(err, "failed to create deviceService on edge platform") + conditions.MarkFalse(ds, devicev1alpha1.DeviceServiceSyncedCondition, "failed to add DeviceService to EdgeX", clusterv1.ConditionSeverityWarning, err.Error()) + return fmt.Errorf("fail to add DeviceService to edge platform: %v", err) + } + + klog.V(4).InfoS("Successfully add DeviceService to Edge Platform, Name: %s, EdgeId: %s", ds.GetName(), createdDs.Status.EdgeId) + ds.Status.EdgeId = createdDs.Status.EdgeId + ds.Status.Synced = true + conditions.MarkTrue(ds, devicev1alpha1.DeviceServiceSyncedCondition) + return r.Status().Update(ctx, ds) } } else { // a. If object exists, the status of the device on OpenYurt is updated @@ -176,50 +189,12 @@ func (r *DeviceServiceReconciler) reconcileCreateDeviceService(ctx context.Conte ds.Status.EdgeId = edgeDs.Status.EdgeId return r.Status().Update(ctx, ds) } - - // b. If object does not exist, a request is sent to the edge platform to create a new deviceService and related addressable - addressable := ds.Spec.Addressable - as, err := r.deviceServiceCli.GetAddressable(nil, addressable.Name, edgeInterface.GetOptions{}) - if err == nil { - klog.V(4).Infof("AddressableName: %s, obj already exists on edge platform", addressable.Name) - ds.Spec.Addressable = *as - } else if clis.IsNotFoundErr(err) { - createdAddr, err := r.deviceServiceCli.CreateAddressable(nil, &addressable, edgeInterface.CreateOptions{}) - if err != nil { - conditions.MarkFalse(ds, devicev1alpha1.DeviceServiceSyncedCondition, "failed to add addressable to EdgeX", clusterv1.ConditionSeverityWarning, err.Error()) - return fmt.Errorf("failed to add addressable to edge platform: %v", err) - } - klog.V(4).Infof("Successfully add the Addressable to edge platform, Name: %s, EdgeId: %s", addressable.Name, createdAddr.Id) - ds.Spec.Addressable.Id = createdAddr.Id - } else { - klog.V(4).ErrorS(err, "fail to visit the edge platform core-metatdata-service") - conditions.MarkFalse(ds, devicev1alpha1.DeviceServiceSyncedCondition, "failed to visit the EdgeX core-metadata-service", clusterv1.ConditionSeverityWarning, err.Error()) - return err - } - if err = r.Update(ctx, ds); err != nil { - return err - } - - createdDs, err := r.deviceServiceCli.Create(nil, ds, edgeInterface.CreateOptions{}) - if err != nil { - klog.V(4).ErrorS(err, "failed to create deviceService on edge platform") - conditions.MarkFalse(ds, devicev1alpha1.DeviceServiceSyncedCondition, "failed to add DeviceService to EdgeX", clusterv1.ConditionSeverityWarning, err.Error()) - return fmt.Errorf("fail to add DeviceService to edge platform: %v", err) - } - - klog.V(4).InfoS("Successfully add DeviceService to Edge Platform, Name: %s, EdgeId: %s", ds.GetName(), createdDs.Status.EdgeId) - ds.Status.EdgeId = createdDs.Status.EdgeId - ds.Status.Synced = true - conditions.MarkTrue(ds, devicev1alpha1.DeviceServiceSyncedCondition) - return r.Status().Update(ctx, ds) } func (r *DeviceServiceReconciler) reconcileUpdateDeviceService(ctx context.Context, ds *devicev1alpha1.DeviceService) error { // 1. reconciling the AdminState field of deviceService newDeviceServiceStatus := ds.Status.DeepCopy() updateDeviceService := ds.DeepCopy() - // do not update deviceService's OperatingState - updateDeviceService.Spec.OperatingState = "" if ds.Spec.AdminState != "" && ds.Spec.AdminState != ds.Status.AdminState { newDeviceServiceStatus.AdminState = ds.Spec.AdminState diff --git a/controllers/deviceservice_syncer.go b/controllers/deviceservice_syncer.go index 49eaae0..49949dc 100644 --- a/controllers/deviceservice_syncer.go +++ b/controllers/deviceservice_syncer.go @@ -222,7 +222,7 @@ func (ds *DeviceServiceSyncer) completeCreateContent(edgeDS *devicev1alpha1.Devi createDevice := edgeDS.DeepCopy() createDevice.Spec.NodePool = ds.NodePool createDevice.Namespace = ds.Namespace - createDevice.Name = strings.Join([]string{ds.NodePool, createDevice.Name}, "-") + createDevice.Name = strings.Join([]string{ds.NodePool, edgeDS.Name}, "-") createDevice.Spec.Managed = false return createDevice } diff --git a/controllers/valuedescriptor_controller.go b/controllers/valuedescriptor_controller.go deleted file mode 100644 index bdbe9b7..0000000 --- a/controllers/valuedescriptor_controller.go +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2021 The OpenYurt Authors. - -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 - - http://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. -*/ - -package controllers - -import ( - "context" - "fmt" - - "github.com/edgexfoundry/go-mod-core-contracts/models" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog/v2" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - - devicev1alpha1 "github.com/openyurtio/device-controller/api/v1alpha1" - clis "github.com/openyurtio/device-controller/clients" - edgexCli "github.com/openyurtio/device-controller/clients/edgex-foundry" - "github.com/openyurtio/device-controller/cmd/yurt-device-controller/options" -) - -// ValueDescriptorReconciler reconciles a ValueDescriptor object -type ValueDescriptorReconciler struct { - client.Client - Scheme *runtime.Scheme - *edgexCli.EdgexValueDescriptorClient -} - -//+kubebuilder:rbac:groups=device.openyurt.io,resources=valuedescriptors,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=device.openyurt.io,resources=valuedescriptors/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=device.openyurt.io,resources=valuedescriptors/finalizers,verbs=update - -func (r *ValueDescriptorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - var vd devicev1alpha1.ValueDescriptor - if err := r.Get(ctx, req.NamespacedName, &vd); err != nil { - return ctrl.Result{}, err - } - // 1. check if the Edgex code-data has the corresponding ValueDescriptor - // NOTE this version does not support valuedescriptor update - _, err := r.GetValueDescriptorByName(vd.GetName()) - if err == nil { - klog.V(2).Info("ValueDescriptor already exists on edge platform") - return ctrl.Result{}, nil - } - if !clis.IsNotFoundErr(err) { - klog.V(2).Info("Fail to visit the edge platform's core-data-service") - return ctrl.Result{}, nil - } - - // 2. create one if the ValueDescriptor doesnot exist - edgexId, err := r.AddValueDescript(toEdgexValue(vd)) - if err != nil { - return ctrl.Result{}, fmt.Errorf("Fail to add ValueDescriptor to Edgex: %v", err) - } - klog.V(4).InfoS("Successfully add ValueDescriptor to edge platform", - "ValueDescriptor", vd.GetName(), "EdgexId", edgexId) - vd.Spec.Id = edgexId - vd.Status.AddedToEdgeX = true - - return ctrl.Result{}, r.Update(ctx, &vd) -} - -// SetupWithManager sets up the controller with the Manager. -func (r *ValueDescriptorReconciler) SetupWithManager(mgr ctrl.Manager, opts *options.YurtDeviceControllerOptions) error { - r.EdgexValueDescriptorClient = edgexCli.NewValueDescriptorClient(opts.CoreDataAddr) - return ctrl.NewControllerManagedBy(mgr). - For(&devicev1alpha1.ValueDescriptor{}). - WithEventFilter(genFirstUpdateFilter("valuedescriptor")). - Complete(r) -} - -func toEdgexValue(vd devicev1alpha1.ValueDescriptor) models.ValueDescriptor { - return models.ValueDescriptor{ - Id: vd.Spec.Id, - Created: vd.Spec.Created, - Description: vd.Spec.Description, - Modified: vd.Spec.Modified, - Origin: vd.Spec.Origin, - Name: vd.GetName(), - Min: vd.Spec.Min, - Max: vd.Spec.Max, - DefaultValue: vd.Spec.DefaultValue, - Type: vd.Spec.Type, - UomLabel: vd.Spec.UomLabel, - Formatting: vd.Spec.Formatting, - Labels: vd.Spec.Labels, - MediaType: vd.Spec.MediaType, - FloatEncoding: vd.Spec.FloatEncoding, - } -} diff --git a/go.mod b/go.mod index a552506..231a980 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/openyurtio/device-controller go 1.15 require ( - github.com/edgexfoundry/go-mod-core-contracts v0.1.111 + github.com/edgexfoundry/go-mod-core-contracts/v2 v2.1.0 github.com/go-resty/resty/v2 v2.4.0 github.com/onsi/ginkgo v1.16.4 github.com/onsi/gomega v1.14.0 diff --git a/go.sum b/go.sum index 12affb5..c7f09ea 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,7 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -63,6 +64,10 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -75,8 +80,13 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.5.0/go.mod h1:acH3+MQoiMzozT/ivU+DbRg7Ooo2298RdRaWcOv+4vM= +github.com/aws/smithy-go v1.5.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -88,6 +98,8 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/casbin/casbin/v2 v2.31.6/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -97,12 +109,14 @@ github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.12/go.mod h1:NJOI8ceUF/NTgEwtjD+TUq3/BnH/GF7WAM3RzCa3hBo= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -133,8 +147,12 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/drone/envsubst/v2 v2.0.0-20210615175204-7bf45dbf5372/go.mod h1:esf2rsHFNlZlxsqsZDojNBcnNs5REqIvRrWRHqX0vEU= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/edgexfoundry/go-mod-core-contracts v0.1.111 h1:dNez3rZIiUpTGXzRz+su9bEhQMWkgrMQc28EIiyFrhI= -github.com/edgexfoundry/go-mod-core-contracts v0.1.111/go.mod h1:84hDSh/zad/Tc56pSMW0yVLRS7BjAOxFCjW/2VJ9bio= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edgexfoundry/go-mod-core-contracts/v2 v2.1.0 h1:uphot3ZKOH0/aoo/Y5gr2NCRgGzy9RksWsXKtJRVEuQ= +github.com/edgexfoundry/go-mod-core-contracts/v2 v2.1.0/go.mod h1:I6UhBPCREubcU0ouIGBdZlNG5Xx4NijUVN5rvEtD03k= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -154,17 +172,20 @@ github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= -github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.3.0 h1:aM45YGMctNakddNNAezPxDUpv38j44Abh+hifNuqXik= +github.com/fxamacker/cbor/v2 v2.3.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -174,6 +195,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.11.0/go.mod h1:73/6Ixaufkvb5Osvkls8C79vuQ49Ba1rUEUYNSf+FUw= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -225,14 +247,19 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= +github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-resty/resty/v2 v2.4.0 h1:s6TItTLejEI+2mn98oijC5w/Rk2YU+OA6x0mnZN6r6k= github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/gobuffalo/flect v0.2.3 h1:f/ZukRnSNA/DUpSNDadko7Qc0PhGvsew35p/2tu+CRY= github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= @@ -275,6 +302,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -315,14 +343,17 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -335,13 +366,18 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.8.1/go.mod h1:sDjTOq0yUyv5G4h+BqSea7Fn6BU+XbolEz1952UB+mk= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.7.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -354,9 +390,13 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -364,7 +404,10 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -380,18 +423,23 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -404,9 +452,14 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -415,7 +468,10 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -439,7 +495,13 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= +github.com/nats-io/jwt/v2 v2.0.2/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= +github.com/nats-io/nats-server/v2 v2.2.6/go.mod h1:sEnFaxqe09cDmfMgACxZbziXnhQFhwk+aKkZjBBRYrI= +github.com/nats-io/nats.go v1.11.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= +github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -449,30 +511,40 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -499,10 +571,14 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -514,9 +590,11 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -539,6 +617,9 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -608,11 +689,15 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -674,6 +759,7 @@ golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -733,7 +819,9 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -746,9 +834,12 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -757,6 +848,7 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -789,8 +881,10 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -808,6 +902,7 @@ golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -830,6 +925,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -984,17 +1080,20 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1004,6 +1103,7 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=