Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
refactor: change dummy device to dummy special device
Browse files Browse the repository at this point in the history
- change DummyDevice to DummySpecialDevice
- modify related document
  • Loading branch information
Frank Mai authored and guangbochen committed May 27, 2020
1 parent fd24433 commit 9f4c704
Show file tree
Hide file tree
Showing 26 changed files with 583 additions and 530 deletions.
157 changes: 89 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Octopus is an edge device management system based on Kubernetes, it is very ligh

<!-- /toc -->


## Idea

Like the real octopus, Octopus consists of `brain` and `limb`s. The `brain` only needs to deploy one or choose the leader, it is responsible for processing some relatively centralized information, such as judging whether the node exists, whether the device model(type) exists, etc. The `limb`s need to deploy on edge nodes that the device can connect to, they talk to devices in the real world through `adaptors`. Therefore, Octopus manages devices by managing the device connections(`DeviceLink`).
Expand Down Expand Up @@ -105,135 +104,153 @@ After installed, we can verify the status of Octopus as below:
```shell script
$ kubectl get all -n octopus-system
NAME READY STATUS RESTARTS AGE
pod/octopus-limb-d4nbz 1/1 Running 0 40s
pod/octopus-limb-5g9q8 1/1 Running 0 40s
pod/octopus-limb-zsx7c 1/1 Running 0 40s
pod/octopus-brain-7767fcc4cf-g8str 1/1 Running 0 40s
pod/octopus-limb-mcv5v 1/1 Running 0 40s
pod/octopus-limb-w8vcf 1/1 Running 0 14s
pod/octopus-limb-862kh 1/1 Running 0 14s
pod/octopus-limb-797d8 1/1 Running 0 14s
pod/octopus-limb-8w462 1/1 Running 0 14s
pod/octopus-brain-65fdb4ff99-zvw62 1/1 Running 0 14s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/octopus-brain ClusterIP 10.43.150.114 <none> 8080/TCP 40s
service/octopus-limb ClusterIP 10.43.64.223 <none> 8080/TCP 40s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/octopus-brain ClusterIP 10.43.92.81 <none> 8080/TCP 14s
service/octopus-limb ClusterIP 10.43.143.49 <none> 8080/TCP 14s

NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/octopus-limb 4 4 4 4 4 <none> 40s
daemonset.apps/octopus-limb 4 4 4 4 4 <none> 14s

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/octopus-brain 1/1 1 1 40s
deployment.apps/octopus-brain 1/1 1 1 14s

NAME DESIRED CURRENT READY AGE
replicaset.apps/octopus-brain-7767fcc4cf 1 1 1 40s
replicaset.apps/octopus-brain-65fdb4ff99 1 1 1 14s

```

### Deploy Device Model & Device Adaptor

Octopus has prepared a dummy adaptor for testing, which does not need to be connected to a real device. So we can imagine that the dummy device is a realistic device in here.

At first, we need to describe the device as a resource in Kubernetes. This description process is modeling the device. In Kubernetes, the best way to describe resources is to use [CustomResourceDefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions), so **defining a device model in Octopus is actually defining the CustomResourceDefinitions.** Take a quick look at this `DummyDevice` model:
At first, we need to describe the device as a resource in Kubernetes. This description process is modeling the device. In Kubernetes, the best way to describe resources is to use [CustomResourceDefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions), so **defining a device model in Octopus is actually defining the CustomResourceDefinitions.** Take a quick look at this `DummySpecialDevice` model(pretend it is a smart fan):

