Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Marko Mudrinić <mudrinic.mare@gmail.com>
  • Loading branch information
xmudrii committed Apr 17, 2019
1 parent 71c8429 commit 6b5d5d0
Show file tree
Hide file tree
Showing 13 changed files with 675 additions and 22 deletions.
1 change: 1 addition & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions pkg/apis/kubeonecluster/helpers.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
Copyright 2019 The KubeOne 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 kubeonecluster

import (
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/kubeonecluster/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ type MetricsServer struct {

// OpenIDConnect feature flag
type OpenIDConnect struct {
Enable bool `json:"enable"`
Config OpenIDConnectConfig `json:"config"`
Enable bool `json:"enable"`
Config *OpenIDConnectConfig `json:"config"`
}

// OpenIDConnectConfig config
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/kubeonecluster/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ type MetricsServer struct {

// OpenIDConnect feature flag
type OpenIDConnect struct {
Enable bool `json:"enable"`
Config OpenIDConnectConfig `json:"config"`
Enable bool `json:"enable"`
Config *OpenIDConnectConfig `json:"config"`
}

// OpenIDConnectConfig config
Expand Down
8 changes: 2 additions & 6 deletions pkg/apis/kubeonecluster/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions pkg/apis/kubeonecluster/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

146 changes: 142 additions & 4 deletions pkg/apis/kubeonecluster/validation/validation.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,51 @@
/*
Copyright 2019 The KubeOne 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 validation

import (
"net"

"github.com/kubermatic/kubeone/pkg/apis/kubeonecluster"
"github.com/pkg/errors"

"k8s.io/apimachinery/pkg/util/validation/field"
)

// ValidateKubeOneCluster validates the KubeOneCluster object
func ValidateKubeOneCluster(c *kubeonecluster.KubeOneCluster) field.ErrorList {
allErrs := field.ErrorList{}

allErrs = append(allErrs, ValidateProviderConfig(&c.Spec.Provider, field.NewPath("provider"))...)

if len(c.Spec.Hosts) > 0 {
allErrs = append(allErrs, ValidateHostConfig(c.Spec.Hosts, field.NewPath("hosts"))...)
} else {
allErrs = append(allErrs, field.Invalid(field.NewPath("hosts"), c.Spec.Hosts, "no host specified"))
}

if *c.Spec.MachineController.Deploy {
allErrs = append(allErrs, ValidateMachineControllerConfig(&c.Spec.MachineController, c.Spec.Provider.Name, field.NewPath("machineController"))...)
allErrs = append(allErrs, ValidateWorkerConfig(c.Spec.Workers, field.NewPath("workers"))...)
} else if len(c.Spec.Workers) > 0 {
allErrs = append(allErrs, field.Invalid(field.NewPath("workers"), c.Spec.Workers, "machine-controller deployment is disabled, but configuration still contains worker definitions"))
}

allErrs = append(allErrs, ValidateClusterNetworkConfig(&c.Spec.ClusterNetwork, field.NewPath("clusterNetwork"))...)
allErrs = append(allErrs, ValidateFeatures(&c.Spec.Features, field.NewPath("features"))...)

return allErrs
}

Expand All @@ -20,16 +57,117 @@ func ValidateProviderConfig(p *kubeonecluster.ProviderConfig, fldPath *field.Pat
case kubeonecluster.ProviderNameAWS:
case kubeonecluster.ProviderNameOpenStack:
if p.CloudConfig == "" {
allErrs = append(allErrs, field.Invalid(field.NewPath("clerrors.Errorf("`provider.cloud_config` is required for openstack provider"))
allErrs = append(allErrs, field.Invalid(fldPath, p.CloudConfig, "`provider.cloud_config` is required for openstack provider"))
}
case kubeonecluster.ProviderNameHetzner:
case kubeonecluster.ProviderNameDigitalOcean:
case kubeonecluster.ProviderNameVSphere:
case kubeonecluster.ProviderNameGCE:
case kubeonecluster.ProviderNameNone:
default:
return errors.Errorf("unknown provider name %q", p.Name)
allErrs = append(allErrs, field.Invalid(fldPath, p.Name, "unknown provider name"))
}

return allErrs
}

// TODO(xmudrii): hosts == 0

// ValidateHostConfig validates the HostConfig structure
func ValidateHostConfig(hosts []*kubeonecluster.HostConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

for _, h := range hosts {
if len(h.PublicAddress) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, h.PublicAddress, "no public IP/address given"))
}
if len(h.PrivateAddress) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, h.PrivateAddress, "no private IP/address givevn"))
}
if len(h.SSHPrivateKeyFile) == 0 && len(h.SSHAgentSocket) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, h.SSHPrivateKeyFile, "neither SSH private key nor agent socket given, don't know how to authenticate"))
allErrs = append(allErrs, field.Invalid(fldPath, h.SSHAgentSocket, "neither SSH private key nor agent socket given, don't know how to authenticate"))
}
if len(h.SSHUsername) == 0 {
allErrs = append(allErrs, field.Invalid(fldPath, h.SSHUsername, "no SSH username given"))
}
}

return allErrs
}

// ValidateMachineControllerConfig validates the MachineControllerConfig structure
func ValidateMachineControllerConfig(m *kubeonecluster.MachineControllerConfig, cloudProviderName kubeonecluster.ProviderName, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

// If ProviderName is not None default to cloud provider and ensure user have not
// manually provided machine-controller provider different than cloud provider.
// If ProviderName is None, take user input or default to None.
if cloudProviderName != kubeonecluster.ProviderNameNone {
if m.Provider != cloudProviderName {
allErrs = append(allErrs, field.Invalid(fldPath, m.Provider, "cloud provider must be same as machine-controller provider"))
}
} else if cloudProviderName == kubeonecluster.ProviderNameNone && m.Provider == "" {
allErrs = append(allErrs, field.Invalid(fldPath, m.Provider, "machine-controller deployed but no provider selected"))
}

return allErrs
}

func ValidateWorkerConfig(workerset []kubeonecluster.WorkerConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

for _, w := range workerset {
if w.Name == "" {
allErrs = append(allErrs, field.Invalid(fldPath, w.Name, "no name given"))
}
if w.Replicas == nil || *w.Replicas < 1 {
allErrs = append(allErrs, field.Invalid(fldPath, w.Replicas, "replicas must be specified and >= 1"))
}
}

return nil
return allErrs
}

// ValidateClusterNetworkConfig validates the ClusterNetworkConfig structure
func ValidateClusterNetworkConfig(c *kubeonecluster.ClusterNetworkConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

if c.PodSubnet != "" {
if _, _, err := net.ParseCIDR(c.PodSubnet); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, c.PodSubnet, "invalid pod subnet specified"))
}
}

if c.ServiceSubnet != "" {
if _, _, err := net.ParseCIDR(c.ServiceSubnet); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, c.ServiceSubnet, "invalid service subnet specified"))
}
}

return allErrs
}

// ValidateFeatures validates the Features structure
func ValidateFeatures(f *kubeonecluster.Features, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if f.OpenIDConnect != nil && f.OpenIDConnect.Enable {
allErrs = append(allErrs, ValidateOIDCConfig(f.OpenIDConnect.Config, fldPath.Child("openidConnect"))...)
}
allErrs = append(allErrs)
return allErrs
}

// ValidateOIDCConfig validates the OpenID Connect configuration
func ValidateOIDCConfig(o *kubeonecluster.OpenIDConnectConfig, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

if o.IssuerURL == "" {
allErrs = append(allErrs, field.Invalid(fldPath, o.IssuerURL, "openid_connect.config.issuer_url can't be empty"))
}
if o.ClientID == "" {
allErrs = append(allErrs, field.Invalid(fldPath, o.ClientID, "openid_connect.config.client_id can't be empty"))
}

return allErrs
}
Loading

0 comments on commit 6b5d5d0

Please sign in to comment.