| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| package cmdutil | |
| import ( | |
| "crypto/tls" | |
| "crypto/x509" | |
| "errors" | |
| "fmt" | |
| "os" | |
| "strconv" | |
| "github.com/apache/doris-operator/pkg/common/cmd/types" | |
| "github.com/go-sql-driver/mysql" | |
| _ "github.com/go-sql-driver/mysql" | |
| "github.com/jmoiron/sqlx" | |
| ) | |
| // Client provides abstractions that access doris cluster methods. | |
| type Client interface { | |
| ShowFrontends() ([]*cmdtypes.Frontend, error) | |
| ShowBackends() ([]*cmdtypes.Backend, error) | |
| } | |
| var _ Client = &DorisClient{} | |
| type DorisClient struct { | |
| db *sqlx.DB | |
| } | |
| func NewDorisClient(dc *DorisConfig) (*DorisClient, error) { | |
| user := dc.User | |
| password := dc.Password | |
| host := dc.FeHost | |
| queryPort := strconv.Itoa(dc.QueryPort) | |
| dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", user, password, host, queryPort, "mysql") | |
| rootCertPool := x509.NewCertPool() | |
| if dc.SSLCaPath != "" { | |
| pem, err := os.ReadFile(dc.SSLCaPath) | |
| if err != nil { | |
| return nil, errors.New("read root ca cert failed," + err.Error()) | |
| } | |
| if ok := rootCertPool.AppendCertsFromPEM(pem); !ok { | |
| return nil, errors.New("Failed to append ca cert or pem failed.") | |
| } | |
| clientCerts := make([]tls.Certificate, 0, 1) | |
| cCert, err := tls.LoadX509KeyPair(dc.SSLCrtPath, dc.SSLKeyPath) | |
| if err != nil { | |
| return nil, errors.New("load x509 key pair failed," + err.Error()) | |
| } | |
| clientCerts = append(clientCerts, cCert) | |
| if err = mysql.RegisterTLSConfig("doris", &tls.Config{ | |
| RootCAs: rootCertPool, | |
| Certificates: clientCerts, | |
| }); err != nil { | |
| return nil, errors.New("register tls config failed," + err.Error()) | |
| } | |
| dsn = dsn + "?tls=doris" | |
| } | |
| db, err := sqlx.Open("mysql", dsn) | |
| if err != nil { | |
| return nil, errors.New("NewDorisSqlDB sqlx.Open failed open doris sql client connection, err: " + err.Error()) | |
| } | |
| return &DorisClient{ | |
| db: db, | |
| }, nil | |
| } | |
| func (dc *DorisClient) ShowFrontends() ([]*cmdtypes.Frontend, error) { | |
| if err := dc.db.Ping(); err != nil { | |
| return nil, err | |
| } | |
| var fs []*cmdtypes.Frontend | |
| if err := dc.db.Unsafe().Select(&fs, "show frontends"); err != nil { | |
| return fs, err | |
| } | |
| return fs, nil | |
| } | |
| func (dc *DorisClient) ShowBackends() ([]*cmdtypes.Backend, error) { | |
| if err := dc.db.Ping(); err != nil { | |
| return nil, err | |
| } | |
| var bs []*cmdtypes.Backend | |
| if err := dc.db.Unsafe().Select(&bs, "show backends"); err != nil { | |
| return bs, err | |
| } | |
| return bs, nil | |
| } |