Skip to content

Commit

Permalink
Display Service Environment configuration in RHS (#143)
Browse files Browse the repository at this point in the history
This change is the first step in better handling of service
environment configuration in the plugin. The installation environment
variables are now examined to expose which service environment
value the test server will use. This is displayed in the plugin RHS.
The creation date of the server is now also displayed for
informational purposes.
  • Loading branch information
gabrieljackson authored Nov 8, 2023
1 parent 46a185a commit b3eb328
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 18 deletions.
31 changes: 28 additions & 3 deletions server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import (
"encoding/json"
"net/http"

cloud "github.com/mattermost/mattermost-cloud/model"
"github.com/mattermost/mattermost-server/v6/plugin"
"github.com/pkg/errors"
)

const serviceEnvironmentEnvVarKey = "MM_SERVICEENVIRONMENT"

// InstallationWebWrapper embeds the standard plugin installation object with
// some extra ephemeral fields used in the webapp.
type InstallationWebWrapper struct {
*Installation
CreateAtDate string
ServiceEnvironment string
InstallationLogsURL string
ProvisionerLogsURL string
}
Expand All @@ -29,7 +34,16 @@ func CreateInstallationWebWrapper(i *Installation) (*InstallationWebWrapper, err
return nil, err
}

return &InstallationWebWrapper{i, installationLogsURL, provisionerLogsURL}, nil
serviceEnvironment := getInstallationServiceEnvironment(i)
i.HideSensitiveFields()

return &InstallationWebWrapper{
Installation: i,
CreateAtDate: cloud.DateStringFromMillis(i.CreateAt),
ServiceEnvironment: serviceEnvironment,
InstallationLogsURL: installationLogsURL,
ProvisionerLogsURL: provisionerLogsURL,
}, nil
}

// ServeHTTP handles HTTP requests to the plugin.
Expand Down Expand Up @@ -89,9 +103,9 @@ func (p *Plugin) handleUserInstalls(w http.ResponseWriter, r *http.Request) {
return
}

installsForUser, err := p.getUpdatedInstallsForUser(req.UserID)
installsForUser, err := p.getUpdatedInstallsForUserWithSensitive(req.UserID)
if err != nil {
p.API.LogError(errors.Wrap(err, "Unable to getUpdatedInstallsForUser").Error())
p.API.LogError(errors.Wrap(err, "Unable to getUpdatedInstallsForUserWithSensitive").Error())
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}
Expand Down Expand Up @@ -201,3 +215,14 @@ func (p *Plugin) handleGetConfig(w http.ResponseWriter, r *http.Request) {
}
w.Write(data)
}

