Skip to content

Commit 4d4b336

Browse files
committed
refactor: redefine configuration structure (database-lab#278):
- change configs structure - adjust Docker image - clean up README
1 parent f40c5b7 commit 4d4b336

File tree

10 files changed

+58
-138
lines changed

10 files changed

+58
-138
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@
88
/deploy/
99

1010
config/config.yml
11+
configs/config.yml
12+
configs/joe.yml
13+
meta/sessions.json

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ RUN apk add --no-cache bash postgresql-client
55
WORKDIR /home/
66

77
COPY ./bin/joe ./bin/joe
8-
COPY ./config ./config
8+
COPY ./configs/explain ./explain
99

1010
EXPOSE $SERVER_PORT
1111

README.md

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -18,100 +18,8 @@ at the upper right corner):
1818

1919
![Add a star](./assets/star.gif)
2020

21-
To discuss Joe, [join our community Slack](https://database-lab-team-slack-invite.herokuapp.com/).
22-
23-
## Install Software
24-
25-
### 1. Database Lab
26-
Install and setup [Database Lab](https://gitlab.com/postgres-ai/database-lab)
27-
28-
Prepare one or more Database Lab instances before configuring Joe bot.
29-
30-
> ⚠ Make sure that `accessHost` is specified in the Database Lab configuration file.
31-
32-
Then, configure ways of communication with Joe.
33-
34-
### 2. Configure communication channels
35-
36-
There are two available types of communication:
37-
- Web UI powered by [Postgres.ai Console](https://postgres.ai/console/)
38-
- Slack
39-
40-
You can use both of them in parallel. Feel free to implement more types of communication: see [communication channels issues](https://gitlab.com/postgres-ai/joe/-/issues?label_name%5B%5D=Communication+channel).
41-
42-
### 2a. Set up Joe in Postgres.ai Console ("Web UI")
43-
If you don't need Web UI and prefer working with Joe only in messengers (such as Slack), proceed to the next step.
44-
45-
To configure Web UI:
46-
47-
1. First, get your `PLATFORM_TOKEN`. In [Postgres.ai Console](https://postgres.ai/console/), switch to proper organization and open the `Access Tokens` page.
48-
1. Then, go to the `Joe instances` page from the `SQL Optimization` sidebar section, choose a project from the dropdown menu and `Add instance`.
49-
1. Generate `Signing secret`. Use the secret as `WEBUI_SIGNING_SECRET` at the configuration file. We will add and verify the URL on the last step.
50-
51-
52-
### 2b. Slack App
53-
Configure a new Slack App in order to use Joe in Slack and add the app to your
54-
team Workspace. Joe Bot should be available with public URL calls from Slack.
55-
1. Create "#db-lab" channel in your Slack Workspace (You can use another channel name).
56-
1. [Create a new Slack App](https://api.slack.com/apps?new_app=1).
57-
* Use "Joe Bot" as App Name and select a proper team Workspace.
58-
1. Add Bot User.
59-
* Use "Joe Bot" as Display Name and "joe-bot" as the default username.
60-
1. Grant permissions on the "OAuth & Permissions" page for the following "Bot Token Scopes" :
61-
* `channels:history`
62-
* `chat:write`
63-
* `files:read`
64-
* `files:write`
65-
* `incoming-webhook`
66-
* `reactions:write`
67-
* `users.profile:read`
68-
* `users:read`
69-
1. Run Joe Bot with `Bot User OAuth Access Token ("xoxb-TOKEN")` from "OAuth & Permissions" Feature and `Signing Secret` from "Basic Information" page (See **Run** below).
70-
1. Enable Incoming Webhooks Feature.
71-
* Press "Add New Webhook to Workspace" and select a previously created channel to post token.
72-
1. Enable Event Subscriptions Feature.
73-
* Specify Request URL (URL will be verified by Slack API) (e.g. http://35.200.200.200:2400, https://joe.dev.domain.com). You would need to run Joe with proper settings before you could verify Request URL.
74-
75-
### 3. Run
76-
Deploy Joe instance in your infrastructure. You would need to:
77-
78-
1. Configure communication channels. You can copy the example `config/config.example.yml` to `~/.dblab/joe.yml`, inspect all configuration options, and adjust if needed.
79-
80-
1. Run the Joe Docker image to connect with the Database Lab server according to the previous configurations.
81-
Example:
82-
83-
```bash
84-
docker run \
85-
--name joe_bot \
86-
--publish 2400:2400 \
87-
--volume ~/.dblab/joe.yml:/home/config/config.yml \
88-
--restart=on-failure \
89-
--detach \
90-
postgresai/joe:latest
91-
```
92-
The Joe instance will be running by port 2400 of the current machine.
93-
94-
1. Make a publicly accessible HTTP(S) server port specified in the configuration for Web UI/Slack Events Request URL.
95-
96-
### 4. Verify the configuration
97-
98-
### 4a. Finish the WebUI configuration
99-
100-
1. Return to the page of Joe configuration in the Console, enter the URL with the specific path `/webui/`. For example, `https://joe.dev.domain.com/webui/`.
101-
1. Press the `Verify` button to check connection and `Add` the instance after the verification is passed.
102-
1. Choose the created instance and send a command.
103-
104-
105-
### 4b. Finish the Slack App configuration
106-
1. Enable Event Subscriptions Feature.
107-
* Go to the "Event Subscriptions" page.
108-
* Specify Request URL adding the specific for connection path: `/slack/` (URL will be verified by Slack API). You would need to run Joe with proper settings before you could verify Request URL. For example, `https://joe.dev.domain.com/slack/`
109-
* In the "Subscribe to Bot Events" dropdown-tab add `message.channels`.
110-
* Press "Save Changes".
111-
112-
1. Invite "Joe Bot" to "#db-lab" channel.
113-
1. Send a command to the #db-lab channel. For example, `help`.
114-
21+
## Installation
22+
Follow the [tutorial](https://postgres.ai/docs/tutorials/joe-setup) to install Joe Bot and start using it for PostgreSQL query optimization
11523

11624
## Development
11725
See our [GitLab Container Registry](https://gitlab.com/postgres-ai/joe/container_registry) for develop builds.
@@ -120,4 +28,4 @@ See our [GitLab Container Registry](https://gitlab.com/postgres-ai/joe/container
12028

12129
Bug reports, ideas, and merge requests are welcome: https://gitlab.com/postgres-ai/joe
12230

123-
To discuss Joe, join our Slack: https://database-lab-team-slack-invite.herokuapp.com/
31+
To discuss Joe, [join our community Slack](https://slack.postgres.ai/)

cmd/joe/main.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"net/http"
1414
"os"
1515
"os/signal"
16+
"path"
1617
"syscall"
1718
"time"
1819

@@ -30,9 +31,6 @@ import (
3031

3132
const (
3233
shutdownTimeout = 60 * time.Second
33-
34-
configFilePath = "config/config.yml"
35-
sessionsFilePath = "config/sessions.json"
3634
)
3735

3836
// ldflag variables.
@@ -41,7 +39,7 @@ var buildTime, version string
4139
func main() {
4240
version := formatBotVersion()
4341

44-
botCfg, err := loadConfig(configFilePath)
42+
botCfg, err := loadAppConfig()
4543
if err != nil {
4644
log.Fatal("failed to load config: ", err)
4745
}
@@ -60,7 +58,7 @@ func main() {
6058
ctx, cancel := context.WithCancel(context.Background())
6159
shutdownCh := setShutdownListener()
6260

63-
sessionsStorage := storage.NewJSONSessionData(sessionsFilePath)
61+
sessionsStorage := storage.NewJSONSessionData(path.Join(config.MetadataPath, config.SessionsFilename))
6462
if err := sessionsStorage.Load(); err != nil {
6563
log.Fatal("unable to load sessions data: ", err)
6664
}
@@ -87,8 +85,11 @@ func main() {
8785
}
8886
}
8987

90-
func loadConfig(configPath string) (*config.Config, error) {
91-
var botCfg config.Config
88+
func loadAppConfig() (*config.Config, error) {
89+
var (
90+
botCfg config.Config
91+
configPath = path.Join(config.ConfigsPath, config.AppFilename)
92+
)
9293

9394
if err := cleanenv.ReadConfig(configPath, &botCfg); err != nil {
9495
return nil, errors.Wrap(err, "failed to read a config file")

config/envs/default.sh

Lines changed: 0 additions & 16 deletions
This file was deleted.

config/config.example.yml renamed to configs/config.example.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Joe Bot configuration.
2-
# Copy this file to: ./config/config.yml
2+
# Copy this file to: ~/.dblab/joe/configs/joe.yml
33

44
app:
55
# HTTP server IP address or host.
File renamed without changes.

do.sh

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,6 @@ run() {
1010

1111
set +x
1212

13-
# Instead of editing default values here create a separate config file.
14-
# e.g. for staging environment create a file /deploy/configs/staging.sh
15-
# use `export` to define variables and run with `ENV=staging makerun.sh`.
16-
if [ -z ${ENV+x} ]; then
17-
echo "Using default variables"
18-
source ./config/envs/default.sh
19-
else
20-
source ./config/envs/${ENV}.sh
21-
fi
22-
2313
# Read and set git status info if it wasn't done before.
2414
if [ "$INCLUDE_GIT_STATUS" == "true" ] && [ -z "$GIT_COMMIT_HASH" ]; then
2515
echo "Fetching git status..."

pkg/config/config.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ import (
1212
"gitlab.com/postgres-ai/joe/pkg/pgexplain"
1313
)
1414

15+
const (
16+
// ConfigsPath declares the directory where configuration files are stored.
17+
ConfigsPath = "configs"
18+
19+
// AppFilename declares name of the application configuration file.
20+
AppFilename = "joe.yml"
21+
22+
// MetadataPath declares path where metadata files are stored.
23+
MetadataPath = "meta"
24+
25+
// SessionsFilename declares name of the file that stores current Joe Bot sessions.
26+
SessionsFilename = "sessions.json"
27+
)
28+
1529
// Config defines an App configuration.
1630
type Config struct {
1731
App App `yaml:"app"`

pkg/config/pgexplain.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package config
77
import (
88
"io/ioutil"
99
"os"
10+
"path"
1011
"path/filepath"
1112

1213
"github.com/pkg/errors"
@@ -15,19 +16,32 @@ import (
1516
"gitlab.com/postgres-ai/joe/pkg/pgexplain"
1617
)
1718

19+
const (
20+
// explainPath declares the directory where explain config files are stored.
21+
explainPath = "explain"
22+
23+
// explainFilename declares name of explain configuration file.
24+
explainFilename = "explain.yaml"
25+
)
26+
1827
// LoadExplainConfig loads and parses an explain configuration.
1928
func LoadExplainConfig() (pgexplain.ExplainConfig, error) {
2029
var explainConfig pgexplain.ExplainConfig
2130

22-
if err := loadConfig(&explainConfig, "explain.yaml"); err != nil {
31+
if err := readConfig(&explainConfig, path.Join(explainPath, explainFilename)); err != nil {
2332
return explainConfig, err
2433
}
2534

2635
return explainConfig, nil
2736
}
2837

29-
func loadConfig(config interface{}, name string) error {
30-
b, err := ioutil.ReadFile(getConfigPath(name))
38+
func readConfig(config interface{}, name string) error {
39+
cfgPath, err := getConfigPath(name)
40+
if err != nil {
41+
return errors.Wrap(err, "failed to build config path")
42+
}
43+
44+
b, err := ioutil.ReadFile(cfgPath)
3145
if err != nil {
3246
return errors.Errorf("Error loading %s config file: %v", name, err)
3347
}
@@ -39,10 +53,16 @@ func loadConfig(config interface{}, name string) error {
3953
return nil
4054
}
4155

42-
func getConfigPath(name string) string {
43-
bindir, _ := filepath.Abs(filepath.Dir(os.Args[0]))
44-
dir, _ := filepath.Abs(filepath.Dir(bindir))
45-
path := dir + string(os.PathSeparator) + "config" + string(os.PathSeparator) + name
56+
func getConfigPath(name string) (string, error) {
57+
binDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
58+
if err != nil {
59+
return "", err
60+
}
61+
62+
dir, err := filepath.Abs(filepath.Dir(binDir))
63+
if err != nil {
64+
return "", err
65+
}
4666

47-
return path
67+
return path.Join(dir, name), nil
4868
}

0 commit comments

Comments
 (0)