Welcome to mirror list, hosted at ThFree Co, Russian Federation.

domains.go « source « internal - gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e4a582ea9378a9e13b489d390b29c7d6f1b2902b (plain)
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
package source

import (
	"fmt"
	"regexp"

	"gitlab.com/gitlab-org/labkit/log"

	"gitlab.com/gitlab-org/gitlab-pages/internal/domain"
	"gitlab.com/gitlab-org/gitlab-pages/internal/source/disk"
	"gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab"
)

var (
	// serverlessDomainRegex is a regular expression we use to check if a domain
	// is a serverless domain, to short circuit gitlab source rollout. It can be
	// removed after the rollout is done
	serverlessDomainRegex = regexp.MustCompile(`^[^.]+-[[:xdigit:]]{2}a1[[:xdigit:]]{10}f2[[:xdigit:]]{2}[[:xdigit:]]+-?.*`)
)

type configSource int

const (
	sourceGitlab configSource = iota
	sourceDisk
	sourceAuto
)

// Domains struct represents a map of all domains supported by pages. It is
// currently using two sources during the transition to the new GitLab domains
// source.
type Domains struct {
	configSource configSource
	gitlab       Source
	disk         *disk.Disk // legacy disk source
}

// NewDomains is a factory method for domains initializing a mutex. It should
// not initialize `dm` as we later check the readiness by comparing it with a
// nil value.
func NewDomains(config Config) (*Domains, error) {
	domains := &Domains{
		// TODO: disable domains.disk https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382
		disk: disk.New(),
	}

	if err := domains.setConfigSource(config); err != nil {
		return nil, err
	}

	return domains, nil
}

// setConfigSource and initialize gitlab source
// returns error if -domain-config-source is not valid
// returns error if -domain-config-source=gitlab and init fails
func (d *Domains) setConfigSource(config Config) error {
	// TODO: Handle domain-config-source=auto https://gitlab.com/gitlab-org/gitlab/-/issues/218358
	// attach gitlab by default when source is not disk (auto, gitlab)
	switch config.DomainConfigSource() {
	case "gitlab":
		// TODO:  https://gitlab.com/gitlab-org/gitlab/-/issues/218357
		d.configSource = sourceGitlab
		return d.setGitLabClient(config)
	case "auto":
		// TODO: handle DomainConfigSource == "auto" https://gitlab.com/gitlab-org/gitlab/-/issues/218358
		d.configSource = sourceAuto
		return d.setGitLabClient(config)
	case "disk":
		d.configSource = sourceDisk
	default:
		return fmt.Errorf("invalid option for -domain-config-source: %q", config.DomainConfigSource())
	}

	return nil
}

// setGitLabClient when domain-config-source is `gitlab` or `auto`, only return error for `gitlab` source
func (d *Domains) setGitLabClient(config Config) error {
	// We want to notify users about any API issues
	// Creating a glClient will start polling connectivity in the background
	// and spam errors in log
	glClient, err := gitlab.New(config)
	if err != nil {
		if d.configSource == sourceGitlab {
			return err
		}

		log.WithError(err).Warn("failed to initialize GitLab client for `-domain-config-source=auto`")

		return nil
	}

	d.gitlab = glClient

	return nil
}

// GetDomain retrieves a domain information from a source. We are using two
// sources here because it allows us to switch behavior and the domain source
// for some subset of domains, to test / PoC the new GitLab Domains Source that
// we plan to use to replace the disk source.
func (d *Domains) GetDomain(name string) (*domain.Domain, error) {
	return d.source(name).GetDomain(name)
}

// Read starts the disk domain source. It is DEPRECATED, because we want to
// remove it entirely when disk source gets removed.
func (d *Domains) Read(rootDomain string) {
	d.disk.Read(rootDomain)
}

// IsReady checks if the disk domain source managed to traverse entire pages
// filesystem and is ready for use. It is DEPRECATED, because we want to remove
// it entirely when disk source gets removed.
func (d *Domains) IsReady() bool {
	return d.disk.IsReady()
}

func (d *Domains) source(domain string) Source {
	if d.gitlab == nil {
		return d.disk
	}

	// This check is only needed until we enable `d.gitlab` source in all
	// environments (including on-premises installations) followed by removal of
	// `d.disk` source. This can be safely removed afterwards.
	if IsServerlessDomain(domain) {
		return d.gitlab
	}

	if d.configSource == sourceDisk {
		return d.disk
	}

	// TODO: handle sourceAuto https://gitlab.com/gitlab-org/gitlab/-/issues/218358
	// check IsReady for sourceAuto for now
	if d.configSource == sourceGitlab || d.gitlab.IsReady() {
		return d.gitlab
	}

	return d.disk
}

// IsServerlessDomain checks if a domain requested is a serverless domain we
// need to handle differently.
//
// Domain is a serverless domain when it matches `serverlessDomainRegex`. The
// regular expression is also defined on the gitlab-rails side, see
// https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/serverless/domain.rb#L7
func IsServerlessDomain(domain string) bool {
	return serverlessDomainRegex.MatchString(domain)
}