Skip to content

Commit

Permalink
Added initial implementation to detect changes
Browse files Browse the repository at this point in the history
  • Loading branch information
faizanahmad055 committed Jul 6, 2018
1 parent 055c4ed commit 5920890
Show file tree
Hide file tree
Showing 15 changed files with 801 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
@@ -0,0 +1,10 @@
*.swp
_dist/
.idea
golib
release
out/
_gopath/
.DS_Store
build
vendor
1 change: 1 addition & 0 deletions .version
@@ -0,0 +1 @@
1.0.0
8 changes: 8 additions & 0 deletions Jenkinsfile
@@ -0,0 +1,8 @@
#!/usr/bin/groovy
@Library('github.com/stakater/fabric8-pipeline-library@v2.4.0')

def dummy

goBuildAndRelease {

}
52 changes: 52 additions & 0 deletions Makefile
@@ -0,0 +1,52 @@
# note: call scripts from /scripts

.PHONY: default build builder-image binary-image test stop clean-images clean push apply deploy

BUILDER ?= reloader-builder
BINARY ?= Reloader
DOCKER_IMAGE ?= stakater/reloader
# Default value "dev"
DOCKER_TAG ?= dev
REPOSITORY = ${DOCKER_IMAGE}:${DOCKER_TAG}

VERSION=$(shell cat .version)
BUILD=

GOCMD = go
GLIDECMD = glide
GOFLAGS ?= $(GOFLAGS:)
LDFLAGS =

default: build test

install:
"$(GLIDECMD)" install

build:
"$(GOCMD)" build ${GOFLAGS} ${LDFLAGS} -o "${BINARY}"

builder-image:
@docker build --network host -t "${BUILDER}" -f build/package/Dockerfile.build .

binary-image: builder-image
@docker run --network host --rm "${BUILDER}" | docker build --network host -t "${REPOSITORY}" -f Dockerfile.run -

test:
"$(GOCMD)" test -v ./...

stop:
@docker stop "${BINARY}"

clean-images: stop
@docker rmi "${BUILDER}" "${BINARY}"

clean:
"$(GOCMD)" clean -i

push: ## push the latest Docker image to DockerHub
docker push $(REPOSITORY)

apply:
kubectl apply -f deployments/manifests/

deploy: binary-image push apply
23 changes: 23 additions & 0 deletions README.1.md
@@ -0,0 +1,23 @@
# configmapcontroller

This comment has been minimized.

Copy link
@rasheedamir

rasheedamir Jul 6, 2018

Member

@faizanahmad055 this seems to direct copy of cmc and this will stay in our commit history


This controller watches for changes to `ConfigMap` and `Secret` objects and performs rolling upgrades on their associated deployments, deamonsets and statefulsets and updating dynamically.

This is particularly useful if the `ConfigMap` is used to define environment variables - or your app cannot easily and reliably watch the `ConfigMap` and update itself on the fly.

## How to use configmapcontroller

For a `Deployment` called `foo` have a `ConfigMap` called `foo`. Then add this annotation to your `Deployment`

```yaml
metadata:
annotations:
configmap.fabric8.io/update-on-change: "foo"
```

Then, providing `configmapcontroller` is running, whenever you edit the `ConfigMap` called `foo` the configmapcontroller will update the `Deployment` by adding the environment variable:

This comment has been minimized.

Copy link
@rasheedamir

rasheedamir Jul 6, 2018

Member

@faizanahmad055 this must work for all things that is:

  1. deployment
  2. statefulset
  3. daemonset

This comment has been minimized.

Copy link
@faizanahmad055

faizanahmad055 Jul 9, 2018

Author Contributor

Sure sir, currently I've added changes for deployment but I'll add further changes for statefulset and daemonset as well and update the readme.


```
FABRICB_FOO_REVISION=${configMapRevision}
```

This then triggers a rolling upgrade of your deployment's pods to use the new configuration.
35 changes: 35 additions & 0 deletions glide.yaml
@@ -0,0 +1,35 @@
package: .
import:
- package: github.com/openshift/origin
version: v1.3.0
subpackages:
- pkg/client
- package: github.com/spf13/cobra
- package: github.com/spf13/pflag
- package: k8s.io/kubernetes
version: 52492b4bff99ef3b8ca617d385a3ff0612f9402d
repo: git://github.com/openshift/kubernetes.git
vcs: git
subpackages:
- pkg/api
- pkg/api/resource
- pkg/api/unversioned
- pkg/client/unversioned
- pkg/fields
- pkg/kubectl/cmd
- pkg/kubectl/cmd/util
- pkg/labels
- pkg/runtime
- pkg/util
- package: github.com/opencontainers/runc
version: v0.0.7
subpackages:
- libcontainer
- package: github.com/imdario/mergo
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
- package: github.com/Sirupsen/logrus
version: aaf92c95712104318fc35409745f1533aa5ff327
- package: github.com/docker/distribution
version: 559433598c7be9d30d6cfc5cad5b5dfdb686725c
repo: git://github.com/openshift/docker-distribution.git
vcs: git
9 changes: 9 additions & 0 deletions internal/pkg/app/app.go
@@ -0,0 +1,9 @@
package app

