-
Notifications
You must be signed in to change notification settings - Fork 787
/
applications.go
182 lines (152 loc) · 4.92 KB
/
applications.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package applications
import (
v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
"github.com/jenkins-x/jx/v2/pkg/cmd/clients"
"github.com/jenkins-x/jx/v2/pkg/flagger"
"github.com/jenkins-x/jx/v2/pkg/kube"
"github.com/jenkins-x/jx/v2/pkg/kube/naming"
"github.com/jenkins-x/jx/v2/pkg/kube/services"
"github.com/jenkins-x/jx/v2/pkg/util"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// Deployment represents an application deployment in a single environment
type Deployment struct {
*appsv1.Deployment
}
// Environment represents an environment in which an application has been
// deployed
type Environment struct {
v1.Environment
Deployments []Deployment
}
// Application represents an application in jx
type Application struct {
*v1.SourceRepository
Environments map[string]Environment
}
// List is a collection of applications
type List struct {
Items []Application
}
// Environments loops through all applications in a list and returns a map with
// all the unique environments
func (l List) Environments() map[string]v1.Environment {
envs := make(map[string]v1.Environment)
for _, a := range l.Items {
for name, env := range a.Environments {
if _, ok := envs[name]; !ok {
envs[name] = env.Environment
}
}
}
return envs
}
// Name returns the application name
func (a Application) Name() string {
return naming.ToValidName(a.SourceRepository.Spec.Repo)
}
// IsPreview returns true if the environment is a preview environment
func (e Environment) IsPreview() bool {
return e.Environment.Spec.Kind == v1.EnvironmentKindTypePreview
}
// Version returns the deployment version
func (d Deployment) Version() string {
return kube.GetVersion(&d.Deployment.ObjectMeta)
}
// Pods returns the ratio of pods that are ready/replicas
func (d Deployment) Pods() string {
pods := ""
ready := d.Deployment.Status.ReadyReplicas
if d.Deployment.Spec.Replicas != nil && ready > 0 {
replicas := util.Int32ToA(*d.Deployment.Spec.Replicas)
pods = util.Int32ToA(ready) + "/" + replicas
}
return pods
}
// URL returns a deployment URL
func (d Deployment) URL(kc kubernetes.Interface, a Application) string {
url, _ := services.FindServiceURL(kc, d.Deployment.Namespace, a.Name())
return url
}
// GetApplications fetches all Applications
func GetApplications(factory clients.Factory) (List, error) {
list := List{
Items: make([]Application, 0),
}
client, namespace, err := factory.CreateJXClient()
if err != nil {
return list, errors.Wrap(err, "failed to create a jx client from applications.GetApplications")
}
// fetch ALL repositories
srList, err := client.JenkinsV1().SourceRepositories(namespace).List(metav1.ListOptions{})
if err != nil {
return list, errors.Wrapf(err, "failed to find any SourceRepositories in namespace %s", namespace)
}
// fetch all environments
envMap, _, err := kube.GetOrderedEnvironments(client, namespace)
if err != nil {
return list, errors.Wrapf(err, "failed to fetch environments in namespace %s", namespace)
}
// only keep permanent environments
permanentEnvsMap := map[string]*v1.Environment{}
for _, env := range envMap {
if env.Spec.Kind.IsPermanent() {
permanentEnvsMap[env.Spec.Namespace] = env
}
}
// copy repositories that aren't environments to our applications list
for _, sr := range srList.Items {
srCopy := sr
if !kube.IsIncludedInTheGivenEnvs(permanentEnvsMap, &srCopy) {
list.Items = append(list.Items, Application{&srCopy, make(map[string]Environment)})
}
}
kubeClient, _, err := factory.CreateKubeClient()
// fetch deployments by environment (excluding dev)
deployments := make(map[string]map[string]appsv1.Deployment)
for _, env := range permanentEnvsMap {
if env.Spec.Kind != v1.EnvironmentKindTypeDevelopment {
envDeployments, err := kube.GetDeployments(kubeClient, env.Spec.Namespace)
if err != nil {
return list, err
}
deployments[env.Spec.Namespace] = envDeployments
}
}
err = list.appendMatchingDeployments(permanentEnvsMap, deployments)
if err != nil {
return list, err
}
return list, nil
}
func getDeploymentAppNameInEnvironment(d appsv1.Deployment, e *v1.Environment) (string, error) {
labels, err := metav1.LabelSelectorAsMap(d.Spec.Selector)
if err != nil {
return "", err
}
name := kube.GetAppName(labels["app"], e.Spec.Namespace)
return name, nil
}
func (l List) appendMatchingDeployments(envs map[string]*v1.Environment, deps map[string]map[string]appsv1.Deployment) error {
for _, app := range l.Items {
for envName, env := range envs {
for _, dep := range deps[envName] {
depAppName, err := getDeploymentAppNameInEnvironment(dep, env)
if err != nil {
return errors.Wrap(err, "getting app name")
}
if depAppName == app.Name() && !flagger.IsCanaryAuxiliaryDeployment(dep) {
depCopy := dep
app.Environments[env.Name] = Environment{
*env,
[]Deployment{{&depCopy}},
}
}
}
}
}
return nil
}