1/*
2Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package object
18
19import (
20	"errors"
21	"strconv"
22
23	"github.com/vmware/govmomi/vim25"
24	"github.com/vmware/govmomi/vim25/methods"
25	"github.com/vmware/govmomi/vim25/mo"
26	"github.com/vmware/govmomi/vim25/types"
27	"golang.org/x/net/context"
28)
29
30var (
31	ErrKeyNameNotFound = errors.New("key name not found")
32)
33
34type CustomFieldsManager struct {
35	Common
36}
37
38// GetCustomFieldsManager wraps NewCustomFieldsManager, returning ErrNotSupported
39// when the client is not connected to a vCenter instance.
40func GetCustomFieldsManager(c *vim25.Client) (*CustomFieldsManager, error) {
41	if c.ServiceContent.CustomFieldsManager == nil {
42		return nil, ErrNotSupported
43	}
44	return NewCustomFieldsManager(c), nil
45}
46
47func NewCustomFieldsManager(c *vim25.Client) *CustomFieldsManager {
48	m := CustomFieldsManager{
49		Common: NewCommon(c, *c.ServiceContent.CustomFieldsManager),
50	}
51
52	return &m
53}
54
55func (m CustomFieldsManager) Add(ctx context.Context, name string, moType string, fieldDefPolicy *types.PrivilegePolicyDef, fieldPolicy *types.PrivilegePolicyDef) (*types.CustomFieldDef, error) {
56	req := types.AddCustomFieldDef{
57		This:           m.Reference(),
58		Name:           name,
59		MoType:         moType,
60		FieldDefPolicy: fieldDefPolicy,
61		FieldPolicy:    fieldPolicy,
62	}
63
64	res, err := methods.AddCustomFieldDef(ctx, m.c, &req)
65	if err != nil {
66		return nil, err
67	}
68
69	return &res.Returnval, nil
70}
71
72func (m CustomFieldsManager) Remove(ctx context.Context, key int32) error {
73	req := types.RemoveCustomFieldDef{
74		This: m.Reference(),
75		Key:  key,
76	}
77
78	_, err := methods.RemoveCustomFieldDef(ctx, m.c, &req)
79	return err
80}
81
82func (m CustomFieldsManager) Rename(ctx context.Context, key int32, name string) error {
83	req := types.RenameCustomFieldDef{
84		This: m.Reference(),
85		Key:  key,
86		Name: name,
87	}
88
89	_, err := methods.RenameCustomFieldDef(ctx, m.c, &req)
90	return err
91}
92
93func (m CustomFieldsManager) Set(ctx context.Context, entity types.ManagedObjectReference, key int32, value string) error {
94	req := types.SetField{
95		This:   m.Reference(),
96		Entity: entity,
97		Key:    key,
98		Value:  value,
99	}
100
101	_, err := methods.SetField(ctx, m.c, &req)
102	return err
103}
104
105func (m CustomFieldsManager) Field(ctx context.Context) ([]types.CustomFieldDef, error) {
106	var fm mo.CustomFieldsManager
107
108	err := m.Properties(ctx, m.Reference(), []string{"field"}, &fm)
109	if err != nil {
110		return nil, err
111	}
112
113	return fm.Field, nil
114}
115
116func (m CustomFieldsManager) FindKey(ctx context.Context, key string) (int32, error) {
117	field, err := m.Field(ctx)
118	if err != nil {
119		return -1, err
120	}
121
122	for _, def := range field {
123		if def.Name == key {
124			return def.Key, nil
125		}
126	}
127
128	k, err := strconv.Atoi(key)
129	if err == nil {
130		// assume literal int key
131		return int32(k), nil
132	}
133
134	return -1, ErrKeyNameNotFound
135}
136