Permalink
Browse files

refactor

  • Loading branch information...
kcq committed Aug 19, 2017
1 parent df6d52c commit 57ca3111c1047bc5f87407575002bea4643848d7
Showing with 231 additions and 232 deletions.
  1. +4 −4 README.md
  2. +2 −147 cmd/docker-slim-sensor/main.go
  3. +5 −2 cmd/docker-slim/main.go
  4. 0 {sample → examples}/apps/java_ubuntu/Dockerfile
  5. 0 {sample → examples}/apps/java_ubuntu/docker.build.command
  6. 0 {sample → examples}/apps/java_ubuntu/docker.run.command
  7. 0 {sample → examples}/apps/java_ubuntu/jar.build.command
  8. 0 {sample → examples}/apps/java_ubuntu/pom.xml
  9. BIN {sample → examples}/apps/java_ubuntu/service.keystore
  10. 0 {sample → examples}/apps/java_ubuntu/service.yml
  11. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/AppConfiguration.java
  12. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/JavaApplication.java
  13. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/api/Saying.java
  14. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/core/Template.java
  15. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/health/TemplateHealthCheck.java
  16. 0 {sample → examples}/apps/java_ubuntu/src/main/java/my/resources/AppResource.java
  17. 0 {sample → examples}/apps/java_ubuntu/src/main/resources/banner.txt
  18. 0 {sample → examples}/apps/node_alpine/.dockerignore
  19. 0 {sample → examples}/apps/node_alpine/Dockerfile
  20. 0 {sample → examples}/apps/node_alpine/build.command
  21. 0 {sample → examples}/apps/node_alpine/run.command
  22. 0 {sample → examples}/apps/node_alpine/service/package.json
  23. 0 {sample → examples}/apps/node_alpine/service/server.js
  24. 0 {sample → examples}/apps/node_alpine/slim.command
  25. 0 {sample → examples}/apps/node_jessie/Dockerfile
  26. 0 {sample → examples}/apps/node_jessie/build.command
  27. 0 {sample → examples}/apps/node_jessie/run.command
  28. 0 {sample → examples}/apps/node_jessie/service/docker-entrypoint.sh
  29. 0 {sample → examples}/apps/node_jessie/service/package.json
  30. 0 {sample → examples}/apps/node_jessie/service/server.js
  31. 0 {sample → examples}/apps/node_jessie/slim.command
  32. 0 {sample → examples}/apps/node_ubuntu/.dockerignore
  33. 0 {sample → examples}/apps/node_ubuntu/Dockerfile
  34. 0 {sample → examples}/apps/node_ubuntu/build.command
  35. 0 {sample → examples}/apps/node_ubuntu/run.command
  36. 0 {sample → examples}/apps/node_ubuntu/service/package.json
  37. 0 {sample → examples}/apps/node_ubuntu/service/server.js
  38. 0 {sample → examples}/apps/node_ubuntu/slim.command
  39. 0 {sample → examples}/apps/python_alpine/.dockerignore
  40. 0 {sample → examples}/apps/python_alpine/Dockerfile
  41. 0 {sample → examples}/apps/python_alpine/README.md
  42. 0 {sample → examples}/apps/python_alpine/build.command
  43. 0 {sample → examples}/apps/python_alpine/run.command
  44. 0 {sample → examples}/apps/python_alpine/service/requirements.txt
  45. 0 {sample → examples}/apps/python_alpine/service/server.py
  46. 0 {sample → examples}/apps/python_alpine/slim.command
  47. 0 {sample → examples}/apps/python_gunicorn_ubuntu/.dockerignore
  48. 0 {sample → examples}/apps/python_gunicorn_ubuntu/Dockerfile
  49. 0 {sample → examples}/apps/python_gunicorn_ubuntu/Dockerfile.dbg
  50. 0 {sample → examples}/apps/python_gunicorn_ubuntu/Dockerfile.dbgrun
  51. 0 {sample → examples}/apps/python_gunicorn_ubuntu/Dockerfile.simple
  52. 0 {sample → examples}/apps/python_gunicorn_ubuntu/README.md
  53. 0 {sample → examples}/apps/python_gunicorn_ubuntu/build.command
  54. 0 {sample → examples}/apps/python_gunicorn_ubuntu/build.dbg.command
  55. 0 {sample → examples}/apps/python_gunicorn_ubuntu/build.dbgrun.command
  56. 0 {sample → examples}/apps/python_gunicorn_ubuntu/build.simple.command
  57. 0 {sample → examples}/apps/python_gunicorn_ubuntu/run.command
  58. 0 {sample → examples}/apps/python_gunicorn_ubuntu/service/requirements.txt
  59. 0 {sample → examples}/apps/python_gunicorn_ubuntu/service/run.sh
  60. 0 {sample → examples}/apps/python_gunicorn_ubuntu/service/server.py
  61. 0 {sample → examples}/apps/python_gunicorn_ubuntu/slim.command
  62. 0 {sample → examples}/apps/python_gunicorn_ubuntu/slim.simple.command
  63. 0 {sample → examples}/apps/python_ubuntu/.dockerignore
  64. 0 {sample → examples}/apps/python_ubuntu/Dockerfile
  65. 0 {sample → examples}/apps/python_ubuntu/README.md
  66. 0 {sample → examples}/apps/python_ubuntu/build.command
  67. 0 {sample → examples}/apps/python_ubuntu/run.command
  68. 0 {sample → examples}/apps/python_ubuntu/service/requirements.txt
  69. 0 {sample → examples}/apps/python_ubuntu/service/server.py
  70. 0 {sample → examples}/apps/python_ubuntu/slim.command
  71. 0 {sample → examples}/apps/ruby_alpine/.dockerignore
  72. 0 {sample → examples}/apps/ruby_alpine/Dockerfile
  73. 0 {sample → examples}/apps/ruby_alpine/README.md
  74. 0 {sample → examples}/apps/ruby_alpine/build.command
  75. 0 {sample → examples}/apps/ruby_alpine/run.command
  76. 0 {sample → examples}/apps/ruby_alpine/service/Gemfile
  77. 0 {sample → examples}/apps/ruby_alpine/service/server.rb
  78. 0 {sample → examples}/apps/ruby_alpine/slim.command
  79. 0 {sample → examples}/apps/ruby_ubuntu/.dockerignore
  80. 0 {sample → examples}/apps/ruby_ubuntu/Dockerfile
  81. 0 {sample → examples}/apps/ruby_ubuntu/README.md
  82. 0 {sample → examples}/apps/ruby_ubuntu/build.command
  83. 0 {sample → examples}/apps/ruby_ubuntu/run.command
  84. 0 {sample → examples}/apps/ruby_ubuntu/service/Gemfile
  85. 0 {sample → examples}/apps/ruby_ubuntu/service/server.rb
  86. 0 {sample → examples}/apps/ruby_ubuntu/slim.command
  87. 0 {sample → examples}/artifacts/Dockerfile.fat
  88. 0 {sample → examples}/artifacts/creport.json
  89. 0 {sample → examples}/artifacts/my-sample-node-app-apparmor-profile
  90. 0 {sample → examples}/artifacts/my-sample-node-app-seccomp.json
  91. +7 −0 internal/app/master/app.go
  92. +2 −2 { → internal/app}/master/builder/image_builder.go
  93. +3 −3 {cmd/docker-slim → internal/app/master}/cli.go
  94. +6 −6 { → internal/app}/master/commands/build.go
  95. +3 −3 { → internal/app}/master/commands/info.go
  96. +5 −5 { → internal/app}/master/commands/profile.go
  97. +2 −2 { → internal/app}/master/commands/version.go
  98. 0 { → internal/app}/master/config/config.go
  99. +1 −1 { → internal/app}/master/docker/dockerclient/client.go
  100. 0 { → internal/app}/master/docker/dockerfile/dockerfile.go
  101. 0 { → internal/app}/master/docker/dockerhost/host.go
  102. +8 −8 { → internal/app}/master/inspectors/container/container_inspector.go
  103. +1 −1 { → internal/app}/master/inspectors/container/ipc/ipc.go
  104. +2 −2 { → internal/app}/master/inspectors/container/probes/http/custom_probe.go
  105. +1 −1 { → internal/app}/master/inspectors/image/image_inspector.go
  106. +2 −2 {cmd/docker-slim → internal/app/master}/opts.go
  107. +1 −1 { → internal/app}/master/security/apparmor/apparmor.go
  108. +2 −2 { → internal/app}/master/security/seccomp/seccomp.go
  109. +1 −1 {cmd/docker-slim → internal/app/master}/signals.go
  110. +155 −0 internal/app/sensor/app.go
  111. +3 −3 {cmd/docker-slim-sensor → internal/app/sensor}/artifacts.go
  112. +2 −2 {cmd/docker-slim-sensor → internal/app/sensor}/cleanup.go
  113. +4 −4 {cmd/docker-slim-sensor → internal/app/sensor}/data_porcessor.go
  114. +1 −1 { → internal/app}/sensor/ipc/ipc.go
  115. +1 −1 { → internal/app}/sensor/monitors/fanotify/monitor.go
  116. +1 −1 { → internal/app}/sensor/monitors/pevent/monitor.go
  117. +2 −2 { → internal/app}/sensor/monitors/ptrace/monitor.go
  118. +1 −1 {cmd/docker-slim-sensor → internal/app/sensor}/signals.go
  119. 0 { → internal/app}/sensor/target/target_app.go
  120. 0 { → pkg}/consts/version.go
  121. 0 { → pkg}/messages/messages.go
  122. 0 { → pkg}/report/container_report.go
  123. 0 {external → pkg/third_party}/opencontainers/specs/seccomp.go
  124. +1 −1 pkg/version/version.go
  125. +1 −10 scripts/src.fmt.sh
  126. +1 −13 scripts/src.inspect.sh
