Skip to content

Commit

Permalink
Add flag for go template to format host names
Browse files Browse the repository at this point in the history
When using an alternate DNS like external-dns, your host names will be
different than the internal core-dns format.  This adds a flag so that
the user can specify the name format using a go template.
  • Loading branch information
dmayle committed May 26, 2020
1 parent c4a6a1b commit 490dc4a
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
11 changes: 7 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ import (
var Version = "DEVELOPMENT.GOGET"

var (
masterURL string
kubeconfig string
checkVersion bool
masterURL string
kubeconfig string
hostsTemplate string
checkVersion bool

onlyOneSignalHandler = make(chan struct{})
shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}
Expand All @@ -56,6 +57,7 @@ var (
func init() {
flag.StringVar(&kubeconfig, "kubeconfig", "", "path to a kubeconfig. Only required if out-of-cluster")
flag.StringVar(&masterURL, "master", "", "the address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster")
flag.StringVar(&hostsTemplate, "hosts-template", "", "the go template to use for hostname formatting of name fields (StatefulSet, CIService, HLService, Ellipsis, Domain)")
flag.BoolVar(&checkVersion, "version", false, "print version")
}

Expand Down Expand Up @@ -117,7 +119,8 @@ func main() {
kubeInformerFactory.Apps().V1().Deployments(),
kubeInformerFactory.Batch().V1().Jobs(),
minioInformerFactory.Operator().V1().MinIOInstances(),
kubeInformerFactory.Core().V1().Services())
kubeInformerFactory.Core().V1().Services(),
hostsTemplate)

mirrorController := mirror.NewController(kubeClient, controllerClient,
kubeInformerFactory.Batch().V1().Jobs(),
Expand Down
40 changes: 40 additions & 0 deletions pkg/apis/operator.min.io/v1/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package v1

import (
"bytes"
"context"
"crypto/tls"
"errors"
Expand All @@ -26,6 +27,7 @@ import (
"net/http"
"path"
"strconv"
"text/template"
"time"

appsv1 "k8s.io/api/apps/v1"
Expand All @@ -39,6 +41,14 @@ import (
"github.com/minio/minio/pkg/madmin"
)

type hostsTemplateValues struct {
StatefulSet string
CIService string
HLService string
Ellipsis string
Domain string
}

// HasCredsSecret returns true if the user has provided a secret
// for a MinIOInstance else false
func (mi *MinIOInstance) HasCredsSecret() bool {
Expand Down Expand Up @@ -203,6 +213,36 @@ func (mi *MinIOInstance) MinIOHosts() []string {
return hosts
}

// TemplatedMinIOHosts returns the domain names in ellipses format created for current MinIOInstance without the service part
func (mi *MinIOInstance) TemplatedMinIOHosts(hostsTemplate string) []string {
hosts := make([]string, 0)
tmpl, err := template.New("hosts").Parse(hostsTemplate)
if err != nil {
msg := "Invalid go template for hosts"
klog.V(2).Infof(msg)
return hosts
}
var max, index int32
// Create the ellipses style URL
for _, z := range mi.Spec.Zones {
max = max + z.Servers
data := hostsTemplateValues{
StatefulSet: mi.MinIOStatefulSetName(),
CIService: mi.MinIOCIServiceName(),
HLService: mi.MinIOHLServiceName(),
Ellipsis: "{" + strconv.Itoa(int(index)) + "..." + strconv.Itoa(int(max)-1) + "}",
Domain: ClusterDomain,
}
output := new(bytes.Buffer)
if err = tmpl.Execute(output, data); err != nil {
continue
}
hosts = append(hosts, output.String())
index = max
}
return hosts
}

// AllMinIOHosts returns the all the individual domain names relevant for current MinIOInstance
func (mi *MinIOInstance) AllMinIOHosts() []string {
hosts := make([]string, 0)
Expand Down
13 changes: 9 additions & 4 deletions pkg/controller/cluster/main-controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ type Controller struct {
// recorder is an event recorder for recording Event resources to the
// Kubernetes API.
recorder record.EventRecorder

// Use a go template to render the hosts string
hostsTemplate string
}

// NewController returns a new sample controller
Expand All @@ -136,7 +139,8 @@ func NewController(
deploymentInformer appsinformers.DeploymentInformer,
jobInformer batchinformers.JobInformer,
minioInstanceInformer informers.MinIOInstanceInformer,
serviceInformer coreinformers.ServiceInformer) *Controller {
serviceInformer coreinformers.ServiceInformer,
hostsTemplate string) *Controller {

// Create event broadcaster
// Add minio-controller types to the default Kubernetes Scheme so Events can be
Expand Down Expand Up @@ -164,6 +168,7 @@ func NewController(
serviceListerSynced: serviceInformer.Informer().HasSynced,
workqueue: queue.NewNamedRateLimitingQueue(queue.DefaultControllerRateLimiter(), "MinIOInstances"),
recorder: recorder,
hostsTemplate: hostsTemplate,
}

klog.Info("Setting up event handlers")
Expand Down Expand Up @@ -411,7 +416,7 @@ func (c *Controller) syncHandler(key string) error {
if err != nil {
return err
}
ss = statefulsets.NewForMinIO(mi, hlSvc.Name)
ss = statefulsets.NewForMinIO(mi, hlSvc.Name, c.hostsTemplate)
ss, err = c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Create(ctx, ss, cOpts)
if err != nil {
return err
Expand Down Expand Up @@ -446,7 +451,7 @@ func (c *Controller) syncHandler(key string) error {
}
}

ss = statefulsets.NewForMinIO(mi, hlSvc.Name)
ss = statefulsets.NewForMinIO(mi, hlSvc.Name, c.hostsTemplate)
klog.V(2).Infof("Removing the existing StatefulSet %s with replicas: %d", name, *ss.Spec.Replicas)
if err := c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Delete(ctx, ss.Name, metav1.DeleteOptions{}); err != nil {
return err
Expand All @@ -472,7 +477,7 @@ func (c *Controller) syncHandler(key string) error {
return err
}
klog.V(4).Infof("Updating MinIOInstance %s MinIO server version %s, to: %s", name, mi.Spec.Image, ss.Spec.Template.Spec.Containers[0].Image)
ss = statefulsets.NewForMinIO(mi, hlSvc.Name)
ss = statefulsets.NewForMinIO(mi, hlSvc.Name, c.hostsTemplate)
if _, err := c.kubeClientSet.AppsV1().StatefulSets(mi.Namespace).Update(ctx, ss, uOpts); err != nil {
return err
}
Expand Down
9 changes: 6 additions & 3 deletions pkg/resources/statefulsets/minio-statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func volumeMounts(mi *miniov1.MinIOInstance) []corev1.VolumeMount {
}

// Builds the MinIO container for a MinIOInstance.
func minioServerContainer(mi *miniov1.MinIOInstance, serviceName string) corev1.Container {
func minioServerContainer(mi *miniov1.MinIOInstance, serviceName string, hostsTemplate string) corev1.Container {
args := []string{"server"}

if mi.Spec.Zones[0].Servers == 1 {
Expand All @@ -159,6 +159,9 @@ func minioServerContainer(mi *miniov1.MinIOInstance, serviceName string) corev1.
} else {
// append all the MinIOInstance replica URLs
hosts := mi.MinIOHosts()
if hostsTemplate != "" {
hosts = mi.TemplatedMinIOHosts(hostsTemplate)
}
for _, h := range hosts {
args = append(args, fmt.Sprintf("%s://"+h+"%s", miniov1.Scheme, mi.VolumePath()))
}
Expand Down Expand Up @@ -217,7 +220,7 @@ func getVolumesForContainer(mi *miniov1.MinIOInstance) []corev1.Volume {
}

// NewForMinIO creates a new StatefulSet for the given Cluster.
func NewForMinIO(mi *miniov1.MinIOInstance, serviceName string) *appsv1.StatefulSet {
func NewForMinIO(mi *miniov1.MinIOInstance, serviceName string, hostsTemplate string) *appsv1.StatefulSet {
// If a PV isn't specified just use a EmptyDir volume
var podVolumes = getVolumesForContainer(mi)
var replicas = mi.MinIOReplicas()
Expand Down Expand Up @@ -299,7 +302,7 @@ func NewForMinIO(mi *miniov1.MinIOInstance, serviceName string) *appsv1.Stateful
})
}

containers := []corev1.Container{minioServerContainer(mi, serviceName)}
containers := []corev1.Container{minioServerContainer(mi, serviceName, hostsTemplate)}

ss := &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Expand Down

0 comments on commit 490dc4a

Please sign in to comment.