github.com/profzone/eden-framework@v1.0.10/internal/generator/k8s_generator.go (about) 1 package generator 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/profzone/eden-framework/internal/generator/files" 7 "github.com/profzone/eden-framework/internal/project" 8 "github.com/profzone/eden-framework/pkg/courier/transport_grpc" 9 "github.com/profzone/eden-framework/pkg/courier/transport_http" 10 "github.com/profzone/eden-framework/pkg/reflectx" 11 "github.com/sirupsen/logrus" 12 appsv1 "k8s.io/api/apps/v1" 13 apiv1 "k8s.io/api/core/v1" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/apimachinery/pkg/runtime/serializer/json" 16 "k8s.io/apimachinery/pkg/types" 17 "k8s.io/apimachinery/pkg/util/intstr" 18 "path" 19 "reflect" 20 "strings" 21 ) 22 23 type K8sGenerator struct { 24 config []interface{} 25 } 26 27 func NewK8sGenerator(config []interface{}) *K8sGenerator { 28 return &K8sGenerator{ 29 config: config, 30 } 31 } 32 33 func (d *K8sGenerator) Load(cwd string) { 34 } 35 36 func (d *K8sGenerator) Pick() { 37 } 38 39 func (d *K8sGenerator) Output(outputPath string) Outputs { 40 outputs := Outputs{} 41 42 serverPorts := findServerPorts(d.config) 43 44 // Deployment config file 45 deploymentConfig := &appsv1.Deployment{ 46 TypeMeta: metav1.TypeMeta{ 47 Kind: "Deployment", 48 APIVersion: "apps/v1", 49 }, 50 ObjectMeta: metav1.ObjectMeta{ 51 Name: files.EnvVar(project.EnvKeyProjectName), 52 Namespace: files.EnvVar(project.EnvKeyProjectGroup), 53 }, 54 Spec: appsv1.DeploymentSpec{ 55 Replicas: int2Ptr(1), 56 Selector: &metav1.LabelSelector{ 57 MatchLabels: map[string]string{ 58 "workload.user.cattle.io/workloadselector": files.EnvVar(project.EnvKeyProjectSelector), 59 }, 60 }, 61 Template: apiv1.PodTemplateSpec{ 62 ObjectMeta: metav1.ObjectMeta{ 63 Labels: map[string]string{ 64 "workload.user.cattle.io/workloadselector": files.EnvVar(project.EnvKeyProjectSelector), 65 }, 66 }, 67 Spec: apiv1.PodSpec{ 68 Containers: []apiv1.Container{ 69 { 70 Name: files.EnvVar(project.EnvKeyProjectName), 71 Image: fmt.Sprintf("%s/%s/%s:%s", 72 files.EnvVar(project.EnvKeyDockerRegistryKey), 73 files.EnvVar(project.EnvKeyProjectGroup), 74 files.EnvVar(project.EnvKeyProjectName), 75 files.EnvVar(project.EnvKeyProjectVersion), 76 ), 77 ImagePullPolicy: apiv1.PullAlways, 78 Ports: []apiv1.ContainerPort{}, 79 }, 80 }, 81 RestartPolicy: apiv1.RestartPolicyAlways, 82 }, 83 }, 84 }, 85 } 86 87 // Service config file 88 serviceConfig := &apiv1.Service{ 89 TypeMeta: metav1.TypeMeta{ 90 Kind: "Deployment", 91 APIVersion: "apps/v1", 92 }, 93 ObjectMeta: metav1.ObjectMeta{ 94 Name: files.EnvVar(project.EnvKeyProjectName), 95 Namespace: files.EnvVar(project.EnvKeyProjectGroup), 96 OwnerReferences: []metav1.OwnerReference{ 97 { 98 APIVersion: "apps/v1beta2", 99 Kind: "Deployment", 100 Name: files.EnvVar(project.EnvKeyProjectName), 101 UID: types.UID(files.EnvVar(project.EnvKeyDeploymentUID)), 102 }, 103 }, 104 }, 105 Spec: apiv1.ServiceSpec{ 106 Selector: map[string]string{ 107 "workload.user.cattle.io/workloadselector": files.EnvVar(project.EnvKeyProjectSelector), 108 }, 109 Ports: []apiv1.ServicePort{}, 110 }, 111 } 112 113 for _, port := range serverPorts { 114 deploymentConfig.Spec.Template.Spec.Containers[0].Ports = append(deploymentConfig.Spec.Template.Spec.Containers[0].Ports, apiv1.ContainerPort{ 115 Name: fmt.Sprintf("tcp%d", port), 116 ContainerPort: port, 117 Protocol: apiv1.ProtocolTCP, 118 }) 119 serviceConfig.Spec.Ports = append(serviceConfig.Spec.Ports, apiv1.ServicePort{ 120 Name: fmt.Sprintf("tcp%d", port), 121 Protocol: apiv1.ProtocolTCP, 122 Port: port, 123 TargetPort: intstr.FromInt(int(port)), 124 }) 125 } 126 127 serializer := json.NewSerializerWithOptions(json.DefaultMetaFactory, nil, nil, json.SerializerOptions{ 128 Yaml: true, 129 Pretty: true, 130 Strict: true, 131 }) 132 deploymentBuffer := bytes.NewBuffer([]byte{}) 133 err := serializer.Encode(deploymentConfig, deploymentBuffer) 134 if err != nil { 135 logrus.Panic(err) 136 } 137 serviceBuffer := bytes.NewBuffer([]byte{}) 138 err = serializer.Encode(serviceConfig, serviceBuffer) 139 if err != nil { 140 logrus.Panic(err) 141 } 142 143 outputs.Add(path.Join(outputPath, "build/deploy.default.yml"), deploymentBuffer.String()) 144 outputs.Add(path.Join(outputPath, "build/service.default.yml"), serviceBuffer.String()) 145 return outputs 146 } 147 148 func findServerPorts(config []interface{}) (ports []int32) { 149 for _, c := range config { 150 val := reflect.ValueOf(c) 151 152 exampleNames := exampleServerFullTypeName() 153 EachFieldValue(val.Elem(), func(field reflect.Value) bool { 154 fullName := reflectx.FullTypeName(reflectx.FromRType(field.Type())) 155 for _, name := range exampleNames { 156 if strings.HasSuffix(fullName, name) { 157 field = reflectx.Indirect(field) 158 portVal := field.FieldByName("Port") 159 if !reflectx.IsEmptyValue(portVal) { 160 ports = append(ports, int32(portVal.Int())) 161 } 162 } 163 } 164 165 return true 166 }) 167 } 168 return 169 } 170 171 func exampleServerFullTypeName() (names []string) { 172 exampleHttpServer := transport_http.ServeHTTP{} 173 exampleGrpcServer := transport_grpc.ServeGRPC{} 174 175 httpTyp := reflect.TypeOf(exampleHttpServer) 176 names = append(names, httpTyp.PkgPath()+"."+httpTyp.Name()) 177 grpcTyp := reflect.TypeOf(exampleGrpcServer) 178 names = append(names, grpcTyp.PkgPath()+"."+grpcTyp.Name()) 179 return 180 } 181 182 func EachFieldValue(val reflect.Value, walker func(value reflect.Value) bool) { 183 for i := 0; i < val.NumField(); i++ { 184 field := val.Field(i) 185 if !walker(field) { 186 break 187 } 188 } 189 }