```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
...
name: dummydevices.devices.edge.cattle.io
annotations:
controller-gen.kubebuilder.io/version: v0.2.5
devices.edge.cattle.io/description: dummy device description
devices.edge.cattle.io/device-property: ""
devices.edge.cattle.io/enable: "true"
devices.edge.cattle.io/icon: ""
labels:
app.kubernetes.io/name: octopus-adaptor-dummy
app.kubernetes.io/version: master
name: dummyspecialdevices.devices.edge.cattle.io
spec:
group: devices.edge.cattle.io
names:
kind: DummyDevice
listKind: DummyDeviceList
plural: dummydevices
singular: dummydevice
kind: DummySpecialDevice
listKind: DummySpecialDeviceList
plural: dummyspecialdevices
singular: dummyspecialdevice
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: DummyDevice is the Schema for the dummy device API
description: DummySpecialDevice is the Schema for the dummy special device
API.
properties:
...
spec:
description: DummyDeviceSpec defines the desired state of DummyDevice
description: DummySpecialDeviceSpec defines the desired state of DummySpecialDevice.
properties:
gear:
description: Specifies how fast the device should be
description: Specifies how fast the dummy special device should be.
enum:
- slow
- middle
- fast
type: string
"on":
description: Turn on the device
description: Turn on the dummy special device.
type: boolean
protocol:
description: Protocol for accessing the dummy special device.
properties:
location:
type: string
required:
- location
type: object
required:
- "on"
- protocol
type: object
status:
description: DummyDeviceStatus defines the observed state of DummyDevice
description: DummySpecialDeviceStatus defines the observed state of DummySpecialDevice.
properties:
gear:
description: Reports the current gear
description: Reports the current gear of dummy special device.
enum:
- slow
- middle
- fast
type: string
rotatingSpeed:
description: Reports the detail number of speed
description: Reports the detail number of speed of dummy special device.
format: int32
type: integer
type: object
type: object
...
status:
...
...

```
The dummy adaptor installer YAML file is under the [`adaptors/dummy/deploy/e2e`](./adaptors/dummy/deploy/e2e) directory, the `all_in_one.yaml` includes the device model and the device adaptor, we can apply them into the cluster directly:

```shell script
$ kubectl apply -f https://raw.githubusercontent.com/cnrancher/octopus/master/adaptors/dummy/deploy/e2e/all_in_one.yaml
customresourcedefinition.apiextensions.k8s.io/dummydevices.devices.edge.cattle.io created
customresourcedefinition.apiextensions.k8s.io/dummyspecialdevices.devices.edge.cattle.io created
clusterrole.rbac.authorization.k8s.io/octopus-adaptor-dummy-manager-role created
clusterrolebinding.rbac.authorization.k8s.io/octopus-adaptor-dummy-manager-rolebinding created
daemonset.apps/octopus-adaptor-dummy-adaptor created
$ kubectl get all -n octopus-system
NAME READY STATUS RESTARTS AGE
pod/octopus-limb-d4nbz 1/1 Running 0 4m56s
pod/octopus-limb-5g9q8 1/1 Running 0 4m56s
pod/octopus-limb-zsx7c 1/1 Running 0 4m56s
pod/octopus-brain-7767fcc4cf-g8str 1/1 Running 0 4m56s
pod/octopus-limb-mcv5v 1/1 Running 0 4m56s
pod/octopus-adaptor-dummy-adaptor-vgpgf 1/1 Running 0 24s
pod/octopus-adaptor-dummy-adaptor-kg5rw 1/1 Running 0 25s
pod/octopus-adaptor-dummy-adaptor-2m4xf 1/1 Running 0 26s
pod/octopus-adaptor-dummy-adaptor-tn5kz 1/1 Running 0 24s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/octopus-brain ClusterIP 10.43.150.114 <none> 8080/TCP 4m56s
service/octopus-limb ClusterIP 10.43.64.223 <none> 8080/TCP 4m56s
pod/octopus-limb-w8vcf 1/1 Running 0 2m27s
pod/octopus-limb-862kh 1/1 Running 0 2m27s
pod/octopus-limb-797d8 1/1 Running 0 2m27s
pod/octopus-limb-8w462 1/1 Running 0 2m27s
pod/octopus-brain-65fdb4ff99-zvw62 1/1 Running 0 2m27s
pod/octopus-adaptor-dummy-adaptor-6xcdz 1/1 Running 0 21s
pod/octopus-adaptor-dummy-adaptor-mmk5l 1/1 Running 0 21s
pod/octopus-adaptor-dummy-adaptor-xnjrf 1/1 Running 0 21s
pod/octopus-adaptor-dummy-adaptor-srsjz 1/1 Running 0 21s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/octopus-brain ClusterIP 10.43.92.81 <none> 8080/TCP 2m27s
service/octopus-limb ClusterIP 10.43.143.49 <none> 8080/TCP 2m27s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/octopus-limb 4 4 4 4 4 <none> 4m56s
daemonset.apps/octopus-adaptor-dummy-adaptor 4 4 4 4 4 <none> 3m19s
daemonset.apps/octopus-limb 4 4 4 4 4 <none> 2m27s
daemonset.apps/octopus-adaptor-dummy-adaptor 4 4 4 4 4 <none> 21s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/octopus-brain 1/1 1 1 4m56s
deployment.apps/octopus-brain 1/1 1 1 2m27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/octopus-brain-7767fcc4cf 1 1 1 4m56s
replicaset.apps/octopus-brain-65fdb4ff99 1 1 1 2m27s
```

