Small improvements & refactoring

Change-Id: I639e2bb5473b7a04a4210f516d41bcfb2c9072ae
Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
This commit is contained in:
Ruslan Aliev 2024-03-08 17:14:50 -06:00
parent e1dc792eac
commit ecc7b61434
4 changed files with 60 additions and 46 deletions

3
go.mod
View File

@ -4,6 +4,7 @@ go 1.21
require (
github.com/databus23/goslo.policy v0.0.0-20210929125152-81bf2876dbdb
github.com/databus23/keystone v0.0.0-20180111110916-350fd0e663cd
github.com/gin-gonic/gin v1.9.1
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.18.2
@ -13,7 +14,6 @@ require (
k8s.io/apiextensions-apiserver v0.29.0
k8s.io/apimachinery v0.29.0
k8s.io/client-go v0.29.0
k8s.io/klog/v2 v2.110.1
opendev.org/airship/armada-operator v0.0.0-20240307081059-16b2953b2143
sigs.k8s.io/controller-runtime v0.17.2
sigs.k8s.io/yaml v1.4.0
@ -82,6 +82,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

2
go.sum
View File

@ -8,6 +8,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/databus23/goslo.policy v0.0.0-20210929125152-81bf2876dbdb h1:8JB2G8t3o1iCL8vCzssUj2Nn2qjqSab2/G3xXhvkpPQ=
github.com/databus23/goslo.policy v0.0.0-20210929125152-81bf2876dbdb/go.mod h1:tRj172JgwQmUmEqZZJBWzYWFStitMFTtb95NtUnmpkw=
github.com/databus23/keystone v0.0.0-20180111110916-350fd0e663cd h1:OptdAs3t90tBs6w+lAJVVhBQj3/gqHh1tAQQBL5r08M=
github.com/databus23/keystone v0.0.0-20180111110916-350fd0e663cd/go.mod h1:TtJx0X0i4vIrVWmEEDScoV1pI2IRk0xnLSOdkBOSNgQ=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=

View File

@ -18,14 +18,15 @@ import (
"bufio"
"context"
"errors"
"flag"
"fmt"
"io"
"net/http"
"net/url"
"opendev.org/airship/armada-go/pkg/auth"
"opendev.org/airship/armada-go/pkg/log"
"os"
"regexp"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"strings"
"time"
@ -45,7 +46,6 @@ import (
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
"sigs.k8s.io/yaml"
"opendev.org/airship/armada-go/pkg/config"
@ -102,12 +102,7 @@ type AirshipChart struct {
// RunE runs the phase
func (c *RunCommand) RunE() error {
klog.InitFlags(nil)
klog.SetOutput(c.Out)
if err := flag.Set("v", "5"); err != nil {
return err
}
klog.V(2).Infof("armada-go apply, manifests path %s", c.Manifests)
log.Printf("armada-go apply, manifests path %s", c.Manifests)
if err := c.ParseManifests(); err != nil {
return err
@ -115,7 +110,7 @@ func (c *RunCommand) RunE() error {
k8sConfig, err := rest.InClusterConfig()
if err != nil {
klog.V(2).Infoln("Unable to load in-cluster kubeconfig, reason: ", err)
log.Printf("Unable to load in-cluster kubeconfig, reason: ", err)
k8sConfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(), &clientcmd.ConfigOverrides{}).ClientConfig()
if err != nil {
@ -140,11 +135,11 @@ func (c *RunCommand) RunE() error {
for _, cgName := range c.airManifest.ChartGroups {
cg := c.airGroups[cgName]
klog.V(5).Infof("processing chart group %s, sequenced %s", cgName, cg.Sequenced)
log.Printf("processing chart group %s, sequenced %s", cgName, cg.Sequenced)
if !cg.Sequenced {
eg := errgroup.Group{}
for _, cName := range cg.ChartGroup {
klog.V(5).Infof("adding 1 chart to wg %s", cName)
log.Printf("adding 1 chart to wg %s", cName)
chp := c.airCharts[cName]
chpc := c.ConvertChart(chp)
eg.Go(func() error {
@ -156,7 +151,7 @@ func (c *RunCommand) RunE() error {
}
} else {
for _, cName := range cg.ChartGroup {
klog.V(5).Infof("sequential chart install %s", cName)
log.Printf("sequential chart install %s", cName)
if err = c.InstallChart(c.ConvertChart(c.airCharts[cName]), resClient, k8sConfig); err != nil {
return err
}
@ -171,7 +166,7 @@ func (c *RunCommand) InstallChart(
resClient dynamic.NamespaceableResourceInterface,
restConfig *rest.Config) error {
klog.V(5).Infof("installing chart %s %s %s", chart.GetName(), chart.Name, chart.Namespace)
log.Printf("installing chart %s %s %s", chart.GetName(), chart.Name, chart.Namespace)
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(chart)
if err != nil {
return err
@ -179,26 +174,26 @@ func (c *RunCommand) InstallChart(
if oldObj, err := resClient.Namespace(chart.Namespace).Get(
context.Background(), chart.GetName(), metav1.GetOptions{}); err != nil {
klog.V(5).Infof("unable to get chart %s: %s, creating", chart.Name, err.Error())
log.Printf("unable to get chart %s: %s, creating", chart.Name, err.Error())
if _, err = resClient.Namespace(chart.Namespace).Create(
context.Background(), &unstructured.Unstructured{Object: obj}, metav1.CreateOptions{}); err != nil {
return err
}
klog.V(5).Infof("chart has been successfully created %s", chart.Name)
log.Printf("chart has been successfully created %s", chart.Name)
} else {
uObj := &unstructured.Unstructured{Object: obj}
uObj.SetResourceVersion(oldObj.GetResourceVersion())
klog.V(5).Infof("chart %s was found, updating", chart.Name)
log.Printf("chart %s was found, updating", chart.Name)
if _, err = resClient.Namespace(chart.Namespace).Update(
context.Background(), uObj, metav1.UpdateOptions{}); err != nil {
klog.V(5).Infof("resource update error: %s", err.Error())
log.Printf("resource update error: %s", err.Error())
if strings.Contains(err.Error(), "the object has been modified") {
klog.V(5).Infof("resource expired, retrying %s", err.Error())
log.Printf("resource expired, retrying %s", err.Error())
return c.InstallChart(chart, resClient, restConfig)
}
return err
}
klog.V(5).Infof("chart has been successfully updated %s", chart.Name)
log.Printf("chart has been successfully updated %s", chart.Name)
}
wOpts := armadawait.WaitOptions{
@ -208,11 +203,11 @@ func (c *RunCommand) InstallChart(
fmt.Sprintf("%s-%s", c.airManifest.ReleasePrefix, chart.Spec.Release)),
ResourceType: "armadacharts",
Timeout: time.Second * time.Duration(chart.Spec.Wait.Timeout),
Logger: klog.FromContext(context.Background()),
Logger: zap.New(zap.WriteTo(c.Out), zap.ConsoleEncoder()),
}
err = wOpts.Wait(context.Background())
klog.V(5).Infof("finished with chart %s", chart.GetName())
log.Printf("finished with chart %s", chart.GetName())
return err
}
@ -237,14 +232,14 @@ func (c *RunCommand) CheckCRD(restConfig *rest.Config) error {
crdClient := apiextension.NewForConfigOrDie(restConfig)
if _, err := crdClient.ApiextensionsV1().CustomResourceDefinitions().Get(context.Background(), "armadacharts.armada.airshipit.org", metav1.GetOptions{}); err != nil {
if apierrors.IsNotFound(err) {
klog.V(5).Infof("armadacharts CRD not found, creating: %s", err.Error())
log.Printf("armadacharts CRD not found, creating: %s", err.Error())
objToapp, err := c.ReadCRD()
if err != nil {
return err
}
_, err = crdClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.Background(), objToapp, metav1.CreateOptions{})
if err != nil {
klog.V(5).Infof("error while creating crd %t", err)
log.Printf("error while creating crd %t", err)
return err
}
} else {
@ -287,10 +282,10 @@ func (c *RunCommand) VerifyNamespaces(rsc *rest.Config) error {
}
}
for k, _ := range namespaces {
klog.V(5).Infof("processing namespace %s", k)
log.Printf("processing namespace %s", k)
if _, err := cs.CoreV1().Namespaces().Get(context.Background(), k, metav1.GetOptions{}); err != nil {
if apierrors.IsNotFound(err) {
klog.V(5).Infof("namespace %s not found, creating", k)
log.Printf("namespace %s not found, creating", k)
if _, err = cs.CoreV1().Namespaces().Create(context.Background(), &v1.Namespace{
ObjectMeta: metav1.ObjectMeta{Name: k}}, metav1.CreateOptions{}); err != nil {
return err
@ -300,7 +295,7 @@ func (c *RunCommand) VerifyNamespaces(rsc *rest.Config) error {
}
}
}
klog.V(5).Infof("all namespaces validated successfully")
log.Printf("all namespaces validated successfully")
return nil
}
@ -324,12 +319,12 @@ func (c *RunCommand) ValidateManifests() error {
return errors.New(fmt.Sprintf("no group document with name %s found", cgname))
}
}
klog.V(5).Infof("all airship manifests validated successfully")
log.Printf("all airship manifests validated successfully")
return nil
}
func (c *RunCommand) ParseManifests() error {
klog.V(5).Infof("parsing manifests started, path: %s", c.Manifests)
log.Printf("parsing manifests started, path: %s", c.Manifests)
var f io.ReadCloser
u, err := url.Parse(c.Manifests)
@ -378,7 +373,7 @@ func (c *RunCommand) ParseManifests() error {
}
var typeMeta AirshipDocument
if err := yaml.Unmarshal(buf, &typeMeta); err != nil {
klog.V(2).Infof("unmarshalling error %s, continuing...", err.Error())
log.Printf("unmarshalling error %s, continuing...", err.Error())
continue
}
@ -389,7 +384,7 @@ func (c *RunCommand) ParseManifests() error {
if err := yaml.Unmarshal(buf, &airManifest); err != nil {
return err
}
klog.V(2).Infof("found airship manifest %s", airManifest.Metadata.Name)
log.Printf("found airship manifest %s", airManifest.Metadata.Name)
c.airManifest = &airManifest
}
}

View File

@ -17,12 +17,12 @@ package server
import (
"fmt"
policy "github.com/databus23/goslo.policy"
"github.com/databus23/keystone"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
"gopkg.in/yaml.v3"
"net/http"
"opendev.org/airship/armada-go/pkg/apply"
auth2 "opendev.org/airship/armada-go/pkg/auth"
"opendev.org/airship/armada-go/pkg/config"
"opendev.org/airship/armada-go/pkg/log"
"os"
@ -39,16 +39,30 @@ type JsonDataRequest struct {
Overrides []any `json:"overrides"`
}
func PolicyEnforcer(enforcer *policy.Enforcer, rule string) gin.HandlerFunc {
return func(context *gin.Context) {
ctx := policy.Context{
Roles: strings.Split(context.GetHeader("X-Roles"), ","),
Logger: log.Printf,
}
if enforcer.Enforce(rule, ctx) {
context.Next()
func Enforcer(enforcer *policy.Enforcer, rule string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("X-Identity-Status") != "Confirmed" {
w.WriteHeader(401)
_, _ = fmt.Fprint(w, "Invalid or no token provided")
} else {
context.String(401, "oslo policy error")
ctx := policy.Context{
Roles: strings.Split(r.Header.Get("X-Roles"), ","),
Logger: log.Printf,
}
if !enforcer.Enforce(rule, ctx) {
w.WriteHeader(401)
_, _ = fmt.Fprint(w, "Oslo policy error")
}
log.Printf("Request from authenticated user %s with roles %s", r.Header.Get("X-User-Name"), r.Header.Get("X-Roles"))
}
}
}
func Authenticator(h http.Handler) gin.HandlerFunc {
return func(c *gin.Context) {
h.ServeHTTP(c.Writer, c.Request)
if c.Writer.Status() == 401 {
c.Abort()
}
}
}
@ -127,8 +141,10 @@ func (c *RunCommand) RunE() error {
}
log.Printf("armada-go server has been started")
r := gin.Default()
auth := auth2.New(viper.Sub("keystone_authtoken").GetString("auth_url"))
r := gin.New()
r.Use(gin.Recovery())
auth := keystone.New(viper.Sub("keystone_authtoken").GetString("auth_url"))
buf, err := os.ReadFile("/etc/armada/policy.yaml")
if err != nil {
@ -146,9 +162,9 @@ func (c *RunCommand) RunE() error {
return err
}
r.POST("/api/v1.0/apply", gin.Logger(), auth.Handler(r.Handler()), PolicyEnforcer(enf, "armada:create_endpoints"), Apply)
r.POST("/api/v1.0/validatedesign", gin.Logger(), auth.Handler(r.Handler()), PolicyEnforcer(enf, "armada:validate_manifest"), Validate)
r.GET("/api/v1.0/releases", gin.Logger(), auth.Handler(r.Handler()), PolicyEnforcer(enf, "armada:get_release"), Releases)
r.POST("/api/v1.0/apply", gin.Logger(), Authenticator(auth.Handler(Enforcer(enf, "armada:create_endpoints"))), Apply)
r.POST("/api/v1.0/validatedesign", gin.Logger(), Authenticator(auth.Handler(Enforcer(enf, "armada:validate_manifest"))), Validate)
r.GET("/api/v1.0/releases", gin.Logger(), Authenticator(auth.Handler(Enforcer(enf, "armada:get_release"))), Releases)
r.GET("/api/v1.0/health", Health)
return r.Run(":8000")
}