import "github.com/stakater/Reloader/internal/pkg/cmd"

// Run runs the command
func Run() error {
cmd := cmd.NewReloaderCommand()
return cmd.Execute()
}
49 changes: 49 additions & 0 deletions internal/pkg/client/client.go
@@ -0,0 +1,49 @@
/**
* Copyright (C) 2015 Red Hat, Inc.
*
* 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 client

import (
oclient "github.com/openshift/origin/pkg/client"
"github.com/pkg/errors"
"k8s.io/kubernetes/pkg/client/restclient"
client "k8s.io/kubernetes/pkg/client/unversioned"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

func NewClient(f *cmdutil.Factory) (*client.Client, *restclient.Config, error) {
var err error
cfg, err := f.ClientConfig()
if err != nil {
return nil, nil, errors.Wrap(err, "Could not initialise client")
}
c, err := client.New(cfg)
if err != nil {
return nil, nil, errors.Wrap(err, "Could not initialise client")
}

return c, cfg, nil
}

func NewOpenShiftClient(cfg *restclient.Config) (*oclient.Client, *restclient.Config, error) {
ocfg := *cfg
ocfg.APIPath = ""
c, err := oclient.New(&ocfg)
if err != nil {
return nil, nil, errors.Wrap(err, "Could not initialise an OpenShift client")
}

return c, cfg, nil
}
117 changes: 117 additions & 0 deletions internal/pkg/cmd/reloader.go
@@ -0,0 +1,117 @@
package main

import (
"flag"
"fmt"
"net/http"
"net/http/pprof"
"os"
"os/signal"
"syscall"
"time"

"github.com/spf13/cobra"
"github.com/stakater/Reloader/internal/pkg/client"
"github.com/stakater/Reloader/internal/pkg/controller"
"github.com/stakater/Reloader/internal/pkg/util"
"github.com/stakater/Reloader/pkg/kube"
"github.com/golang/glog"
oclient "github.com/openshift/origin/pkg/client"
"github.com/spf13/pflag"
"k8s.io/kubernetes/pkg/api"
kubectlutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
)

func NewReloaderCommand() *cobra.Command {
cmds := &cobra.Command{
Use: "reloader",
Short: "A watcher for your Kubernetes cluster",
Run: startReloader,
}
return cmds
}

const (
healthPort = 10254
)

var (
flags = pflag.NewFlagSet("", pflag.ExitOnError)

resyncPeriod = flags.Duration("sync-period", 30*time.Second,
`Relist and confirm services this often.`)

healthzPort = flags.Int("healthz-port", healthPort, "port for healthz endpoint.")

profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)
)

func startReloader(cmd *cobra.Command, args []string) {
glog.Println("Starting Reloader")

// create the clientset
clientset, err := kube.GetClient()
if err != nil {
log.Fatal(err)
}

// get the Controller config file
config := getControllerConfig()

for k, v := range kube.ResourceMap {
c, err := controller.NewController(clientset, *resyncPeriod, config, v)
if err != nil {
glog.Fatalf("%s", err)
}

go registerHandlers()
go handleSigterm(c)

// Now let's start the controller
stop := make(chan struct{})
defer close(stop)

go c.Run(1, stop)
}

// Wait forever
select {}
}

func registerHandlers() {
mux := http.NewServeMux()

if *profiling {
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
}

server := &http.Server{
Addr: fmt.Sprintf(":%v", *healthzPort),
Handler: mux,
}
glog.Fatal(server.ListenAndServe())
}

func handleSigterm(c *controller.Controller) {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
sig := <-signalChan
glog.Infof("Received %s, shutting down", sig)
c.Stop()
}

// get the yaml configuration for the controller
func getControllerConfig() config.Config {
configFilePath := os.Getenv("CONFIG_FILE_PATH")
if len(configFilePath) == 0 {
//Default config file is placed in configs/ folder
configFilePath = "configs/config.yaml"
}
configuration, err := config.ReadConfig(configFilePath)
if err != nil {
log.Panic(err)
}
return configuration
}

2 comments on commit 5920890

@rasheedamir
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@faizanahmad055 few comments:

  1. I hope you have looked in the PR's on CMC as they have all the goodies we need as they support all different types of resources; the codebase in master is very old and almost obsolete

  2. if you copy something blindly plz ensure you give credit from where you copied it! cheating is not allowed in opensource world

  3. i see you started logging without using that logging thingie that we were suppose to take inspiration from kube-alert repo

  4. I don't like tons of code being pushed without any proper tests to verify it's execution; plz avoid that in future

@faizanahmad055
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sir, I'll take care of these from now on. I'm discussing these with @waseem-h and will update the structure of code. I'm currently testing the functionality locally, as soon as it is in working state I'll add unit test cases as well and make a PR.

Please sign in to comment.