ee5e6a81 |
package create
import ( |
063c94a0 |
"encoding/csv" |
ee5e6a81 |
"fmt"
"io"
"strings"
"github.com/spf13/cobra"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/runtime"
"github.com/openshift/origin/pkg/client" |
6267dded |
"github.com/openshift/origin/pkg/cmd/templates" |
ee5e6a81 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
quotaapi "github.com/openshift/origin/pkg/quota/api"
)
|
6267dded |
const ClusterQuotaRecommendedName = "clusterresourcequota" |
ee5e6a81 |
|
6267dded |
var (
clusterQuotaLong = templates.LongDesc(`
Create a cluster resource quota that controls certain resources. |
ee5e6a81 |
|
6267dded |
Cluster resource quota objects defined quota restrictions that span multiple projects based on label selectors.`) |
ee5e6a81 |
|
6267dded |
clusterQuotaExample = templates.Examples(`
# Create a cluster resource quota limited to 10 pods
%[1]s limit-bob --project-annotation-selector=openshift.io/requester=user-bob --hard=pods=10`) |
ee5e6a81 |
)
type CreateClusterQuotaOptions struct {
ClusterQuota *quotaapi.ClusterResourceQuota
Client client.ClusterResourceQuotasInterface
Mapper meta.RESTMapper
OutputFormat string
Out io.Writer
Printer ObjectPrinter
}
// NewCmdCreateServiceAccount is a macro command to create a new service account
func NewCmdCreateClusterQuota(name, fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
o := &CreateClusterQuotaOptions{Out: out}
cmd := &cobra.Command{ |
3635d268 |
Use: name + " NAME --project-label-selector=key=value [--hard=RESOURCE=QUANTITY]...", |
ee5e6a81 |
Short: "Create cluster resource quota resource.",
Long: clusterQuotaLong,
Example: fmt.Sprintf(clusterQuotaExample, fullName),
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(cmd, f, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run())
},
Aliases: []string{"clusterquota"},
}
|
3635d268 |
cmd.Flags().String("project-label-selector", "", "The project label selector for the cluster resource quota")
cmd.Flags().String("project-annotation-selector", "", "The project annotation selector for the cluster resource quota") |
ee5e6a81 |
cmd.Flags().StringSlice("hard", []string{}, "The resource to constrain: RESOURCE=QUANTITY (pods=10)")
cmdutil.AddOutputFlagsForMutation(cmd)
return cmd
}
func (o *CreateClusterQuotaOptions) Complete(cmd *cobra.Command, f *clientcmd.Factory, args []string) error {
if len(args) != 1 {
return fmt.Errorf("NAME is required: %v", args)
}
|
3635d268 |
var labelSelector *unversioned.LabelSelector
labelSelectorString := cmdutil.GetFlagString(cmd, "project-label-selector")
if len(labelSelectorString) > 0 {
var err error
labelSelector, err = unversioned.ParseToLabelSelector(labelSelectorString)
if err != nil {
return err
}
}
|
063c94a0 |
annotationSelector, err := parseAnnotationSelector(cmdutil.GetFlagString(cmd, "project-annotation-selector")) |
ee5e6a81 |
if err != nil {
return err
}
o.ClusterQuota = "aapi.ClusterResourceQuota{
ObjectMeta: kapi.ObjectMeta{Name: args[0]},
Spec: quotaapi.ClusterResourceQuotaSpec{ |
3635d268 |
Selector: quotaapi.ClusterResourceQuotaSelector{
LabelSelector: labelSelector, |
063c94a0 |
AnnotationSelector: annotationSelector, |
3635d268 |
}, |
ee5e6a81 |
Quota: kapi.ResourceQuotaSpec{
Hard: kapi.ResourceList{},
},
},
}
for _, resourceCount := range cmdutil.GetFlagStringSlice(cmd, "hard") {
tokens := strings.Split(resourceCount, "=")
if len(tokens) != 2 {
return fmt.Errorf("%v must in the form of resource=quantity", resourceCount)
}
quantity, err := resource.ParseQuantity(tokens[1])
if err != nil {
return err
} |
8201efbe |
o.ClusterQuota.Spec.Quota.Hard[kapi.ResourceName(tokens[0])] = quantity |
ee5e6a81 |
}
o.Client, _, err = f.Clients()
if err != nil {
return err
}
o.Mapper, _ = f.Object(false)
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
o.Printer = func(obj runtime.Object, out io.Writer) error {
return f.PrintObject(cmd, o.Mapper, obj, out)
}
return nil
}
func (o *CreateClusterQuotaOptions) Validate() error {
if o.ClusterQuota == nil {
return fmt.Errorf("ClusterQuota is required")
}
if o.Client == nil {
return fmt.Errorf("Client is required")
}
if o.Mapper == nil {
return fmt.Errorf("Mapper is required")
}
if o.Out == nil {
return fmt.Errorf("Out is required")
}
if o.Printer == nil {
return fmt.Errorf("Printer is required")
}
return nil
}
func (o *CreateClusterQuotaOptions) Run() error {
actualObj, err := o.Client.ClusterResourceQuotas().Create(o.ClusterQuota)
if err != nil {
return err
}
if useShortOutput := o.OutputFormat == "name"; useShortOutput || len(o.OutputFormat) == 0 {
cmdutil.PrintSuccess(o.Mapper, useShortOutput, o.Out, "clusterquota", actualObj.Name, "created")
return nil
}
return o.Printer(actualObj, o.Out)
} |
063c94a0 |
// parseAnnotationSelector just parses key=value,key=value=...,
// further validation is left to be done server-side.
func parseAnnotationSelector(s string) (map[string]string, error) {
if len(s) == 0 {
return nil, nil
}
stringReader := strings.NewReader(s)
csvReader := csv.NewReader(stringReader)
annotations, err := csvReader.Read()
if err != nil {
return nil, err
}
parsed := map[string]string{}
for _, annotation := range annotations {
parts := strings.SplitN(annotation, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("Malformed annotation selector, expected %q: %s", "key=value", annotation)
}
parsed[parts[0]] = parts[1]
}
return parsed, nil
} |