View
@@ -134,9 +134,9 @@ The demo run on Mac OS X, but you can build a linux version. Note that these ste
`git clone https://github.com/docker-slim/docker-slim.git`
3. Create a Docker image for the sample node.js app in `sample/apps/node`. You can skip this step if you have your own app.
3. Create a Docker image for the sample node.js app in `examples/apps/node_ubuntu`. You can skip this step if you have your own app.
`cd docker-slim/sample/apps/node`
`cd docker-slim/examples/apps/node_ubuntu`
`eval "$(docker-machine env default)"` <- optional (depends on how Docker is installed on your machine); if the Docker host is not running you'll need to start it first: `docker-machine start default`; see the `Docker connect options` section for more details.
@@ -304,7 +304,7 @@ It's used to minify the `container-transform` tool. You can get the minified ima
## CURRENT STATE
It works pretty well with the sample Node.js, Python (2 and 3), Ruby and Java images (built from `sample/apps`). More testing needs to be done to see how it works with other images. Rails/unicorn app images are not fully supported yet (WIP).
It works pretty well with the sample Node.js, Python (2 and 3), Ruby and Java images (built from `examples/apps`). More testing needs to be done to see how it works with other images. Rails/unicorn app images are not fully supported yet (WIP).
Sample images (built with the standard Ubuntu 14.04 base image):
@@ -350,7 +350,7 @@ Notes:
You can explore the artifacts DockerSlim generates when it's creating a slim image. You'll find those in `<docker-slim directory>/.images/<TARGET_IMAGE_ID>/artifacts`. One of the artifacts is a "reverse engineered" Dockerfile for the original image. It'll be called `Dockerfile.fat`.
If you'd like to see the artifacts without running `docker-slim` you can take a look at the `sample/artifacts` directory in this repo. It doesn't include any image files, but you'll find:
If you'd like to see the artifacts without running `docker-slim` you can take a look at the `examples/artifacts` directory in this repo. It doesn't include any image files, but you'll find:
* a reverse engineered Dockerfile (`Dockerfile.fat`)
* a container report file (`creport.json`)
@@ -1,154 +1,9 @@
package main
import (
"flag"
"os"
"time"
"github.com/docker-slim/docker-slim/messages"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
"github.com/docker-slim/docker-slim/report"
"github.com/docker-slim/docker-slim/sensor/ipc"
"github.com/docker-slim/docker-slim/sensor/monitors/fanotify"
"github.com/docker-slim/docker-slim/sensor/monitors/pevent"
"github.com/docker-slim/docker-slim/sensor/monitors/ptrace"
log "github.com/Sirupsen/logrus"
"github.com/cloudimmunity/system"
"github.com/docker-slim/docker-slim/internal/app/sensor"
)
var doneChan chan struct{}
///////////////////////////////////////////////////////////////////////////////
func monitor(stopWork chan bool,
stopWorkAck chan bool,
pids chan []int,
ptmonStartChan chan int,
cmd *messages.StartMonitor,
dirName string) {
log.Info("sensor: monitor starting...")
mountPoint := "/"
stopMonitor := make(chan struct{})
var peReportChan <-chan *report.PeMonitorReport
var peReport *report.PeMonitorReport
usePEMon, err := system.DefaultKernelFeatures.IsCompiled("CONFIG_PROC_EVENTS")
//tmp: disalbe PEVENTs (due to problems with the new boot2docker host OS)
usePEMon = false
if (err == nil) && usePEMon {
log.Info("sensor: proc events are available!")
peReportChan = pevent.Run(stopMonitor)
//ProcEvents are not enabled in the default boot2docker kernel
}
fanReportChan := fanotify.Run(mountPoint, stopMonitor) //data.AppName, data.AppArgs
ptReportChan := ptrace.Run(ptmonStartChan, stopMonitor, cmd.AppName, cmd.AppArgs, dirName)
go func() {
log.Debug("sensor: monitor - waiting to stop monitoring...")
<-stopWork
log.Debug("sensor: monitor - stop message...")
close(stopMonitor)
log.Debug("sensor: monitor - processing data...")
fanReport := <-fanReportChan
ptReport := <-ptReportChan
if peReportChan != nil {
peReport = <-peReportChan
//TODO: when peReport is available filter file events from fanReport
}
processReports(mountPoint, fanReport, ptReport, peReport, cmd)
stopWorkAck <- true
}()
}
/////////
var enableDebug bool
func init() {
flag.BoolVar(&enableDebug, "d", false, "enable debug logging")
}
/////////
func main() {
flag.Parse()
if enableDebug {
log.SetLevel(log.DebugLevel)
}
log.Infof("sensor: args => %#v", os.Args)
dirName, err := os.Getwd()
errutils.WarnOn(err)
log.Debugf("sensor: cwd => %#v", dirName)
initSignalHandlers()
defer func() {
log.Debug("defered cleanup on shutdown...")
cleanupOnShutdown()
}()
log.Debug("sensor: setting up channels...")
doneChan = make(chan struct{})
err = ipc.InitChannels()
errutils.FailOn(err)
cmdChan, err := ipc.RunCmdServer(doneChan)
errutils.FailOn(err)
monDoneChan := make(chan bool, 1)
monDoneAckChan := make(chan bool)
pidsChan := make(chan []int, 1)
ptmonStartChan := make(chan int, 1)
log.Info("sensor: waiting for commands...")
doneRunning:
for {
select {
case cmd := <-cmdChan:
log.Debug("\nsensor: command => ", cmd)
switch data := cmd.(type) {
case *messages.StartMonitor:
if data == nil {
log.Info("sensor: 'start' command - no data...")
break
}
log.Debugf("sensor: 'start' command (%#v) - starting monitor...", data)
monitor(monDoneChan, monDoneAckChan, pidsChan, ptmonStartChan, data, dirName)
//target app started by ptmon... (long story :-))
//TODO: need to get the target app pid to pemon, so it can filter process events
log.Debugf("sensor: target app started => %v %#v", data.AppName, data.AppArgs)
time.Sleep(3 * time.Second)
case *messages.StopMonitor:
log.Debug("sensor: 'stop' command - stopping monitor...")
break doneRunning
default:
log.Debug("sensor: ignoring unknown command => ", cmd)
}
case <-time.After(time.Second * 5):
log.Debug(".")
}
}
monDoneChan <- true
log.Info("sensor: waiting for monitor to finish...")
<-monDoneAckChan
ipc.TryPublishEvt(3, "monitor.finish.completed")
log.Info("sensor: done!")
app.Run()
}
View
@@ -1,6 +1,9 @@
package main
import (
"github.com/docker-slim/docker-slim/internal/app/master"
)
func main() {
initSignalHandlers()
runCli()
app.Run()
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,7 @@
package app
// Run starts the master app
func Run() {
initSignalHandlers()
runCli()
}
@@ -4,8 +4,8 @@ import (
"os"
"path/filepath"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerfile"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerfile"
"github.com/docker-slim/docker-slim/pkg/utils/fsutils"
//log "github.com/Sirupsen/logrus"
@@ -1,13 +1,13 @@
package main
package app
import (
"fmt"
"os"
"strconv"
"time"
"github.com/docker-slim/docker-slim/master/commands"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/commands"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/pkg/version"
log "github.com/Sirupsen/logrus"
@@ -6,12 +6,12 @@ import (
"os"
"time"
"github.com/docker-slim/docker-slim/master/builder"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/master/inspectors/container"
"github.com/docker-slim/docker-slim/master/inspectors/container/probes/http"
"github.com/docker-slim/docker-slim/master/inspectors/image"
"github.com/docker-slim/docker-slim/internal/app/master/builder"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container/probes/http"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/image"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
"github.com/docker-slim/docker-slim/pkg/utils/fsutils"
"github.com/docker-slim/docker-slim/pkg/version"
@@ -3,9 +3,9 @@ package commands
import (
"fmt"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/master/inspectors/image"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/image"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
"github.com/docker-slim/docker-slim/pkg/utils/fsutils"
@@ -6,11 +6,11 @@ import (
"os"
"time"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/master/inspectors/container"
"github.com/docker-slim/docker-slim/master/inspectors/container/probes/http"
"github.com/docker-slim/docker-slim/master/inspectors/image"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container/probes/http"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/image"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
"github.com/docker-slim/docker-slim/pkg/utils/fsutils"
"github.com/docker-slim/docker-slim/pkg/version"
@@ -3,8 +3,8 @@ package commands
import (
"fmt"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerclient"
"github.com/docker-slim/docker-slim/pkg/version"
)
File renamed without changes.
@@ -6,7 +6,7 @@ import (
"path/filepath"
"github.com/cloudimmunity/go-dockerclientx"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
log "github.com/Sirupsen/logrus"
@@ -8,16 +8,16 @@ import (
"path/filepath"
"time"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/docker/dockerhost"
"github.com/docker-slim/docker-slim/master/inspectors/container/ipc"
"github.com/docker-slim/docker-slim/master/inspectors/image"
"github.com/docker-slim/docker-slim/master/security/apparmor"
"github.com/docker-slim/docker-slim/master/security/seccomp"
"github.com/docker-slim/docker-slim/messages"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerhost"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container/ipc"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/image"
"github.com/docker-slim/docker-slim/internal/app/master/security/apparmor"
"github.com/docker-slim/docker-slim/internal/app/master/security/seccomp"
"github.com/docker-slim/docker-slim/pkg/messages"
"github.com/docker-slim/docker-slim/pkg/report"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
"github.com/docker-slim/docker-slim/pkg/utils/fsutils"
"github.com/docker-slim/docker-slim/report"
log "github.com/Sirupsen/logrus"
dockerapi "github.com/cloudimmunity/go-dockerclientx"
@@ -11,7 +11,7 @@ import (
//"github.com/go-mangos/mangos/transport/ipc"
"github.com/go-mangos/mangos/transport/tcp"
"github.com/docker-slim/docker-slim/messages"
"github.com/docker-slim/docker-slim/pkg/messages"
)
// InitContainerChannels initializes the communication channels with the target container
@@ -4,8 +4,8 @@ import (
"fmt"
"time"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/master/inspectors/container"
"github.com/docker-slim/docker-slim/internal/app/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/inspectors/container"
log "github.com/Sirupsen/logrus"
"github.com/franela/goreq"
@@ -5,7 +5,7 @@ import (
"path/filepath"
"strings"
"github.com/docker-slim/docker-slim/master/docker/dockerfile"
"github.com/docker-slim/docker-slim/internal/app/master/docker/dockerfile"
"github.com/docker-slim/docker-slim/pkg/utils/errutils"
log "github.com/Sirupsen/logrus"
@@ -1,4 +1,4 @@
package main
package app
import (
"encoding/json"
@@ -13,7 +13,7 @@ import (
"github.com/cloudimmunity/go-dockerclientx"
"github.com/docker/go-connections/nat"
"github.com/docker-slim/docker-slim/master/config"
"github.com/docker-slim/docker-slim/internal/app/master/config"
)
//based on expose opt parsing in Docker
@@ -6,7 +6,7 @@ import (
"path/filepath"
"text/template"
"github.com/docker-slim/docker-slim/report"
"github.com/docker-slim/docker-slim/pkg/report"
)
const appArmorTemplate = `
@@ -6,8 +6,8 @@ import (
"os"
"path/filepath"
"github.com/docker-slim/docker-slim/external/opencontainers/specs"
"github.com/docker-slim/docker-slim/report"
"github.com/docker-slim/docker-slim/pkg/report"
"github.com/docker-slim/docker-slim/pkg/third_party/opencontainers/specs"
log "github.com/Sirupsen/logrus"
"github.com/cloudimmunity/system"
@@ -1,4 +1,4 @@
package main
package app
import (
"os"
Oops, something went wrong.

0 comments on commit 57ca311

Please sign in to comment.