func getInstallationServiceEnvironment(installation *Installation) string {
if v, ok := installation.PriorityEnv[serviceEnvironmentEnvVarKey]; ok {
return v.Value
}
if v, ok := installation.MattermostEnv[serviceEnvironmentEnvVarKey]; ok {
return v.Value
}

return "production"
}
8 changes: 4 additions & 4 deletions server/command_deletion_lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func (p *Plugin) lockForDeletion(installationID string, userID string) error {
if installationID == "" {
return errors.New("installationID must not be empty")
}
installations, err := p.getUpdatedInstallsForUser(userID)
installations, err := p.getUpdatedInstallsForUserWithoutSensitive(userID)
if err != nil {
return err
}
Expand Down Expand Up @@ -55,7 +55,7 @@ func (p *Plugin) unlockForDeletion(installationID string, userID string) error {
return errors.New("installationID must not be empty")
}

installations, err := p.getUpdatedInstallsForUser(userID)
installations, err := p.getUpdatedInstallsForUserWithoutSensitive(userID)
if err != nil {
return err
}
Expand Down Expand Up @@ -87,7 +87,7 @@ func (p *Plugin) runDeletionLockCommand(args []string, extra *model.CommandArgs)

name := standardizeName(args[0])

installations, err := p.getUpdatedInstallsForUser(extra.UserId)
installations, err := p.getUpdatedInstallsForUserWithoutSensitive(extra.UserId)
if err != nil {
return nil, true, err
}
Expand Down Expand Up @@ -118,7 +118,7 @@ func (p *Plugin) runDeletionUnlockCommand(args []string, extra *model.CommandArg

name := standardizeName(args[0])

installs, err := p.getUpdatedInstallsForUser(extra.UserId)
installs, err := p.getUpdatedInstallsForUserWithoutSensitive(extra.UserId)
if err != nil {
return nil, false, err
}
Expand Down
2 changes: 1 addition & 1 deletion server/command_hibernate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (p *Plugin) runHibernateCommand(args []string, extra *model.CommandArgs) (*

name := standardizeName(args[0])

installs, err := p.getUpdatedInstallsForUser(extra.UserId)
installs, err := p.getUpdatedInstallsForUserWithoutSensitive(extra.UserId)
if err != nil {
return nil, false, err
}
Expand Down
24 changes: 18 additions & 6 deletions server/command_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func (p *Plugin) runListCommand(args []string, extra *model.CommandArgs) (*model.CommandResponse, bool, error) {
installsForUser, err := p.getUpdatedInstallsForUser(extra.UserId)
installsForUser, err := p.getUpdatedInstallsForUserWithoutSensitive(extra.UserId)
if err != nil {
return nil, false, err
}
Expand All @@ -27,7 +27,15 @@ func (p *Plugin) runListCommand(args []string, extra *model.CommandArgs) (*model
return getCommandResponse(model.CommandResponseTypeEphemeral, jsonCodeBlock(prettyPrintJSON(string(data))), extra), false, nil
}

func (p *Plugin) getUpdatedInstallsForUser(userID string) ([]*Installation, error) {
func (p *Plugin) getUpdatedInstallsForUserWithSensitive(userID string) ([]*Installation, error) {
return p.getUpdatedInstallsForUser(userID, false)
}

func (p *Plugin) getUpdatedInstallsForUserWithoutSensitive(userID string) ([]*Installation, error) {
return p.getUpdatedInstallsForUser(userID, true)
}

func (p *Plugin) getUpdatedInstallsForUser(userID string, hideSensitive bool) ([]*Installation, error) {
pluginInstalls, err := p.getInstallationsForUser(userID)
if err != nil {
return nil, err
Expand All @@ -47,7 +55,7 @@ func (p *Plugin) getUpdatedInstallsForUser(userID string) ([]*Installation, erro

var deleted bool
for i, pluginInstall := range pluginInstalls {
deleted, err = p.processInstallationUpdate(pluginInstall, cloudInstalls)
deleted, err = p.processInstallationUpdate(pluginInstall, cloudInstalls, hideSensitive)
if err != nil {
return nil, errors.Wrap(err, "unable to process installation")
}
Expand All @@ -64,11 +72,13 @@ func (p *Plugin) getUpdatedInstallsForUser(userID string) ([]*Installation, erro
return pluginInstalls, nil
}

func (p *Plugin) processInstallationUpdate(pluginInstall *Installation, cloudInstalls []*cloud.InstallationDTO) (bool, error) {
func (p *Plugin) processInstallationUpdate(pluginInstall *Installation, cloudInstalls []*cloud.InstallationDTO, hideSensitive bool) (bool, error) {
for _, cloudInstall := range cloudInstalls {
if pluginInstall.ID == cloudInstall.ID {
pluginInstall.InstallationDTO = *cloudInstall
pluginInstall.HideSensitiveFields()
if hideSensitive {
pluginInstall.HideSensitiveFields()
}
return false, nil
}
}
Expand All @@ -87,7 +97,9 @@ func (p *Plugin) processInstallationUpdate(pluginInstall *Installation, cloudIns
}

pluginInstall.Installation = updatedInstall.Installation
pluginInstall.HideSensitiveFields()
if hideSensitive {
pluginInstall.HideSensitiveFields()
}

if updatedInstall.State != cloud.InstallationStateDeleted {
// This is strange as the installation should have been retrieved in the
Expand Down
34 changes: 31 additions & 3 deletions server/command_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ func TestGetUpdatedInstallsForUser(t *testing.T) {
mockedCloudInstallationsDTO: []*cloud.InstallationDTO{
{
Installation: &cloud.Installation{
ID: "id1",
State: cloud.InstallationStateStable,
ID: "id1",
State: cloud.InstallationStateStable,
MattermostEnv: cloud.EnvVarMap{"secret": cloud.EnvVar{Value: "supersecret"}},
},
},
{
Expand Down Expand Up @@ -54,6 +55,33 @@ func TestGetUpdatedInstallsForUser(t *testing.T) {

plugin.SetAPI(api)

t.Run("test sensitivity", func(t *testing.T) {
pluginInstalls, installationBytes, err := getFakePluginInstallations()
require.NoError(t, err)
api.On("KVGet", mock.AnythingOfType("string")).Return(installationBytes, nil)
api.On("KVCompareAndSet", mock.AnythingOfType("string"), mock.Anything, mock.Anything).Return(true, nil)
api.On("GetDirectChannel", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(&model.Channel{}, nil)
api.On("CreatePost", mock.Anything).Return(nil, nil)
api.On("LogWarn", mock.AnythingOfTypeArgument("string")).Return(nil)

t.Run("with sensitive", func(t *testing.T) {
installations, err := plugin.getUpdatedInstallsForUserWithSensitive("owner 1")
require.NoError(t, err)
require.Equal(t, len(pluginInstalls), len(installations))
assert.Equal(t, "id1", installations[0].ID)
assert.NotNil(t, installations[0].MattermostEnv)
t.Log(installations[0].State)
})

t.Run("without sensitive", func(t *testing.T) {
installations, err := plugin.getUpdatedInstallsForUserWithoutSensitive("owner 1")
require.NoError(t, err)
require.Equal(t, len(pluginInstalls), len(installations))
assert.Equal(t, "id1", installations[0].ID)
assert.Nil(t, installations[0].MattermostEnv)
})
})

t.Run("test deleted installations", func(t *testing.T) {
pluginInstalls, installationBytes, err := getFakePluginInstallations()
require.NoError(t, err)
Expand All @@ -63,7 +91,7 @@ func TestGetUpdatedInstallsForUser(t *testing.T) {
api.On("CreatePost", mock.Anything).Return(nil, nil)
api.On("LogWarn", mock.AnythingOfTypeArgument("string")).Return(nil)

installations, err := plugin.getUpdatedInstallsForUser("owner 1")
installations, err := plugin.getUpdatedInstallsForUserWithoutSensitive("owner 1")
require.NoError(t, err)
require.Equal(t, len(pluginInstalls), len(installations))
assert.Equal(t, "id1", installations[0].ID)
Expand Down
2 changes: 1 addition & 1 deletion server/command_wakeup.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func (p *Plugin) runWakeUpCommand(args []string, extra *model.CommandArgs) (*mod

name := standardizeName(args[0])

installs, err := p.getUpdatedInstallsForUser(extra.UserId)
installs, err := p.getUpdatedInstallsForUserWithoutSensitive(extra.UserId)
if err != nil {
return nil, false, err
}
Expand Down
8 changes: 8 additions & 0 deletions webapp/src/components/sidebar_right/sidebar_right.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@ export default class SidebarRight extends React.PureComponent {
<span style={style.col1}>Size:</span>
<span>{install.Size}</span>
</div>
<div>
<span style={style.col1}>Service Env:</span>
<span>{install.ServiceEnvironment}</span>
</div>
<div>
<span style={style.col1}>Created:</span>
<span>{install.CreateAtDate}</span>
</div>
</div>
{this.installationButtons(install)}
</li>
Expand Down

0 comments on commit b3eb328

Please sign in to comment.