پس از استخدام در پارک علم و فناوری پردیس، یکی از غولهای تکنولوژی کشور در یک حرکت خلاقانه و در راستای خودکفایی تصمیم گرفته یک پیادهسازی فان از Docker با نام Dockerious توسعه دهد. این پروژه به عنوان پروژه شما در دوران آزمایشی تعیین شده. در فاز اول شرکتکنندگان باید بخش هستهای و ابتدایی این ابزار را پیادهسازی کنند.
شما باید یک ابزار خط فرمان (CLI) ساده بسازید که بتواند دستورات سیستمعامل را (البته از لیست مجاز قرار داده شده در internal/commands/allowed.go) در پسزمینه اجرا کرده و وضعیت آنها را ترک کند.
جزئیات پروژه
پروژه اولیه را از این لینک دانلود کنید. ساختار پروژه به شکل زیر است:
├── cmd
│ ├── ps.go # TODO Implement
│ ├── root.go # TODO Implement
│ └── run.go # TODO Implement
├── go.mod
├── go.sum
├── internal
│ ├── commands
│ │ └── allowed.go
│ ├── db
│ │ └── database.go
│ ├── models
│ │ └── process.go
│ ├── monitor
│ │ └── monitor.go
│ └── types
│ └── status.go
├── main.go
در این پروژه، شما صرفا باید قسمتهای مشخص شده با // TODO را در دایرکتوری cmd پیادهسازی کنید. هدف اصلی، پیادهسازی منطق دو دستور اصلی dockerious run و dockerious ps است.
-
internal/commands/allowed.go: یکmapحاوی لیست دستورات مجاز (echo,ls,sleep,pwd) را تعریف میکند. -
internal/db/database.go: مسئولیت اتصال به پایگاهداده PostgreSQL را بر عهده دارد. -
internal/models/process.go: مدل GORM برای جدولprocessesرا تعریف میکند. -
internal/types/status.go: وضعیتهای مختلف یک پروسه (running,finished,failed) را به صورت ثابت تعریف میکند. -
internal/monitor/monitor.go: یک اینترفیس برای نظارت بر چرخه حیات پروسهها تعریف میکند. شما باید پیادهسازی آن را درcmd/run.goانجام دهید.
⚠️ نباید ساختار فایلهای داخل
internalرا تغییر دهید — فقطcmd/*.goقسمتهایی که// TODOدارند باید تکمیل شوند.
مدل پایگاهداده
ساختار جدول processes در پایگاهداده که مدل آن در models/process.go تعریف شده، به شرح زیر است:
| فیلد | تایپ | توضیحات |
|---|---|---|
ID |
uint |
کلید اصلی AUTO_INCREMENT |
PID |
int |
شناسهی پروسه که سیستمعامل برمیگرداند |
Command |
string |
دستور کامل اجرا شده |
Status |
string |
وضعیت پروسه (running، finished، failed) |
CreatedAt |
time.Time |
زمان ایجاد رکورد |
UpdatedAt |
time.Time |
زمان آخرین بهروزرسانی رکورد |
DeletedAt |
time.Time |
زمان حذف رکورد |
دستورات خط فرمان
شما باید توابع و متدهای خالی مشخصشده با // TODO را در فایلهای cmd/root.go، cmd/run.go و cmd/ps.go کامل کنید.
فایل cmd/root.go
cmd/root.goتوضیح: این فایل مسئول راهاندازی ساختار اصلی CLI است. شما باید دستورات فرزند را به دستور ریشه متصل کرده و نقطهی ورود برنامه را تکمیل کنید.
نیازمندیها:
-
func init(): در این تابع، باید دستوراتrunCmdوpsCmdرا به عنوان فرزند بهrootCmdاضافه کنید. -
func Execute(): این تابع که ازmain.goفراخوانی میشود، بایدrootCmdرا اجرا کرده و خطاهای احتمالی را مدیریت کند. -
func GetRootCmdForTest(): این تابع در تستها استفاده میشود و شما نباید آن را ویرایش کنید!
فایل cmd/run.go
cmd/run.goتوضیح: این فایل منطق اصلی اجرای یک پروسه جدید را در خود جای داده است.
نیازمندیها:
-
struct AsyncProcessMonitor: شما باید اینstructرا به گونهای پیادهسازی کنید که اینترفیسmonitor.ProcessMonitorرا ارضا کند. -
func (dpm *AsyncProcessMonitor) MonitorProcess(...): این متد باید یک گوروتین اجرا کند. این گوروتین باید منتظر بماند تا پروسهی ورودی (proc) تمام شود و سپس وضعیت رکورد متناظر با آنpidرا در دیتابیس بهtypes.StatusFinishedتغییر دهد. -
var runCmd = &cobra.Command{...}: در تابعRunاین دستور، باید منطق کامل زیر را پیادهسازی کنید:- بررسی Whitelist: چک کنید که آیا فرمان ورودی در
commands.AllowedCommandsوجود دارد یا خیر. در صورت عدم وجود، اگر دستور مجاز نباشد، باید خطا را به شکل زیر چاپ کنید و هیچ رکوردی هم در دیتابیس ذخیره نشود:
- بررسی Whitelist: چک کنید که آیا فرمان ورودی در
[Dockerious] Error: Command '<command>' is not allowed.
-
آرگومانها: اگر بدون هیچ آرگومانی صدا زده شود، باید خطای پیشفرض (
requires at least 1 arg(s)) بازگردانده شود. -
اجرای پروسه: با استفاده از
os/execو متدStart()، پروسه را در پسزمینه اجرا کنید.- ثبت در دیتابیس: یک رکورد جدید برای پروسه در دیتابیس با وضعیت
types.StatusRunningایجاد کنید. - چاپ خروجی موفقیت: پس از اجرای موفق، پیام زیر چاپ شود:
- ثبت در دیتابیس: یک رکورد جدید برای پروسه در دیتابیس با وضعیت
[Dockerious] Started process "<command and args>" with PID: <pid>
- شروع نظارت: با استفاده از
monitor.GetProcessMonitor()، متدMonitorProcessرا برای پروسهی جدید فراخوانی کنید تا وضعیت آن پس از اتمام، به صورت خودکار آپدیت شود.
فایل cmd/ps.go
cmd/ps.goتوضیح: این دستور برای نمایش لیست پروسههای در حال اجرا و اصلاح وضعیت رکوردهای تاریخگذشته است.
نیازمندیها:
-
var psCmd = &cobra.Command{...}: در تابعRunاین دستور، باید منطق کامل زیر را پیادهسازی کنید:-
واکشی از دیتابیس: تمام پروسههایی که وضعیت آنها
types.StatusRunningاست را از دیتابیس بخوانید. -
منطق Reconciliation: برای هر پروسه، با استفاده از
os.FindProcessو ارسال سیگنال0، بررسی کنید که آیا واقعاً در سیستمعامل در حال اجراست یا خیر. -
آپدیت وضعیت: اگر پروسهای در سیستمعامل وجود نداشت، وضعیت آن را در دیتابیس با فراخوانی تابع
updateStatusToFinishedبهروز کنید و دیگر در خروجی نمایش داده نشود. -
چاپ خروجی: لیست نهایی پروسههایی که واقعاً در حال اجرا هستند را در قالب یک جدول مرتب چاپ کنید.
-
-
برای فرمت جدول میتوانید از خط زیر کمک بگیرید:
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', tabwriter.TabIndent)
fmt.Fprintln(w, "ID\tPID\tSTATUS\tCOMMAND")
خروجی باید همیشه با هدر زیر شروع شود:
ID PID STATUS COMMAND
و در ادامه هر رکورد یک پروسه نمایش داده شود.
func updateStatusToFinished(...): این تابع کمکی باید یک رکورد پروسه را دریافت کرده و وضعیت آن را در دیتابیس بهtypes.StatusFinishedتغییر دهد.
نکات
-
فایلهای
db.goوmain.goاز قبل آماده شدهاند و صرفا برای اجرا در محیط لوکال میتوانید آنها را تغییر دهید. -
تنها فایلهایی که نیاز به ویرایش دارند، فایلهای داخل پوشهی
cmd/هستند.
چه چیزی را آپلود کنید
پس از پیادهسازی ویژگیهای خواستهشده، فقط دایرکتوریهای cmd را فشرده کرده و به صورت یک فایل زیپ ارسال کنید.
ارسال پاسخ برای این سؤال