It is worth noting that we have granted the permission to Octopus for managing `DummyDevice`:
It is worth noting that we have granted the permission to Octopus for managing `DummySpecialDevice`:

```shell script
$ kubectl get clusterrolebinding | grep octopus
octopus-manager-rolebinding 6m42s
octopus-adaptor-dummy-manager-rolebinding 5m5s
octopus-manager-rolebinding 2m49s
octopus-adaptor-dummy-manager-rolebinding 43s
```

Expand All @@ -245,28 +262,28 @@ Next, we are going to connect a device via `DeviceLink`. A link consists of 3 pa
- `Model` describes the model of device, it is the [TypeMeta](https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/v1/types.go) of the device model CRD.
- `Device spec` describes the desired status of device, it is determined by the device model CRD.

We can imagine that there is a device named `example` on the `edge-worker` node, we can try to connect it in.
We can imagine that there is a device named `living-room-fan` on the `edge-worker` node, we can try to connect it in.

```yaml
apiVersion: edge.cattle.io/v1alpha1
kind: DeviceLink
metadata:
name: example
namespace: octopus-test
name: living-room-fan
namespace: default
spec:
adaptor:
node: edge-worker
name: adaptors.edge.cattle.io/dummy
parameters:
ip: 192.168.2.47
model:
apiVersion: "devices.edge.cattle.io/v1alpha1"
kind: "DummyDevice"
kind: "DummySpecialDevice"
template:
metadata:
labels:
device: example
device: living-room-fan
spec:
protocol:
location: "living_room"
gear: slow
"on": true
Expand All @@ -275,15 +292,15 @@ spec:
There are [several states](./docs/octopus/state_of_devicelink.md) of a link, if we found the **DeviceConnected** `PHASE` is on **Healthy** `STATUS`, we can query the same name instance of device model CRD, now the device is in our cluster:

```shell script
$ kubectl get devicelink example -n octopus-test
NAME KIND NODE ADAPTOR PHASE STATUS AGE
example DummyDevice edge-worker adaptors.edge.cattle.io/dummy DeviceConnected Healthy 17s
$ kubectl get devicelink living-room-fan -n default
NAME KIND NODE ADAPTOR PHASE STATUS AGE
living-room-fan DummySpecialDevice edge-worker adaptors.edge.cattle.io/dummy DeviceConnected Healthy 10s
$ kubectl get dummydevice example -n octopus-test -w
NAME GEAR SPEED AGE
example slow 11 20s
example slow 12 22s
example slow 13 25s
$ kubectl get dummyspecialdevice living-room-fan -n default -w
NAME GEAR SPEED AGE
living-room-fan slow 10 32s
living-room-fan slow 11 33s
living-room-fan slow 12 36s
```

Expand All @@ -292,12 +309,16 @@ example slow 13 25s
When we want to stop the device, we can do this as below:

```shell script
$ kubectl patch devicelink example -n octoupus-test --type merge --patch '{"spec":{"template":{"spec":{"on":false}}}}'
devicelink.edge.cattle.io/example patched
$ kubectl patch devicelink living-room-fan -n default --type merge --patch '{"spec":{"template":{"spec":{"on":false}}}}'
devicelink.edge.cattle.io/living-room-fan patched
$ kubectl get devicelink living-room-fan -n default
NAME KIND NODE ADAPTOR PHASE STATUS AGE
living-room-fan DummySpecialDevice edge-worker adaptors.edge.cattle.io/dummy DeviceConnected Healthy 89s
$ kubectl get devicelink example -n octopus-test
NAME GEAR SPEED AGE
example 1m12s
$ kubectl get dummyspecialdevice living-room-fan -n default
NAME GEAR SPEED AGE
living-room-fan 117s
```

Expand Down
68 changes: 62 additions & 6 deletions adaptors/dummy/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Dummy Adaptor

This is for experience or testing
This is for experience or testing.

<!-- toc -->

- [Registration Information](#registration-information)
- [Support Model](#support-model)
+ [DummySpecialDevice](#dummyspecialdevice)
+ [DummySpecialDeviceSpec](#dummyspecialdevicespec)
+ [DummySpecialDeviceStatus](#dummyspecialdevicestatus)
+ [DummySpecialDeviceProtocol](#dummyspecialdeviceprotocol)
+ [DummySpecialDeviceGear](#dummyspecialdevicegear)
- [Support Platform](#support-platform)
- [Usage](#Usage)
- [Authority](#authority)

<!-- /toc -->

## Registration Information

Expand All @@ -12,7 +27,48 @@ This is for experience or testing

| Kind | Group | Version | Available |
|:---:|:---:|:---:|:---:|
| `DummyDevice` | `devices.edge.cattle.io` | `v1alpha1` | * |
| [`DummySpecialDevice`](#dummyspecialdevice) | `devices.edge.cattle.io` | `v1alpha1` | * |

### DummySpecialDevice

The `DummySpecialDevice` can be considered as a fake fan.

| Field | Description | Schema | Required |
|:---|:---|:---|:---:|
| metadata | | [metav1.ObjectMeta](https://github.com/kubernetes/apimachinery/blob/master/pkg/apis/meta/v1/types.go#L110) | false |
| spec | Defines the desired state of DummySpecialDevice. | [DummySpecialDeviceSpec](#dummyspecialdevicespec) | true |
| status | Defines the observed state of DummySpecialDevice. | [DummySpecialDeviceStatus](#dummyspecialdevicestatus) | false |

#### DummySpecialDeviceSpec

| Field | Description | Schema | Required |
|:---|:---|:---|:---:|
| protocol | Protocol for accessing the dummy special device. | [DummySpecialDeviceProtocol](#dummyspecialdeviceprotocol) | true |
| on | Turn on the dummy special device | bool | true |
| gear | Specifies how fast the dummy special device should be. | [DummySpecialDeviceGear](#dummyspecialdevicegear) | false |

#### DummySpecialDeviceStatus

| Field | Description | Schema | Required |
|:---|:---|:---|:---:|
| gear | Reports the current gear of dummy special device. | [DummySpecialDeviceGear](#dummyspecialdevicegear) | false |
| rotatingSpeed | Reports the detail number of speed of dummy special device. | int32 | false |

#### DummySpecialDeviceProtocol

| Field | Description | Schema | Required |
|:---|:---|:---|:---:|
| location | Specifies where to locate the dummy special device. | string | true |

#### DummySpecialDeviceGear

DummySpecialDeviceGear defines how fast the dummy special device should be.

| Field | Description | Schema | Required |
|:---|:---|:---|:---:|
| slow | Starts from 0 and increases every three seconds until 100. | string | false |
| middle | Starts from 100 and increases every two seconds until 200. | string | false |
| fast | Starts from 200 and increases every one second until 300. | string | false |

## Support Platform

Expand All @@ -33,10 +89,10 @@ kubectl apply -f ./deploy/e2e/all_in_one.yaml
Grant permissions to Octopus as below:

```text
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
dummydevices.devices.edge.cattle.io [] [] [create delete get list patch update watch]
dummydevices.devices.edge.cattle.io/status [] [] [get patch update]
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
dummyspecialdevices.devices.edge.cattle.io [] [] [create delete get list patch update watch]
dummyspecialdevices.devices.edge.cattle.io/status [] [] [get patch update]
```

Permissions obtained from cluster as below:
Expand Down
Loading

0 comments on commit 9f4c704

Please sign in to comment.