...
 
Commits (4)
此差异已折叠。
此差异已折叠。
......@@ -36,23 +36,16 @@ func commandByDeviceID(deviceID string, commandID string, body string, isPutComm
if device.AdminState == contract.Locked {
LoggingClient.Error(device.Name + " is in admin locked state")
return "", http.StatusLocked
}
command, err := cc.Command(commandID, ctx)
if err != nil {
LoggingClient.Error(err.Error())
chk, ok := err.(*types.ErrServiceClient)
if ok {
return err.Error(), chk.StatusCode
} else {
return err.Error(), http.StatusInternalServerError
for _, c := range device.Profile.CoreCommands {
if c.Id == commandID {
return commandByDevice(device, c, body, isPutCommand, ctx)
}
}
return commandByDevice(device, command, body, isPutCommand, ctx)
// command with given commandID does not belong to the device
return err.Error(), http.StatusNotFound
}
func commandByNames(dn string, cn string, body string, isPutCommand bool, ctx context.Context) (string, int) {
......
......@@ -52,7 +52,6 @@ type DBClient interface {
GetDeviceProfilesByManufacturerModel(man string, mod string) ([]contract.DeviceProfile, error)
GetDeviceProfilesByManufacturer(man string) ([]contract.DeviceProfile, error)
GetDeviceProfileByName(n string) (contract.DeviceProfile, error)
GetDeviceProfilesByCommandId(id string) ([]contract.DeviceProfile, error)
// Addressable
UpdateAddressable(a contract.Addressable) error
......@@ -88,12 +87,9 @@ type DBClient interface {
DeleteProvisionWatcherById(id string) error
// Command
GetAllCommands() ([]contract.Command, error)
GetCommandById(id string) (contract.Command, error)
GetCommandByName(id string) ([]contract.Command, error)
AddCommand(c contract.Command) (string, error)
GetAllCommands() ([]contract.Command, error)
UpdateCommand(c contract.Command) error
DeleteCommandById(id string) error
// Scrub all metadata (only used in test)
ScrubMetadata() error
......
......@@ -683,29 +683,6 @@ func (_m *DBClient) GetDeviceProfileByName(n string) (models.DeviceProfile, erro
return r0, r1
}
// GetDeviceProfilesByCommandId provides a mock function with given fields: id
func (_m *DBClient) GetDeviceProfilesByCommandId(id string) ([]models.DeviceProfile, error) {
ret := _m.Called(id)
var r0 []models.DeviceProfile
if rf, ok := ret.Get(0).(func(string) []models.DeviceProfile); ok {
r0 = rf(id)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]models.DeviceProfile)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(id)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetDeviceProfilesByManufacturer provides a mock function with given fields: man
func (_m *DBClient) GetDeviceProfilesByManufacturer(man string) ([]models.DeviceProfile, error) {
ret := _m.Called(man)
......
......@@ -167,22 +167,7 @@ func updateDeviceProfileFields(from models.DeviceProfile, to *models.DeviceProfi
if err := checkDuplicateCommands(from, w); err != nil {
return err
}
// taking lazy approach to commands - remove them all and add them
// all back in. TODO - someday make this a two phase commit so
// commands don't get wiped out before profile
// Delete the old commands
if err := deleteCommands(*to, w); err != nil {
return err
}
to.CoreCommands = from.CoreCommands
// Add the new commands
if err := addCommands(to, w); err != nil {
return err
}
}
return nil
......@@ -227,33 +212,6 @@ func checkDuplicateCommands(dp models.DeviceProfile, w http.ResponseWriter) erro
return nil
}
// Delete all of the commands that are a part of the device profile
func deleteCommands(dp models.DeviceProfile, w http.ResponseWriter) error {
for _, command := range dp.CoreCommands {
err := dbClient.DeleteCommandById(command.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return err
}
}
return nil
}
// Add all of the commands that are a part of the device profile
func addCommands(dp *models.DeviceProfile, w http.ResponseWriter) error {
for i := range dp.CoreCommands {
if newId, err := dbClient.AddCommand(dp.CoreCommands[i]); err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return err
} else {
dp.CoreCommands[i].Id = newId
}
}
return nil
}
func restGetProfileByProfileId(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
var did string = vars["id"]
......@@ -362,12 +320,6 @@ func deleteDeviceProfile(dp models.DeviceProfile, w http.ResponseWriter) error {
http.Error(w, err.Error(), http.StatusConflict)
return err
}
for _, command := range dp.CoreCommands {
if err := dbClient.DeleteCommandById(command.Id); err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
return err
}
}
// Delete the profile
if err := dbClient.DeleteDeviceProfileById(dp.Id); err != nil {
http.Error(w, err.Error(), http.StatusServiceUnavailable)
......
......@@ -140,7 +140,7 @@ func (mc MongoClient) AddDevice(d contract.Device) (string, error) {
}
var mapped models.Device
id, err := mapped.FromContract(d, mc, mc, mc, mc)
id, err := mapped.FromContract(d, mc, mc, mc)
if err != nil {
return "", errors.New("FromContract failed")
}
......@@ -152,7 +152,7 @@ func (mc MongoClient) AddDevice(d contract.Device) (string, error) {
func (mc MongoClient) UpdateDevice(d contract.Device) error {
var mapped models.Device
id, err := mapped.FromContract(d, mc, mc, mc, mc)
id, err := mapped.FromContract(d, mc, mc, mc)
if err != nil {
return errors.New("FromContract failed")
}
......@@ -214,7 +214,7 @@ func (mc MongoClient) getDevices(q bson.M) ([]contract.Device, error) {
res := make([]contract.Device, 0)
for _, md := range mds {
d, err := md.ToContract(mc, mc, mc, mc)
d, err := md.ToContract(mc, mc, mc)
if err != nil {
return []contract.Device{}, err
}
......@@ -232,7 +232,7 @@ func (mc MongoClient) getDevice(q bson.M) (contract.Device, error) {
if err := s.DB(mc.database.Name).C(db.Device).Find(q).One(&d); err != nil {
return contract.Device{}, errorMap(err)
}
return d.ToContract(mc, mc, mc, mc)
return d.ToContract(mc, mc, mc)
}
/* -----------------------------Device Profile -----------------------------*/
......@@ -267,7 +267,7 @@ func (mc MongoClient) GetDeviceProfileById(id string) (contract.DeviceProfile, e
if err != nil {
return contract.DeviceProfile{}, err
}
return model.ToContract(mc)
return model.ToContract()
}
func (mc MongoClient) getDeviceProfileById(id string) (models.DeviceProfile, error) {
......@@ -303,7 +303,7 @@ func (mc MongoClient) GetDeviceProfileByName(n string) (contract.DeviceProfile,
if err != nil {
return contract.DeviceProfile{}, err
}
return model.ToContract(mc)
return model.ToContract()
}
// Get device profiles with the passed query
......@@ -319,7 +319,7 @@ func (mc MongoClient) getDeviceProfiles(q bson.M) ([]contract.DeviceProfile, err
cdps := make([]contract.DeviceProfile, 0)
for _, dp := range dps {
c, err := dp.ToContract(mc)
c, err := dp.ToContract()
if err != nil {
return []contract.DeviceProfile{}, err
}
......@@ -354,16 +354,9 @@ func (mc MongoClient) AddDeviceProfile(dp contract.DeviceProfile) (string, error
if count > 0 {
return "", db.ErrNotUnique
}
for i := 0; i < len(dp.CoreCommands); i++ {
if newId, err := mc.AddCommand(dp.CoreCommands[i]); err != nil {
return "", err
} else {
dp.CoreCommands[i].Id = newId
}
}
var mapped models.DeviceProfile
id, err := mapped.FromContract(dp, mc)
id, err := mapped.FromContract(dp)
if err != nil {
return "", err
}
......@@ -379,7 +372,7 @@ func (mc MongoClient) AddDeviceProfile(dp contract.DeviceProfile) (string, error
func (mc MongoClient) UpdateDeviceProfile(dp contract.DeviceProfile) error {
var mapped models.DeviceProfile
id, err := mapped.FromContract(dp, mc)
id, err := mapped.FromContract(dp)
if err != nil {
return err
}
......@@ -389,20 +382,6 @@ func (mc MongoClient) UpdateDeviceProfile(dp contract.DeviceProfile) error {
return mc.updateId(db.DeviceProfile, id, mapped)
}
// Get the device profiles that are currently using the command
func (mc MongoClient) GetDeviceProfilesByCommandId(id string) ([]contract.DeviceProfile, error) {
command, err := mc.getCommandById(id)
if err != nil {
return []contract.DeviceProfile{}, err
}
dps, err := mc.getDeviceProfiles(bson.M{"commands.$id": command.Id})
if err != nil {
return []contract.DeviceProfile{}, err
}
return dps, nil
}
func (mc MongoClient) DeleteDeviceProfileById(id string) error {
return mc.deleteById(db.DeviceProfile, id)
}
......@@ -766,7 +745,7 @@ func (mc MongoClient) GetProvisionWatcher(q bson.M) (pw contract.ProvisionWatche
return
}
pw, err = mpw.ToContract(mc, mc, mc, mc)
pw, err = mpw.ToContract(mc, mc, mc)
return
}
......@@ -787,7 +766,7 @@ func (mc MongoClient) getProvisionWatchers(q bson.M) (pws []contract.ProvisionWa
cpws := make([]contract.ProvisionWatcher, 0)
for _, mpw := range mpws {
cpw, err := mpw.ToContract(mc, mc, mc, mc)
cpw, err := mpw.ToContract(mc, mc, mc)
if err != nil {
return []contract.ProvisionWatcher{}, err
}
......@@ -852,7 +831,7 @@ func (mc MongoClient) AddProvisionWatcher(pw contract.ProvisionWatcher) (string,
pw.Profile = dp
var mapped models.ProvisionWatcher
id, err := mapped.FromContract(pw, mc, mc, mc, mc)
id, err := mapped.FromContract(pw, mc, mc, mc)
if err != nil {
return "", errors.New("ProvisionWatcher FromContract() failed")
}
......@@ -868,7 +847,7 @@ func (mc MongoClient) AddProvisionWatcher(pw contract.ProvisionWatcher) (string,
func (mc MongoClient) UpdateProvisionWatcher(pw contract.ProvisionWatcher) error {
var mapped models.ProvisionWatcher
id, err := mapped.FromContract(pw, mc, mc, mc, mc)
id, err := mapped.FromContract(pw, mc, mc, mc)
if err != nil {
return err
}
......@@ -884,38 +863,16 @@ func (mc MongoClient) DeleteProvisionWatcherById(id string) error {
// ------------------------Command -------------------------------------*/
func (mc MongoClient) DBRefToCommand(dbRef mgo.DBRef) (c models.Command, err error) {
s := mc.session.Copy()
defer s.Close()
if err = s.DB(mc.database.Name).C(db.Command).Find(bson.M{"_id": dbRef.Id}).One(&c); err != nil {
return models.Command{}, errorMap(err)
}
return
}
func (mc MongoClient) CommandToDBRef(c models.Command) (dbRef mgo.DBRef, err error) {
// validate command identity provided in contract actually exists and populate missing Id, Uuid field
var command models.Command
if c.Id.Valid() {
command, err = mc.getCommandById(c.Id.Hex())
} else {
command, err = mc.getCommandById(c.Uuid)
}
if err != nil {
return dbRef, err
}
dbRef = mgo.DBRef{Collection: db.Command, Id: command.Id}
return
}
func (mc MongoClient) GetAllCommands() ([]contract.Command, error) {
s := mc.session.Copy()
defer s.Close()
var commands []models.Command
err := s.DB(mc.database.Name).C(db.Command).Find(bson.M{}).Sort("queryts").All(&commands)
var dps []models.DeviceProfile
err := s.DB(mc.database.Name).C(db.DeviceProfile).Find(bson.M{}).Select(bson.M{"commands": 1}).Sort("queryts").All(&dps)
commands := make([]models.Command, 0)
for _, dp := range dps {
commands = append(commands, dp.CoreCommands...)
}
return mapCommands(commands, err)
}
......@@ -931,26 +888,30 @@ func (mc MongoClient) getCommandById(id string) (models.Command, error) {
s := mc.session.Copy()
defer s.Close()
query, err := idToBsonM(id)
if err != nil {
return models.Command{}, err
}
var command models.Command
if err = s.DB(mc.database.Name).C(db.Command).Find(query).One(&command); err != nil {
//query := bson.M{"commands.uuid": id}
var dp models.DeviceProfile
if err := s.DB(mc.database.Name).C(db.DeviceProfile).Find(bson.M{"commands": bson.M{"$elemMatch": bson.M{"uuid": id}}}).Select(bson.M{"commands.$": 1}).One(&dp); err != nil {
return models.Command{}, errorMap(err)
}
return command, nil
if len(dp.CoreCommands) > 1 {
return models.Command{}, fmt.Errorf("not unique result found for command with %v", id)
}
return dp.CoreCommands[0], nil
}
func (mc MongoClient) GetCommandByName(n string) ([]contract.Command, error) {
s := mc.session.Copy()
defer s.Close()
var commands []models.Command
err := s.DB(mc.database.Name).C(db.Command).Find(bson.M{"name": n}).All(&commands)
return mapCommands(commands, err)
var dps []models.DeviceProfile
if err := s.DB(mc.database.Name).C(db.DeviceProfile).Find(bson.M{"commands": bson.M{"$elemMatch": bson.M{"name": n}}}).Select(bson.M{"commands.$": 1}).All(&dps); err != nil {
return nil, errorMap(err)
}
commands := make([]models.Command, 0)
for _, dp := range dps {
commands = append(commands, dp.CoreCommands...)
}
return mapCommands(commands, nil)
}
func mapCommands(commands []models.Command, err error) ([]contract.Command, error) {
......@@ -966,78 +927,6 @@ func mapCommands(commands []models.Command, err error) ([]contract.Command, erro
return mapped, nil
}
func (mc MongoClient) AddCommand(c contract.Command) (string, error) {
s := mc.session.Copy()
defer s.Close()
var mapped models.Command
id, err := mapped.FromContract(c)
if err != nil {
return "", errors.New("FromContract failed")
}
mapped.TimestampForAdd()
return id, errorMap(s.DB(mc.database.Name).C(db.Command).Insert(mapped))
}
// Update command uses the ID of the command for identification
func (mc MongoClient) UpdateCommand(c contract.Command) error {
var mapped models.Command
id, err := mapped.FromContract(c)
if err != nil {
return errors.New("FromContract failed")
}
mapped.TimestampForUpdate()
return mc.updateId(db.Command, id, mapped)
}
// Delete the command by ID
// Check if the command is still in use by device profiles
func (mc MongoClient) DeleteCommandById(id string) error {
s := mc.session.Copy()
defer s.Close()
col := s.DB(mc.database.Name).C(db.Command)
// Check if the command is still in use
findParameters, err := idToBsonM(id)
if err != nil {
return err
}
query := bson.M{"commands": bson.M{"$elemMatch": findParameters}}
count, err := s.DB(mc.database.Name).C(db.DeviceProfile).Find(query).Count()
if err != nil {
return errorMap(err)
}
if count > 0 {
return db.ErrCommandStillInUse
}
// remove the command
n, v, err := idToQueryParameters(id)
if err != nil {
return err
}
return errorMap(col.Remove(bson.D{{Name: n, Value: v}}))
}
func (mc MongoClient) GetAndMapCommands(c []mgo.DBRef) ([]contract.Command, error) {
s := mc.session.Copy()
defer s.Close()
commands := make([]contract.Command, 0)
for _, cRef := range c {
command, err := mc.GetCommandById(fmt.Sprintf("%s", cRef.Id))
if err != nil {
return []contract.Command{}, err
}
commands = append(commands, command)
}
return commands, nil
}
// Scrub all metadata
func (mc MongoClient) ScrubMetadata() error {
s := mc.session.Copy()
......
......@@ -17,15 +17,8 @@ package models
import (
"github.com/edgexfoundry/edgex-go/internal/pkg/db"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
"github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
)
type commandTransform interface {
DBRefToCommand(dbRef mgo.DBRef) (c Command, err error)
CommandToDBRef(c Command) (dbRef mgo.DBRef, err error)
}
type Response struct {
Code string `bson:"code"`
Description string `bson:"description"`
......@@ -46,23 +39,18 @@ type Put struct {
}
type Command struct {
Created int64 `bson:"created"`
Modified int64 `bson:"modified"`
Origin int64 `bson:"origin"`
Id bson.ObjectId `bson:"_id,omitempty"`
Uuid string `bson:"uuid,omitempty"`
Name string `bson:"name"`
Get Get `bson:"get"`
Put Put `bson:"put"`
Created int64 `bson:"created"`
Modified int64 `bson:"modified"`
Origin int64 `bson:"origin"`
Uuid string `bson:"uuid,omitempty"`
Name string `bson:"name"`
Get Get `bson:"get"`
Put Put `bson:"put"`
}
func (c *Command) ToContract() (cmd contract.Command) {
// Always hand back the UUID as the contract command ID unless it's blank (an old command, for example blackbox test scripts)
id := c.Uuid
if id == "" {
id = c.Id.Hex()
}
cmd.Get = contract.Get{}
cmd.Get.Path = c.Get.Path
cmd.Get.URL = c.Get.URL
......@@ -98,11 +86,8 @@ func (c *Command) ToContract() (cmd contract.Command) {
}
func (c *Command) FromContract(from contract.Command) (contractId string, err error) {
c.Id, c.Uuid, err = fromContractId(from.Id)
if err != nil {
return
}
//temporary for backward compatibility commands have only "uuid"
_, c.Uuid, err = fromContractId(from.Id)
c.Created = from.Created
c.Modified = from.Modified
c.Origin = from.Origin
......@@ -132,8 +117,6 @@ func (c *Command) FromContract(from contract.Command) (contractId string, err er
}
c.Put.URL = from.Put.URL
c.Put.ParameterNames = from.Put.ParameterNames
contractId = toContractId(c.Id, c.Uuid)
return
}
......
......@@ -49,7 +49,7 @@ type Device struct {
ProfileName string `bson:"profileName"` // Associated Device Profile Name
}
func (d *Device) ToContract(dsTransform deviceServiceTransform, dpTransform deviceProfileTransform, cTransform commandTransform, aTransform addressableTransform) (c contract.Device, err error) {
func (d *Device) ToContract(dsTransform deviceServiceTransform, dpTransform deviceProfileTransform, aTransform addressableTransform) (c contract.Device, err error) {
// Always hand back the UUID as the contract command ID unless it's blank (an old command, for example blackbox test scripts)
id := d.Uuid
if id == "" {
......@@ -98,7 +98,7 @@ func (d *Device) ToContract(dsTransform deviceServiceTransform, dpTransform devi
if err != nil {
return
}
result.Profile, err = dpModel.ToContract(cTransform)
result.Profile, err = dpModel.ToContract()
if err != nil {
return
}
......@@ -107,7 +107,7 @@ func (d *Device) ToContract(dsTransform deviceServiceTransform, dpTransform devi
return
}
func (d *Device) FromContract(from contract.Device, dsTransform deviceServiceTransform, dpTransform deviceProfileTransform, cTransform commandTransform, aTransform addressableTransform) (id string, err error) {
func (d *Device) FromContract(from contract.Device, dsTransform deviceServiceTransform, dpTransform deviceProfileTransform, aTransform addressableTransform) (id string, err error) {
if d.Id, d.Uuid, err = fromContractId(from.Id); err != nil {
return
}
......@@ -145,13 +145,14 @@ func (d *Device) FromContract(from contract.Device, dsTransform deviceServiceTra
}
var dpModel DeviceProfile
if _, err = dpModel.FromContract(from.Profile, cTransform); err != nil {
if _, err = dpModel.FromContract(from.Profile); err != nil {
return
}
d.ProfileName = dpModel.Name
if d.Profile, err = dpTransform.DeviceProfileToDBRef(dpModel); err != nil {
return
}
id = toContractId(d.Id, d.Uuid)
return
}
......
......@@ -92,10 +92,10 @@ type DeviceProfile struct {
Labels []string `bson:"labels"`
DeviceResources []DeviceResource `bson:"deviceResources"`
DeviceCommands []ProfileResource `bson:"resources"`
CoreCommands []mgo.DBRef `bson:"commands"`
CoreCommands []Command `bson:"commands"`
}
func (dp *DeviceProfile) ToContract(transform commandTransform) (c contract.DeviceProfile, err error) {
func (dp *DeviceProfile) ToContract() (c contract.DeviceProfile, err error) {
id := dp.Uuid
if id == "" {
id = dp.Id.Hex()
......@@ -173,18 +173,13 @@ func (dp *DeviceProfile) ToContract(transform commandTransform) (c contract.Devi
c.DeviceCommands = append(c.DeviceCommands, cpr)
}
for _, dbRef := range dp.CoreCommands {
command, err := transform.DBRefToCommand(dbRef)
if err != nil {
return contract.DeviceProfile{}, err
}
c.CoreCommands = append(c.CoreCommands, command.ToContract())
for _, from := range dp.CoreCommands {
c.CoreCommands = append(c.CoreCommands, from.ToContract())
}
return
}
func (dp *DeviceProfile) FromContract(from contract.DeviceProfile, transform commandTransform) (contractId string, err error) {
func (dp *DeviceProfile) FromContract(from contract.DeviceProfile) (contractId string, err error) {
dp.Id, dp.Uuid, err = fromContractId(from.Id)
if err != nil {
return
......@@ -267,16 +262,8 @@ func (dp *DeviceProfile) FromContract(from contract.DeviceProfile, transform com
if _, err = commandModel.FromContract(command); err != nil {
return
}
var dbRef mgo.DBRef
dbRef, err = transform.CommandToDBRef(commandModel)
if err != nil {
return
}
dp.CoreCommands = append(dp.CoreCommands, dbRef)
dp.CoreCommands = append(dp.CoreCommands, commandModel)
}
contractId = toContractId(dp.Id, dp.Uuid)
return
}
......
......@@ -34,7 +34,7 @@ type ProvisionWatcher struct {
OperatingState contract.OperatingState `bson:"operatingState"` // operational state - either enabled or disabled
}
func (pw *ProvisionWatcher) ToContract(dpt deviceProfileTransform, dst deviceServiceTransform, ct commandTransform, at addressableTransform) (c contract.ProvisionWatcher, err error) {
func (pw *ProvisionWatcher) ToContract(dpt deviceProfileTransform, dst deviceServiceTransform, at addressableTransform) (c contract.ProvisionWatcher, err error) {
id := pw.Uuid
if id == "" {
id = pw.Id.Hex()
......@@ -51,7 +51,7 @@ func (pw *ProvisionWatcher) ToContract(dpt deviceProfileTransform, dst deviceSer
if err != nil {
return contract.ProvisionWatcher{}, err
}
c.Profile, err = profile.ToContract(ct)
c.Profile, err = profile.ToContract()
if err != nil {
return contract.ProvisionWatcher{}, err
}
......@@ -70,7 +70,7 @@ func (pw *ProvisionWatcher) ToContract(dpt deviceProfileTransform, dst deviceSer
return
}
func (pw *ProvisionWatcher) FromContract(from contract.ProvisionWatcher, dpt deviceProfileTransform, dst deviceServiceTransform, ct commandTransform, at addressableTransform) (id string, err error) {
func (pw *ProvisionWatcher) FromContract(from contract.ProvisionWatcher, dpt deviceProfileTransform, dst deviceServiceTransform, at addressableTransform) (id string, err error) {
pw.Id, pw.Uuid, err = fromContractId(from.Id)
if err != nil {
return
......@@ -83,7 +83,7 @@ func (pw *ProvisionWatcher) FromContract(from contract.ProvisionWatcher, dpt dev
pw.Identifiers = from.Identifiers
var profile DeviceProfile
if _, err = profile.FromContract(from.Profile, ct); err != nil {
if _, err = profile.FromContract(from.Profile); err != nil {
return
}
if pw.Profile, err = dpt.DeviceProfileToDBRef(profile); err != nil {
......
......@@ -15,10 +15,6 @@ package redis
import (
"fmt"
"github.com/edgexfoundry/edgex-go/internal/pkg/db"
"github.com/gomodule/redigo/redis"
contract "github.com/edgexfoundry/go-mod-core-contracts/models"
)
......@@ -31,6 +27,7 @@ type redisDeviceProfile struct {
Labels []string
DeviceResources []contract.DeviceResource
DeviceCommands []contract.ProfileResource
CoreCommands []contract.Command
}
func marshalDeviceProfile(dp contract.DeviceProfile) (out []byte, err error) {
......@@ -43,6 +40,7 @@ func marshalDeviceProfile(dp contract.DeviceProfile) (out []byte, err error) {
Labels: dp.Labels,
DeviceResources: dp.DeviceResources,
DeviceCommands: dp.DeviceCommands,
CoreCommands: dp.CoreCommands,
}
return marshalObject(s)
......@@ -66,26 +64,7 @@ func unmarshalDeviceProfile(o []byte, dp interface{}) (err error) {
x.Labels = s.Labels
x.DeviceResources = s.DeviceResources
x.DeviceCommands = s.DeviceCommands
conn, err := getConnection()
if err != nil {
return err
}
defer conn.Close()
objects, err := getObjectsByValue(conn, db.DeviceProfile+":commands:"+s.Id)
if err != nil {
if err != redis.ErrNil {
return err
}
}
x.CoreCommands = make([]contract.Command, len(objects))
for i, in := range objects {
err = unmarshalObject(in, &x.CoreCommands[i])
if err != nil {
return err
}
}
x.CoreCommands = s.CoreCommands
return nil
default:
return fmt.Errorf("Can only unmarshal into a *DeviceProfile, got %T", x)
......
......@@ -421,10 +421,6 @@ func (c *Client) GetDeviceProfileByName(n string) (contract.DeviceProfile, error
return dp, err
}
func (c *Client) GetDeviceProfilesByCommandId(id string) ([]contract.DeviceProfile, error) {
return c.getDeviceProfilesByValues(db.DeviceProfile + ":command:" + id)
}
// Get device profiles with the passed query
func (c *Client) getDeviceProfilesByValues(vals ...string) ([]contract.DeviceProfile, error) {
conn := c.Pool.Get()
......@@ -493,6 +489,21 @@ func addDeviceProfile(conn redis.Conn, dp contract.DeviceProfile) (string, error
}
dp.Modified = ts
var commands = []contract.Command{}
for _, from := range dp.CoreCommands {
_, err := uuid.Parse(from.Id)
if err != nil {
from.Id = uuid.New().String()
}
ts := db.MakeTimestamp()
if from.Created == 0 {
from.Created = ts
}
from.Modified = ts
commands = append(commands, from)
}
dp.CoreCommands = commands
m, err := marshalDeviceProfile(dp)
if err != nil {
return "", err
......@@ -534,6 +545,11 @@ func deleteDeviceProfile(conn redis.Conn, id string) error {
dp := contract.DeviceProfile{}
_ = unmarshalObject(object, &dp)
for _, c := range dp.CoreCommands {
if err := deleteCommand(conn, c.Id); err != nil {
return err
}
}
_ = conn.Send("MULTI")
_ = conn.Send("DEL", id)
_ = conn.Send("ZREM", db.DeviceProfile, id)
......@@ -543,7 +559,6 @@ func deleteDeviceProfile(conn redis.Conn, id string) error {
for _, label := range dp.Labels {
_ = conn.Send("SREM", db.DeviceProfile+":label:"+label, id)
}
// TODO: should commands be also removed?
for _, c := range dp.CoreCommands {
_ = conn.Send("SREM", db.DeviceProfile+":command:"+c.Id, id)
}
......@@ -1177,50 +1192,7 @@ func (c *Client) GetCommandByName(n string) ([]contract.Command, error) {
return cmd, nil
}
func (c *Client) AddCommand(cmd contract.Command) (string, error) {
conn := c.Pool.Get()
defer conn.Close()
return addCommand(conn, true, cmd)
}
// Update command uses the ID of the command for identification
func (c *Client) UpdateCommand(cmd contract.Command) error {
conn := c.Pool.Get()
defer conn.Close()
err := deleteCommand(conn, cmd.Id)
if err != nil {
return err
}
_, err = addCommand(conn, true, cmd)
return err
}
// Delete the command by ID
func (c *Client) DeleteCommandById(id string) error {
conn := c.Pool.Get()
defer conn.Close()
// TODO: ??? Check if the command is still in use by device profiles
return deleteCommand(conn, id)
}
func addCommand(conn redis.Conn, tx bool, cmd contract.Command) (string, error) {
_, err := uuid.Parse(cmd.Id)
if err != nil {
cmd.Id = uuid.New().String()
}
id := cmd.Id
ts := db.MakeTimestamp()
if cmd.Created == 0 {
cmd.Created = ts
}
cmd.Modified = ts
m, err := marshalObject(cmd)
if err != nil {
return "", err
......@@ -1229,9 +1201,9 @@ func addCommand(conn redis.Conn, tx bool, cmd contract.Command) (string, error)
if tx {
_ = conn.Send("MULTI")
}
_ = conn.Send("SET", id, m)
_ = conn.Send("ZADD", db.Command, 0, id)
_ = conn.Send("SADD", db.Command+":name:"+cmd.Name, id)
_ = conn.Send("SET", cmd.Id, m)
_ = conn.Send("ZADD", db.Command, 0, cmd.Id)
_ = conn.Send("SADD", db.Command+":name:"+cmd.Name, cmd.Id)
if tx {
_, err = conn.Do("EXEC")
if err != nil {
......@@ -1239,7 +1211,7 @@ func addCommand(conn redis.Conn, tx bool, cmd contract.Command) (string, error)
}
}
return id, nil
return cmd.Id, nil
}
func deleteCommand(conn redis.Conn, id string) error {
......
......@@ -21,10 +21,10 @@ func TestMetadataDB(t *testing.T, db interfaces.DBClient) {
db.ScrubMetadata()
testDBAddressables(t, db)
testDBCommand(t, db)
testDBDeviceService(t, db)
testDBDeviceReport(t, db)
testDBDeviceProfile(t, db)
testDBCommand(t, db)
testDBDevice(t, db)
testDBProvisionWatcher(t, db)
......@@ -112,12 +112,7 @@ func getDeviceProfile(db interfaces.DBClient, i int) (models.DeviceProfile, erro
// TODO
// dp.DeviceResources = append(dp.DeviceResources, name)
// dp.Resources = append(dp.Resources, name)
var err error
c := getCommand(db, i)
c.Id, err = db.AddCommand(c)
if err != nil {
return dp, err
}
dp.CoreCommands = append(dp.CoreCommands, c)
return dp, nil
}
......@@ -135,19 +130,6 @@ func populateAddressable(db interfaces.DBClient, count int) (string, error) {
return id, nil
}
func populateCommand(db interfaces.DBClient, count int) (string, error) {
var id string
for i := 0; i < count; i++ {
var err error
c := getCommand(db, i)
id, err = db.AddCommand(c)
if err != nil {
return id, err
}
}
return id, nil
}
func populateDeviceService(db interfaces.DBClient, count int) (string, error) {
var id string
for i := 0; i < count; i++ {
......@@ -493,28 +475,31 @@ func testDBAddressables(t *testing.T, db interfaces.DBClient) {
}
func testDBCommand(t *testing.T, db interfaces.DBClient) {
commands, err := db.GetAllCommands()
dps, err := db.GetAllDeviceProfiles()
if err != nil {
t.Fatalf("Error getting commands %v", err)
}
for _, c := range commands {
if err = db.DeleteCommandById(c.Id); err != nil {
t.Fatalf("Error removing command %v", err)
for _, dp := range dps {
if err = db.DeleteDeviceProfileById(dp.Id); err != nil {
t.Fatalf("Error removing DeviceProfile %v", err)
}
}
id, err := populateCommand(db, 100)
_, err = populateDeviceProfile(db, 100)
if err != nil {
t.Fatalf("Error populating db: %v\n", err)
}
commands, err = db.GetAllCommands()
commands, err := db.GetAllCommands()
if err != nil {
t.Fatalf("Error getting commands %v", err)
}
if len(commands) != 100 {
t.Fatalf("There should be 100 commands instead of %d", len(commands))
}
id := commands[0].Id
c, err := db.GetCommandById(id)
if err != nil {
t.Fatalf("Error getting command by id %v", err)
......@@ -867,23 +852,6 @@ func testDBDeviceProfile(t *testing.T, db interfaces.DBClient) {
if len(deviceProfiles) != 0 {
t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles))
}
deviceProfiles, err = db.GetDeviceProfilesByCommandId(dp.CoreCommands[0].Id)
if err != nil {
t.Fatalf("Error getting deviceProfiles %v", err)
}
if len(deviceProfiles) != 1 {
t.Fatalf("There should be 1 deviceProfiles instead of %d", len(deviceProfiles))
}
deviceProfiles, err = db.GetDeviceProfilesByCommandId(uuid.New().String())
if (err != nil && err != dataBase.ErrNotFound) || len(deviceProfiles) != 0 {
t.Fatalf("Error getting deviceProfiles %v", err)
}
if len(deviceProfiles) != 0 {
t.Fatalf("There should be 0 deviceProfiles instead of %d", len(deviceProfiles))
}
d2 := models.DeviceProfile{}
d2.Id = id
d2.Name = "name"
......